From 20cfd3f50b19d58e913baa697d16af1329589309 Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 29 Mar 2026 03:28:41 +0200 Subject: [PATCH] Clean up terra color picker reactive props --- src/routes/test/color-picker/+page.svelte | 2 +- .../terra/color-picker/color-picker.svelte.ts | 55 ++++++++++++------- .../components/color-picker-input.svelte | 9 ++- .../components/color-picker-root.svelte | 11 ++-- .../components/color-picker-swatches.svelte | 8 ++- 5 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/routes/test/color-picker/+page.svelte b/src/routes/test/color-picker/+page.svelte index a9aa943a5..5dff23196 100644 --- a/src/routes/test/color-picker/+page.svelte +++ b/src/routes/test/color-picker/+page.svelte @@ -23,7 +23,7 @@ let activeFormat = $state<"hex" | "rgb" | "hsl">("hex"); -
+

ColorPicker

Headless, composable, accessible. Part of Bits UI.

diff --git a/src/uix/terra/color-picker/color-picker.svelte.ts b/src/uix/terra/color-picker/color-picker.svelte.ts index 286046817..5f142f59e 100644 --- a/src/uix/terra/color-picker/color-picker.svelte.ts +++ b/src/uix/terra/color-picker/color-picker.svelte.ts @@ -20,6 +20,23 @@ import type { } from "./types"; import { clamp } from '$lib'; +type ColorPickerRootStateProps = { + value: Active; + defaultValue: Active; + onValueChange: Active<((value: ColorValue) => void) | undefined>; + disabled: Active; + format: Active; +}; + +type ColorPickerInputStateProps = { + format: Active; +}; + +type ColorPickerSwatchesStateProps = { + colors: Active; + onSelect: Active<((color: string) => void) | undefined>; +}; + // ─── Root State ─────────────────────────────────────────────────────────────── export class ColorPickerRootState { @@ -37,15 +54,15 @@ export class ColorPickerRootState { readonly disabled: Active; readonly format: Active; - readonly #onValueChange: ((v: ColorValue) => void) | undefined; + readonly #onValueChange: Active<((v: ColorValue) => void) | undefined>; - constructor(props: ColorPickerRootProps) { - const initial = props.defaultValue ?? props.value ?? DEFAULT_COLOR; + constructor(props: ColorPickerRootStateProps) { + const initial = props.defaultValue.current ?? props.value.current ?? DEFAULT_COLOR; - this.#hsv = state(initial.hsv); + this.#hsv = state(initial.hsv); this.#onValueChange = props.onValueChange; - this.disabled = readableActive(() => props.disabled ?? false); - this.format = readableActive(() => props.format ?? "hex"); + this.disabled = props.disabled; + this.format = props.format; this.value = readableActive(() => colorValueFromHsv(this.#hsv.current)); this.hex = readableActive(() => hsvToHex(this.#hsv.current)); @@ -58,7 +75,7 @@ export class ColorPickerRootState { setHsv(hsv: Partial) { const next = { ...this.#hsv.current, ...hsv }; this.#hsv.current = next; - this.#onValueChange?.(colorValueFromHsv(next)); + this.#onValueChange.current?.(colorValueFromHsv(next)); } setHue(h: number) { @@ -77,18 +94,18 @@ export class ColorPickerRootState { const hsv = parseColor(css); if (!hsv) return false; this.#hsv.current = hsv; - this.#onValueChange?.(colorValueFromHsv(hsv)); + this.#onValueChange.current?.(colorValueFromHsv(hsv)); return true; } setFromColorValue(color: ColorValue) { this.#hsv.current = color.hsv; - this.#onValueChange?.(color); + this.#onValueChange.current?.(color); } // ─── Factory ───────────────────────────────────────────────────────────── - static create(props: ColorPickerRootProps) { + static create(props: ColorPickerRootStateProps) { return ColorPickerRootState.ctx.set(new ColorPickerRootState(props)); } @@ -221,7 +238,7 @@ export class ColorPickerAlphaSliderState { export class ColorPickerInputState { readonly #root: ColorPickerRootState; - readonly format: ColorFormat; + readonly format: Active; // Displayed string — formatted according to `format` readonly displayValue: Active; @@ -231,13 +248,13 @@ export class ColorPickerInputState { readonly inputValue: Active; - constructor(props: ColorPickerInputProps) { + constructor(props: ColorPickerInputStateProps) { this.#root = ColorPickerRootState.get(); this.format = props.format; this.displayValue = readableActive(() => { const color = this.#root.value.current; - switch (this.format) { + switch (this.format.current) { case "hex": return color.hex; case "rgb": { const { r, g, b, a } = color.rgb; @@ -275,7 +292,7 @@ export class ColorPickerInputState { if (e.key === "Escape") this.#editBuffer = null; } - static create(props: ColorPickerInputProps) { + static create(props: ColorPickerInputStateProps) { return new ColorPickerInputState(props); } } @@ -284,10 +301,10 @@ export class ColorPickerInputState { export class ColorPickerSwatchesState { readonly #root: ColorPickerRootState; - readonly #onSelect: ((color: string) => void) | undefined; - readonly colors: string[]; + readonly #onSelect: Active<((color: string) => void) | undefined>; + readonly colors: Active; - constructor(props: ColorPickerSwatchesProps) { + constructor(props: ColorPickerSwatchesStateProps) { this.#root = ColorPickerRootState.get(); this.colors = props.colors; this.#onSelect = props.onSelect; @@ -295,7 +312,7 @@ export class ColorPickerSwatchesState { selectSwatch(color: string) { const success = this.#root.setFromString(color); - if (success) this.#onSelect?.(color); + if (success) this.#onSelect.current?.(color); } isSelected(color: string): boolean { @@ -305,7 +322,7 @@ export class ColorPickerSwatchesState { return hsvToHex(hsv) === current; } - static create(props: ColorPickerSwatchesProps) { + static create(props: ColorPickerSwatchesStateProps) { return new ColorPickerSwatchesState(props); } } diff --git a/src/uix/terra/color-picker/components/color-picker-input.svelte b/src/uix/terra/color-picker/components/color-picker-input.svelte index bc73cdb8a..3bd35e442 100644 --- a/src/uix/terra/color-picker/components/color-picker-input.svelte +++ b/src/uix/terra/color-picker/components/color-picker-input.svelte @@ -1,17 +1,22 @@ input.handleInput(e.currentTarget.value)} diff --git a/src/uix/terra/color-picker/components/color-picker-root.svelte b/src/uix/terra/color-picker/components/color-picker-root.svelte index f4668bd5c..98030dec9 100644 --- a/src/uix/terra/color-picker/components/color-picker-root.svelte +++ b/src/uix/terra/color-picker/components/color-picker-root.svelte @@ -1,4 +1,5 @@ diff --git a/src/uix/terra/color-picker/components/color-picker-swatches.svelte b/src/uix/terra/color-picker/components/color-picker-swatches.svelte index b71440709..9d0d3c238 100644 --- a/src/uix/terra/color-picker/components/color-picker-swatches.svelte +++ b/src/uix/terra/color-picker/components/color-picker-swatches.svelte @@ -1,11 +1,15 @@
- {#each swatches.colors as color (color)} + {#each swatches.colors.current as color (color)}