@zag-js/color-picker 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,8 +20,6 @@ export const dom = createScope({
20
20
 
21
21
  getChannelSliderId: (ctx: Ctx, channel: ColorChannel) =>
22
22
  ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
23
- getChannelInputId: (ctx: Ctx, channel: string) =>
24
- ctx.ids?.channelInput?.(channel) ?? `color-picker:${ctx.id}:input:${channel}`,
25
23
  getChannelSliderThumbId: (ctx: Ctx, channel: ColorChannel) =>
26
24
  ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
27
25
 
@@ -29,8 +27,12 @@ export const dom = createScope({
29
27
  getAreaThumbEl: (ctx: Ctx) => dom.getById(ctx, dom.getAreaThumbId(ctx)),
30
28
  getChannelSliderThumbEl: (ctx: Ctx, channel: ColorChannel) =>
31
29
  dom.getById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
32
- getChannelInputEl: (ctx: Ctx, channel: string) =>
33
- dom.getById<HTMLInputElement>(ctx, dom.getChannelInputId(ctx, channel)),
30
+ getChannelInputEl: (ctx: Ctx, channel: string): HTMLInputElement[] => {
31
+ return [
32
+ ...queryAll<HTMLInputElement>(dom.getContentEl(ctx), `input[data-channel="${channel}"]`),
33
+ ...queryAll<HTMLInputElement>(dom.getControlEl(ctx), `input[data-channel="${channel}"]`),
34
+ ]
35
+ },
34
36
 
35
37
  getHiddenInputEl: (ctx: Ctx) => dom.getById<HTMLInputElement>(ctx, dom.getHiddenInputId(ctx)),
36
38
  getAreaEl: (ctx: Ctx) => dom.getById(ctx, dom.getAreaId(ctx)),
@@ -1,5 +1,5 @@
1
1
  import { parseColor, type Color } from "@zag-js/color-utils"
2
- import { createMachine, guards, ref } from "@zag-js/core"
2
+ import { createMachine } from "@zag-js/core"
3
3
  import { trackDismissableElement } from "@zag-js/dismissable"
4
4
  import { trackPointerMove } from "@zag-js/dom-event"
5
5
  import { raf } from "@zag-js/dom-query"
@@ -18,8 +18,6 @@ import type {
18
18
  } from "./color-picker.types"
19
19
  import { getChannelValue } from "./utils/get-channel-input-value"
20
20
 
21
- const { stateIn } = guards
22
-
23
21
  export function machine(userContext: UserDefinedContext) {
24
22
  const ctx = compact(userContext)
25
23
  return createMachine<MachineContext, MachineState>(
@@ -55,7 +53,7 @@ export function machine(userContext: UserDefinedContext) {
55
53
  activities: ["trackFormControl"],
56
54
 
57
55
  watch: {
58
- valueAsString: ["syncInputElements"],
56
+ value: ["syncInputElements"],
59
57
  open: ["toggleVisibility"],
60
58
  },
61
59
 
@@ -63,26 +61,6 @@ export function machine(userContext: UserDefinedContext) {
63
61
  "VALUE.SET": {
64
62
  actions: ["setValue"],
65
63
  },
66
- "CHANNEL_INPUT.FOCUS": [
67
- {
68
- guard: stateIn("idle"),
69
- target: "focused",
70
- actions: ["setActiveChannel"],
71
- },
72
- {
73
- actions: ["setActiveChannel"],
74
- },
75
- ],
76
- "CHANNEL_INPUT.BLUR": [
77
- {
78
- guard: stateIn("focused"),
79
- target: "idle",
80
- actions: ["setChannelColorFromInput"],
81
- },
82
- {
83
- actions: ["setChannelColorFromInput"],
84
- },
85
- ],
86
64
  "CHANNEL_INPUT.CHANGE": {
87
65
  actions: ["setChannelColorFromInput"],
88
66
  },
@@ -100,6 +78,10 @@ export function machine(userContext: UserDefinedContext) {
100
78
  target: "open",
101
79
  actions: ["setInitialFocus", "invokeOnOpen"],
102
80
  },
81
+ "CHANNEL_INPUT.FOCUS": {
82
+ target: "focused",
83
+ actions: ["setActiveChannel"],
84
+ },
103
85
  },
104
86
  },
105
87
 
@@ -114,6 +96,13 @@ export function machine(userContext: UserDefinedContext) {
114
96
  target: "open",
115
97
  actions: ["setInitialFocus", "invokeOnOpen"],
116
98
  },
99
+ "CHANNEL_INPUT.FOCUS": {
100
+ actions: ["setActiveChannel"],
101
+ },
102
+ "CHANNEL_INPUT.BLUR": {
103
+ target: "idle",
104
+ actions: ["setChannelColorFromInput"],
105
+ },
117
106
  },
118
107
  },
119
108
 
@@ -184,6 +173,9 @@ export function machine(userContext: UserDefinedContext) {
184
173
  "CHANNEL_SLIDER.END": {
185
174
  actions: ["setChannelToMax"],
186
175
  },
176
+ "CHANNEL_INPUT.BLUR": {
177
+ actions: ["setChannelColorFromInput"],
178
+ },
187
179
  INTERACT_OUTSIDE: [
188
180
  {
189
181
  guard: "shouldRestoreFocus",
@@ -367,26 +359,29 @@ export function machine(userContext: UserDefinedContext) {
367
359
  },
368
360
  setChannelColorFromInput(ctx, evt) {
369
361
  const { channel, isTextField, value } = evt
362
+ const currentAlpha = ctx.value.getChannelValue("alpha")
370
363
 
371
364
  // handle alpha channel
372
365
  if (channel === "alpha") {
373
- const newColor = ctx.value.withChannelValue("alpha", parseFloat(value))
366
+ let valueAsNumber = parseFloat(value)
367
+ valueAsNumber = Number.isNaN(valueAsNumber) ? currentAlpha : valueAsNumber
368
+ const newColor = ctx.value.withChannelValue("alpha", valueAsNumber)
374
369
  set.value(ctx, newColor)
375
370
  return
376
371
  }
377
372
 
378
373
  // handle other text channels
379
374
  if (isTextField) {
380
- const currentAlpha = ctx.value.getChannelValue("alpha")
381
-
382
375
  const color = tryCatch(
383
376
  () => parse(value).withChannelValue("alpha", currentAlpha),
384
377
  () => ctx.value,
385
378
  )
386
379
 
387
380
  // set channel input value immediately (in event user types native css color, we need to convert it to the current channel format)
388
- const inputEl = dom.getChannelInputEl(ctx, channel)
389
- dom.setValue(inputEl, getChannelValue(color, channel))
381
+ const inputEls = dom.getChannelInputEl(ctx, channel)
382
+ inputEls.forEach((inputEl) => {
383
+ dom.setValue(inputEl, getChannelValue(color, channel))
384
+ })
390
385
 
391
386
  set.value(ctx, color)
392
387
  return
@@ -501,7 +496,6 @@ const invoke = {
501
496
 
502
497
  const set = {
503
498
  value(ctx: MachineContext, color: Color | ColorType | undefined) {
504
- sync.inputs(ctx)
505
499
  if (!color || ctx.value.isEqual(color)) return
506
500
  const currentFormat = ctx.value.getFormat()
507
501
  const outputColor = color.toFormat(currentFormat)
@@ -509,7 +503,7 @@ const set = {
509
503
  outputColor.outputFormat = ctx.value.outputFormat
510
504
  } catch {}
511
505
 
512
- ctx.value = ref(outputColor) as Color
506
+ ctx.value = outputColor
513
507
  invoke.change(ctx)
514
508
  },
515
509
  }
@@ -1,14 +1,13 @@
1
1
  import { parseColor, type Color } from "@zag-js/color-utils"
2
- import { ref } from "@zag-js/core"
3
2
 
4
3
  export const parse = (color: string): Color => {
5
4
  const value = parseColor(color)
6
5
 
7
6
  const colorFormat = value.getFormat()
8
- const lockedFormat = colorFormat.startsWith("hsl") ? "hsla" : "hsba"
7
+ const lockedFormat = colorFormat === "hsla" ? "hsla" : "hsba"
9
8
 
10
9
  const result = value.toFormat(lockedFormat)
11
10
  result.outputFormat = colorFormat
12
11
 
13
- return ref(result)
12
+ return result
14
13
  }
@@ -217,14 +217,10 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
217
217
  * The current color value (as a Color object)
218
218
  */
219
219
  valueAsString: string
220
- /**
221
- * The current color channels of the color
222
- */
223
- channels: [ColorChannel, ColorChannel, ColorChannel]
224
220
  /**
225
221
  * Function to set the color value
226
222
  */
227
- setColor(value: string | Color): void
223
+ setValue(value: string | Color): void
228
224
  /**
229
225
  * Function to set the color value
230
226
  */
@@ -16,7 +16,7 @@ export function getChannelValue(color: Color, channel: ExtendedColorChannel | nu
16
16
  return color.getChannelValue(channel).toString()
17
17
  }
18
18
 
19
- const isHSL = color.getFormat() === "hsl"
19
+ const isHSL = color.getFormat() === "hsla"
20
20
 
21
21
  switch (channel) {
22
22
  case "hue":