@zag-js/color-picker 0.56.1 → 0.58.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.
@@ -6,18 +6,18 @@ import type { MachineContext as Ctx } from "./color-picker.types"
6
6
  export const dom = createScope({
7
7
  getRootId: (ctx: Ctx) => ctx.ids?.root ?? `color-picker:${ctx.id}`,
8
8
  getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `color-picker:${ctx.id}:label`,
9
- getHiddenInputId: (ctx: Ctx) => `color-picker:${ctx.id}:hidden-input`,
9
+ getHiddenInputId: (ctx: Ctx) => ctx.ids?.hiddenInput ?? `color-picker:${ctx.id}:hidden-input`,
10
10
  getControlId: (ctx: Ctx) => ctx.ids?.control ?? `color-picker:${ctx.id}:control`,
11
11
  getTriggerId: (ctx: Ctx) => ctx.ids?.trigger ?? `color-picker:${ctx.id}:trigger`,
12
12
  getContentId: (ctx: Ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`,
13
- getPositionerId: (ctx: Ctx) => `color-picker:${ctx.id}:positioner`,
14
- getFormatSelectId: (ctx: Ctx) => `color-picker:${ctx.id}:format-select`,
13
+ getPositionerId: (ctx: Ctx) => ctx.ids?.positioner ?? `color-picker:${ctx.id}:positioner`,
14
+ getFormatSelectId: (ctx: Ctx) => ctx.ids?.formatSelect ?? `color-picker:${ctx.id}:format-select`,
15
15
 
16
16
  getAreaId: (ctx: Ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`,
17
17
  getAreaGradientId: (ctx: Ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`,
18
18
  getAreaThumbId: (ctx: Ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`,
19
19
 
20
- getChannelSliderId: (ctx: Ctx, channel: ColorChannel) =>
20
+ getChannelSliderTrackId: (ctx: Ctx, channel: ColorChannel) =>
21
21
  ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
22
22
  getChannelSliderThumbId: (ctx: Ctx, channel: ColorChannel) =>
23
23
  ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
@@ -27,9 +27,10 @@ export const dom = createScope({
27
27
  getChannelSliderThumbEl: (ctx: Ctx, channel: ColorChannel) =>
28
28
  dom.getById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
29
29
  getChannelInputEl: (ctx: Ctx, channel: string): HTMLInputElement[] => {
30
+ const selector = `input[data-channel="${channel}"]`
30
31
  return [
31
- ...queryAll<HTMLInputElement>(dom.getContentEl(ctx), `input[data-channel="${channel}"]`),
32
- ...queryAll<HTMLInputElement>(dom.getControlEl(ctx), `input[data-channel="${channel}"]`),
32
+ ...queryAll<HTMLInputElement>(dom.getContentEl(ctx), selector),
33
+ ...queryAll<HTMLInputElement>(dom.getControlEl(ctx), selector),
33
34
  ]
34
35
  },
35
36
  getFormatSelectEl: (ctx: Ctx) => dom.getById<HTMLSelectElement>(ctx, dom.getFormatSelectId(ctx)),
@@ -47,7 +48,7 @@ export const dom = createScope({
47
48
  getTriggerEl: (ctx: Ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
48
49
  getPositionerEl: (ctx: Ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
49
50
  getChannelSliderTrackEl: (ctx: Ctx, channel: ColorChannel) => {
50
- return dom.getById(ctx, dom.getChannelSliderId(ctx, channel))
51
+ return dom.getById(ctx, dom.getChannelSliderTrackId(ctx, channel))
51
52
  },
52
53
  getChannelSliderValueFromPoint(ctx: Ctx, point: Point, channel: ColorChannel) {
53
54
  const trackEl = dom.getChannelSliderTrackEl(ctx, channel)
@@ -193,22 +193,22 @@ export function machine(userContext: UserDefinedContext) {
193
193
  actions: ["setActiveChannel"],
194
194
  },
195
195
  "AREA.ARROW_LEFT": {
196
- actions: ["decrementXChannel"],
196
+ actions: ["decrementAreaXChannel"],
197
197
  },
198
198
  "AREA.ARROW_RIGHT": {
199
- actions: ["incrementXChannel"],
199
+ actions: ["incrementAreaXChannel"],
200
200
  },
201
201
  "AREA.ARROW_UP": {
202
- actions: ["incrementYChannel"],
202
+ actions: ["incrementAreaYChannel"],
203
203
  },
204
204
  "AREA.ARROW_DOWN": {
205
- actions: ["decrementYChannel"],
205
+ actions: ["decrementAreaYChannel"],
206
206
  },
207
207
  "AREA.PAGE_UP": {
208
- actions: ["incrementXChannel"],
208
+ actions: ["incrementAreaXChannel"],
209
209
  },
210
210
  "AREA.PAGE_DOWN": {
211
- actions: ["decrementXChannel"],
211
+ actions: ["decrementAreaXChannel"],
212
212
  },
213
213
  "CHANNEL_SLIDER.ARROW_LEFT": {
214
214
  actions: ["decrementChannel"],
@@ -384,11 +384,11 @@ export function machine(userContext: UserDefinedContext) {
384
384
  },
385
385
  })
386
386
  },
387
- trackPointerMove(ctx, _evt, { send }) {
387
+ trackPointerMove(ctx, evt, { send }) {
388
388
  return trackPointerMove(dom.getDoc(ctx), {
389
389
  onPointerMove({ point }) {
390
390
  const type = ctx.activeId === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE"
391
- send({ type, point })
391
+ send({ type, point, format: evt.format })
392
392
  },
393
393
  onPointerUp() {
394
394
  const type = ctx.activeId === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP"
@@ -427,19 +427,21 @@ export function machine(userContext: UserDefinedContext) {
427
427
  ctx.activeOrientation = null
428
428
  },
429
429
  setAreaColorFromPoint(ctx, evt) {
430
+ const normalizedValue = evt.format ? ctx.value.toFormat(evt.format) : ctx.areaValue
430
431
  const { xChannel, yChannel } = evt.channel || ctx.activeChannel
431
432
 
432
433
  const percent = dom.getAreaValueFromPoint(ctx, evt.point)
433
434
  if (!percent) return
434
435
 
435
- const xValue = ctx.areaValue.getChannelPercentValue(xChannel, percent.x)
436
- const yValue = ctx.areaValue.getChannelPercentValue(yChannel, 1 - percent.y)
436
+ const xValue = normalizedValue.getChannelPercentValue(xChannel, percent.x)
437
+ const yValue = normalizedValue.getChannelPercentValue(yChannel, 1 - percent.y)
437
438
 
438
- const color = ctx.areaValue.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue)
439
+ const color = normalizedValue.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue)
439
440
  set.value(ctx, color)
440
441
  },
441
442
  setChannelColorFromPoint(ctx, evt) {
442
443
  const channel = evt.channel || ctx.activeId
444
+ const normalizedValue = evt.format ? ctx.value.toFormat(evt.format) : ctx.areaValue
443
445
 
444
446
  const percent = dom.getChannelSliderValueFromPoint(ctx, evt.point, channel)
445
447
  if (!percent) return
@@ -447,8 +449,8 @@ export function machine(userContext: UserDefinedContext) {
447
449
  const orientation = ctx.activeOrientation || "horizontal"
448
450
  const channelPercent = orientation === "horizontal" ? percent.x : percent.y
449
451
 
450
- const value = ctx.areaValue.getChannelPercentValue(channel, channelPercent)
451
- const color = ctx.areaValue.withChannelValue(channel, value)
452
+ const value = normalizedValue.getChannelPercentValue(channel, channelPercent)
453
+ const color = normalizedValue.withChannelValue(channel, value)
452
454
  set.value(ctx, color)
453
455
  },
454
456
  setValue(ctx, evt) {
@@ -506,22 +508,22 @@ export function machine(userContext: UserDefinedContext) {
506
508
  const color = ctx.value.decrementChannel(evt.channel, evt.step)
507
509
  set.value(ctx, color)
508
510
  },
509
- incrementXChannel(ctx, evt) {
511
+ incrementAreaXChannel(ctx, evt) {
510
512
  const { xChannel } = evt.channel
511
513
  const color = ctx.areaValue.incrementChannel(xChannel, evt.step)
512
514
  set.value(ctx, color)
513
515
  },
514
- decrementXChannel(ctx, evt) {
516
+ decrementAreaXChannel(ctx, evt) {
515
517
  const { xChannel } = evt.channel
516
518
  const color = ctx.areaValue.decrementChannel(xChannel, evt.step)
517
519
  set.value(ctx, color)
518
520
  },
519
- incrementYChannel(ctx, evt) {
521
+ incrementAreaYChannel(ctx, evt) {
520
522
  const { yChannel } = evt.channel
521
523
  const color = ctx.areaValue.incrementChannel(yChannel, evt.step)
522
524
  set.value(ctx, color)
523
525
  },
524
- decrementYChannel(ctx, evt) {
526
+ decrementAreaYChannel(ctx, evt) {
525
527
  const { yChannel } = evt.channel
526
528
  const color = ctx.areaValue.decrementChannel(yChannel, evt.step)
527
529
  set.value(ctx, color)
@@ -30,9 +30,11 @@ export const props = createProps<UserDefinedContext>()([
30
30
  "open.controlled",
31
31
  "open",
32
32
  "positioning",
33
+ "required",
33
34
  "readOnly",
34
35
  "value",
35
36
  ])
37
+
36
38
  export const splitProps = createSplitProps<Partial<UserDefinedContext>>(props)
37
39
 
38
40
  export const areaProps = createProps<AreaProps>()(["xChannel", "yChannel"])
@@ -1,5 +1,5 @@
1
1
  import type { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from "@zag-js/color-utils"
2
- import type { StateMachine as S } from "@zag-js/core"
2
+ import type { Machine, StateMachine as S } from "@zag-js/core"
3
3
  import type { InteractOutsideHandlers } from "@zag-js/dismissable"
4
4
  import type { PositioningOptions } from "@zag-js/popper"
5
5
  import type { CommonProperties, DirectionProperty, Orientation, PropTypes, RequiredBy } from "@zag-js/types"
@@ -45,9 +45,12 @@ export type ElementIds = Partial<{
45
45
  trigger: string
46
46
  label: string
47
47
  input: string
48
+ hiddenInput: string
48
49
  content: string
49
50
  area: string
50
51
  areaGradient: string
52
+ positioner: string
53
+ formatSelect: string
51
54
  areaThumb: string
52
55
  channelInput(id: string): string
53
56
  channelSliderTrack(id: ColorChannel): string
@@ -72,6 +75,10 @@ interface PublicContext extends CommonProperties, DirectionProperty, InteractOut
72
75
  * Whether the color picker is read-only
73
76
  */
74
77
  readOnly?: boolean
78
+ /**
79
+ * Whether the color picker is required
80
+ */
81
+ required?: boolean
75
82
  /**
76
83
  * Handler that is called when the value changes, as the user drags.
77
84
  */
@@ -194,6 +201,8 @@ export type State = S.State<MachineContext, MachineState>
194
201
 
195
202
  export type Send = S.Send<S.AnyEventObject>
196
203
 
204
+ export type Service = Machine<MachineContext, MachineState, S.AnyEventObject>
205
+
197
206
  /* -----------------------------------------------------------------------------
198
207
  * Component API
199
208
  * -----------------------------------------------------------------------------*/
@@ -203,6 +212,10 @@ export interface ChannelProps {
203
212
  orientation?: Orientation
204
213
  }
205
214
 
215
+ export interface ChannelSliderProps extends ChannelProps {
216
+ format?: ColorFormat
217
+ }
218
+
206
219
  export interface ChannelInputProps {
207
220
  channel: ExtendedColorChannel
208
221
  orientation?: Orientation
@@ -271,6 +284,10 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
271
284
  * Function to set the color value
272
285
  */
273
286
  getChannelValue(channel: ColorChannel): string
287
+ /**
288
+ * Function to get the formatted and localized value of a specific channel
289
+ */
290
+ getChannelValueText(channel: ColorChannel, locale: string): string
274
291
  /**
275
292
  * Function to set the color value of a specific channel
276
293
  */
@@ -308,11 +325,14 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
308
325
  getAreaBackgroundProps(props?: AreaProps): T["element"]
309
326
  getAreaThumbProps(props?: AreaProps): T["element"]
310
327
 
311
- getChannelSliderProps(props: ChannelProps): T["element"]
312
- getChannelSliderTrackProps(props: ChannelProps): T["element"]
313
- getChannelSliderThumbProps(props: ChannelProps): T["element"]
314
328
  getChannelInputProps(props: ChannelInputProps): T["input"]
315
329
 
330
+ getChannelSliderProps(props: ChannelSliderProps): T["element"]
331
+ getChannelSliderTrackProps(props: ChannelSliderProps): T["element"]
332
+ getChannelSliderThumbProps(props: ChannelSliderProps): T["element"]
333
+ getChannelSliderLabelProps(props: ChannelProps): T["element"]
334
+ getChannelSliderValueTextProps(props: ChannelProps): T["element"]
335
+
316
336
  getTransparencyGridProps(props?: TransparencyGridProps): T["element"]
317
337
 
318
338
  getEyeDropperTriggerProps(): T["button"]
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export { parse } from "./color-picker.parse"
6
6
  export type {
7
7
  MachineApi as Api,
8
8
  AreaProps,
9
+ ChannelSliderProps,
9
10
  ChannelInputProps,
10
11
  ChannelProps,
11
12
  Color,
@@ -23,4 +24,5 @@ export type {
23
24
  SwatchTriggerState,
24
25
  TransparencyGridProps,
25
26
  ValueChangeDetails,
27
+ Service,
26
28
  } from "./color-picker.types"