@zag-js/color-picker 0.46.0 → 0.48.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.
package/dist/index.d.mts CHANGED
@@ -11,6 +11,20 @@ import { MaybeFunction } from '@zag-js/utils';
11
11
  declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparencyGrid" | "swatchGroup" | "swatchTrigger" | "swatchIndicator" | "swatch" | "eyeDropperTrigger" | "formatTrigger" | "formatSelect">;
12
12
 
13
13
  type ExtendedColorChannel = ColorChannel | "hex" | "css";
14
+ interface EyeDropper {
15
+ new (): EyeDropper;
16
+ open: (options?: {
17
+ signal?: AbortSignal;
18
+ }) => Promise<{
19
+ sRGBHex: string;
20
+ }>;
21
+ [Symbol.toStringTag]: "EyeDropper";
22
+ }
23
+ declare global {
24
+ interface Window {
25
+ EyeDropper: EyeDropper;
26
+ }
27
+ }
14
28
  interface ValueChangeDetails {
15
29
  value: Color;
16
30
  valueAsString: string;
@@ -164,8 +178,8 @@ interface SwatchTriggerProps {
164
178
  interface SwatchTriggerState {
165
179
  value: Color;
166
180
  valueAsString: string;
167
- isChecked: boolean;
168
- isDisabled: boolean;
181
+ checked: boolean;
182
+ disabled: boolean;
169
183
  }
170
184
  interface SwatchProps {
171
185
  /**
@@ -184,11 +198,11 @@ interface MachineApi<T extends PropTypes = PropTypes> {
184
198
  /**
185
199
  * Whether the color picker is being dragged
186
200
  */
187
- isDragging: boolean;
201
+ dragging: boolean;
188
202
  /**
189
203
  * Whether the color picker is open
190
204
  */
191
- isOpen: boolean;
205
+ open: boolean;
192
206
  /**
193
207
  * The current color value (as a string)
194
208
  */
@@ -226,13 +240,9 @@ interface MachineApi<T extends PropTypes = PropTypes> {
226
240
  */
227
241
  setAlpha(value: number): void;
228
242
  /**
229
- * Function to open the color picker
230
- */
231
- open(): void;
232
- /**
233
- * Function to close the color picker
243
+ * Function to open or close the color picker
234
244
  */
235
- close(): void;
245
+ setOpen(open: boolean): void;
236
246
  rootProps: T["element"];
237
247
  labelProps: T["element"];
238
248
  controlProps: T["element"];
package/dist/index.d.ts CHANGED
@@ -11,6 +11,20 @@ import { MaybeFunction } from '@zag-js/utils';
11
11
  declare const anatomy: _zag_js_anatomy.Anatomy<"root" | "label" | "control" | "trigger" | "positioner" | "content" | "area" | "areaThumb" | "areaBackground" | "channelSlider" | "channelSliderTrack" | "channelSliderThumb" | "channelInput" | "transparencyGrid" | "swatchGroup" | "swatchTrigger" | "swatchIndicator" | "swatch" | "eyeDropperTrigger" | "formatTrigger" | "formatSelect">;
12
12
 
13
13
  type ExtendedColorChannel = ColorChannel | "hex" | "css";
14
+ interface EyeDropper {
15
+ new (): EyeDropper;
16
+ open: (options?: {
17
+ signal?: AbortSignal;
18
+ }) => Promise<{
19
+ sRGBHex: string;
20
+ }>;
21
+ [Symbol.toStringTag]: "EyeDropper";
22
+ }
23
+ declare global {
24
+ interface Window {
25
+ EyeDropper: EyeDropper;
26
+ }
27
+ }
14
28
  interface ValueChangeDetails {
15
29
  value: Color;
16
30
  valueAsString: string;
@@ -164,8 +178,8 @@ interface SwatchTriggerProps {
164
178
  interface SwatchTriggerState {
165
179
  value: Color;
166
180
  valueAsString: string;
167
- isChecked: boolean;
168
- isDisabled: boolean;
181
+ checked: boolean;
182
+ disabled: boolean;
169
183
  }
170
184
  interface SwatchProps {
171
185
  /**
@@ -184,11 +198,11 @@ interface MachineApi<T extends PropTypes = PropTypes> {
184
198
  /**
185
199
  * Whether the color picker is being dragged
186
200
  */
187
- isDragging: boolean;
201
+ dragging: boolean;
188
202
  /**
189
203
  * Whether the color picker is open
190
204
  */
191
- isOpen: boolean;
205
+ open: boolean;
192
206
  /**
193
207
  * The current color value (as a string)
194
208
  */
@@ -226,13 +240,9 @@ interface MachineApi<T extends PropTypes = PropTypes> {
226
240
  */
227
241
  setAlpha(value: number): void;
228
242
  /**
229
- * Function to open the color picker
230
- */
231
- open(): void;
232
- /**
233
- * Function to close the color picker
243
+ * Function to open or close the color picker
234
244
  */
235
- close(): void;
245
+ setOpen(open: boolean): void;
236
246
  rootProps: T["element"];
237
247
  labelProps: T["element"];
238
248
  controlProps: T["element"];
package/dist/index.js CHANGED
@@ -59,7 +59,6 @@ var import_color_utils3 = require("@zag-js/color-utils");
59
59
  var import_dom_event2 = require("@zag-js/dom-event");
60
60
  var import_dom_query2 = require("@zag-js/dom-query");
61
61
  var import_popper = require("@zag-js/popper");
62
- var import_visually_hidden = require("@zag-js/visually-hidden");
63
62
 
64
63
  // src/color-picker.dom.ts
65
64
  var import_dom_event = require("@zag-js/dom-event");
@@ -250,11 +249,11 @@ function connect(state, send, normalize) {
250
249
  const value = state.context.value;
251
250
  const areaValue = state.context.areaValue;
252
251
  const valueAsString = state.context.valueAsString;
253
- const isDisabled = state.context.isDisabled;
254
- const isInteractive = state.context.isInteractive;
255
- const isDragging = state.hasTag("dragging");
256
- const isOpen = state.hasTag("open");
257
- const isFocused = state.hasTag("focused");
252
+ const disabled = state.context.isDisabled;
253
+ const interactive = state.context.isInteractive;
254
+ const dragging = state.hasTag("dragging");
255
+ const open = state.hasTag("open");
256
+ const focused = state.hasTag("focused");
258
257
  const getAreaChannels = (props) => {
259
258
  const channels = areaValue.getChannels();
260
259
  return {
@@ -272,20 +271,19 @@ function connect(state, send, normalize) {
272
271
  return {
273
272
  value: color,
274
273
  valueAsString: color.toString("hex"),
275
- isChecked: color.isEqual(value),
276
- isDisabled: props.disabled || !isInteractive
274
+ checked: color.isEqual(value),
275
+ disabled: props.disabled || !interactive
277
276
  };
278
277
  }
279
278
  return {
280
- isDragging,
281
- isOpen,
279
+ dragging,
280
+ open,
282
281
  valueAsString,
283
282
  value,
284
- open() {
285
- send({ type: "OPEN" });
286
- },
287
- close() {
288
- send({ type: "CLOSE" });
283
+ setOpen(_open) {
284
+ if (_open === open)
285
+ return;
286
+ send({ type: _open ? "OPEN" : "CLOSE" });
289
287
  },
290
288
  setValue(value2) {
291
289
  send({ type: "VALUE.SET", value: (0, import_color_utils3.normalizeColor)(value2), src: "set-color" });
@@ -311,7 +309,7 @@ function connect(state, send, normalize) {
311
309
  ...parts.root.attrs,
312
310
  dir: state.context.dir,
313
311
  id: dom.getRootId(state.context),
314
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
312
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
315
313
  "data-readonly": (0, import_dom_query2.dataAttr)(state.context.readOnly),
316
314
  style: {
317
315
  "--value": value.toString("css")
@@ -322,9 +320,9 @@ function connect(state, send, normalize) {
322
320
  dir: state.context.dir,
323
321
  id: dom.getLabelId(state.context),
324
322
  htmlFor: dom.getHiddenInputId(state.context),
325
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
323
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
326
324
  "data-readonly": (0, import_dom_query2.dataAttr)(state.context.readOnly),
327
- "data-focus": (0, import_dom_query2.dataAttr)(isFocused),
325
+ "data-focus": (0, import_dom_query2.dataAttr)(focused),
328
326
  onClick(event) {
329
327
  event.preventDefault();
330
328
  const inputEl = (0, import_dom_query2.query)(dom.getControlEl(state.context), "[data-channel=hex]");
@@ -335,33 +333,33 @@ function connect(state, send, normalize) {
335
333
  ...parts.control.attrs,
336
334
  id: dom.getControlId(state.context),
337
335
  dir: state.context.dir,
338
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
336
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
339
337
  "data-readonly": (0, import_dom_query2.dataAttr)(state.context.readOnly),
340
- "data-state": isOpen ? "open" : "closed",
341
- "data-focus": (0, import_dom_query2.dataAttr)(isFocused)
338
+ "data-state": open ? "open" : "closed",
339
+ "data-focus": (0, import_dom_query2.dataAttr)(focused)
342
340
  }),
343
341
  triggerProps: normalize.button({
344
342
  ...parts.trigger.attrs,
345
343
  id: dom.getTriggerId(state.context),
346
344
  dir: state.context.dir,
347
- disabled: isDisabled,
345
+ disabled,
348
346
  "aria-label": `select color. current color is ${valueAsString}`,
349
347
  "aria-controls": dom.getContentId(state.context),
350
348
  "aria-labelledby": dom.getLabelId(state.context),
351
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
349
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
352
350
  "data-readonly": (0, import_dom_query2.dataAttr)(state.context.readOnly),
353
351
  "data-placement": currentPlacement,
354
- "aria-expanded": (0, import_dom_query2.dataAttr)(isOpen),
355
- "data-state": isOpen ? "open" : "closed",
356
- "data-focus": (0, import_dom_query2.dataAttr)(isFocused),
352
+ "aria-expanded": (0, import_dom_query2.dataAttr)(open),
353
+ "data-state": open ? "open" : "closed",
354
+ "data-focus": (0, import_dom_query2.dataAttr)(focused),
357
355
  type: "button",
358
356
  onClick() {
359
- if (!isInteractive)
357
+ if (!interactive)
360
358
  return;
361
359
  send({ type: "TRIGGER.CLICK" });
362
360
  },
363
361
  onBlur() {
364
- if (!isInteractive)
362
+ if (!interactive)
365
363
  return;
366
364
  send({ type: "TRIGGER.BLUR" });
367
365
  },
@@ -380,8 +378,8 @@ function connect(state, send, normalize) {
380
378
  id: dom.getContentId(state.context),
381
379
  dir: state.context.dir,
382
380
  "data-placement": currentPlacement,
383
- "data-state": isOpen ? "open" : "closed",
384
- hidden: !isOpen
381
+ "data-state": open ? "open" : "closed",
382
+ hidden: !open
385
383
  }),
386
384
  getAreaProps(props = {}) {
387
385
  const { xChannel, yChannel } = getAreaChannels(props);
@@ -395,10 +393,10 @@ function connect(state, send, normalize) {
395
393
  id: dom.getAreaId(state.context),
396
394
  role: "group",
397
395
  onPointerDown(event) {
398
- if (!isInteractive)
396
+ if (!interactive)
399
397
  return;
400
398
  const evt = (0, import_dom_event2.getNativeEvent)(event);
401
- if (!(0, import_dom_event2.isLeftClick)(evt) || (0, import_dom_event2.isModifiedEvent)(evt))
399
+ if (!(0, import_dom_event2.isLeftClick)(evt) || (0, import_dom_event2.isModifierKey)(evt))
402
400
  return;
403
401
  const point = (0, import_dom_event2.getEventPoint)(evt);
404
402
  const channel = { xChannel, yChannel };
@@ -442,8 +440,8 @@ function connect(state, send, normalize) {
442
440
  ...parts.areaThumb.attrs,
443
441
  id: dom.getAreaThumbId(state.context),
444
442
  dir: state.context.dir,
445
- tabIndex: isDisabled ? void 0 : 0,
446
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
443
+ tabIndex: disabled ? void 0 : 0,
444
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
447
445
  role: "slider",
448
446
  "aria-valuemin": 0,
449
447
  "aria-valuemax": 100,
@@ -461,12 +459,14 @@ function connect(state, send, normalize) {
461
459
  background: areaValue.withChannelValue("alpha", 1).toString("css")
462
460
  },
463
461
  onFocus() {
464
- if (!isInteractive)
462
+ if (!interactive)
465
463
  return;
466
464
  send({ type: "AREA.FOCUS", id: "area", channel });
467
465
  },
468
466
  onKeyDown(event) {
469
- if (!isInteractive)
467
+ if (event.defaultPrevented)
468
+ return;
469
+ if (!interactive)
470
470
  return;
471
471
  const step = (0, import_dom_event2.getEventStep)(event);
472
472
  const keyMap = {
@@ -526,10 +526,10 @@ function connect(state, send, normalize) {
526
526
  "data-orientation": orientation,
527
527
  role: "presentation",
528
528
  onPointerDown(event) {
529
- if (!isInteractive)
529
+ if (!interactive)
530
530
  return;
531
531
  const evt = (0, import_dom_event2.getNativeEvent)(event);
532
- if (!(0, import_dom_event2.isLeftClick)(evt) || (0, import_dom_event2.isModifiedEvent)(evt))
532
+ if (!(0, import_dom_event2.isLeftClick)(evt) || (0, import_dom_event2.isModifierKey)(evt))
533
533
  return;
534
534
  const point = (0, import_dom_event2.getEventPoint)(evt);
535
535
  send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, point, id: channel, orientation });
@@ -572,11 +572,11 @@ function connect(state, send, normalize) {
572
572
  id: dom.getChannelSliderThumbId(state.context, channel),
573
573
  role: "slider",
574
574
  "aria-label": channel,
575
- tabIndex: isDisabled ? void 0 : 0,
575
+ tabIndex: disabled ? void 0 : 0,
576
576
  "data-channel": channel,
577
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
577
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
578
578
  "data-orientation": orientation,
579
- "aria-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
579
+ "aria-disabled": (0, import_dom_query2.dataAttr)(disabled),
580
580
  "aria-orientation": orientation,
581
581
  "aria-valuemax": maxValue,
582
582
  "aria-valuemin": minValue,
@@ -589,12 +589,14 @@ function connect(state, send, normalize) {
589
589
  ...placementStyles
590
590
  },
591
591
  onFocus() {
592
- if (!isInteractive)
592
+ if (!interactive)
593
593
  return;
594
594
  send({ type: "CHANNEL_SLIDER.FOCUS", channel });
595
595
  },
596
596
  onKeyDown(event) {
597
- if (!isInteractive)
597
+ if (event.defaultPrevented)
598
+ return;
599
+ if (!interactive)
598
600
  return;
599
601
  const step = (0, import_dom_event2.getEventStep)(event) * stepValue;
600
602
  const keyMap = {
@@ -646,15 +648,15 @@ function connect(state, send, normalize) {
646
648
  "aria-label": channel,
647
649
  spellCheck: false,
648
650
  autoComplete: "off",
649
- disabled: isDisabled,
650
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
651
+ disabled,
652
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
651
653
  readOnly: state.context.readOnly,
652
654
  defaultValue: getChannelValue(value, channel),
653
655
  min: range?.minValue,
654
656
  max: range?.maxValue,
655
657
  step: range?.step,
656
658
  onBeforeInput(event) {
657
- if (isTextField || !isInteractive)
659
+ if (isTextField || !interactive)
658
660
  return;
659
661
  const value2 = event.currentTarget.value;
660
662
  if (value2.match(/[^0-9.]/g)) {
@@ -662,19 +664,21 @@ function connect(state, send, normalize) {
662
664
  }
663
665
  },
664
666
  onFocus(event) {
665
- if (!isInteractive)
667
+ if (!interactive)
666
668
  return;
667
669
  send({ type: "CHANNEL_INPUT.FOCUS", channel });
668
670
  event.target.select();
669
671
  },
670
672
  onBlur(event) {
671
- if (!isInteractive)
673
+ if (!interactive)
672
674
  return;
673
675
  const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
674
676
  send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
675
677
  },
676
678
  onKeyDown(event) {
677
- if (!isInteractive)
679
+ if (event.defaultPrevented)
680
+ return;
681
+ if (!interactive)
678
682
  return;
679
683
  if (event.key === "Enter") {
680
684
  const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
@@ -691,21 +695,21 @@ function connect(state, send, normalize) {
691
695
  },
692
696
  hiddenInputProps: normalize.input({
693
697
  type: "text",
694
- disabled: isDisabled,
698
+ disabled,
695
699
  name: state.context.name,
696
700
  id: dom.getHiddenInputId(state.context),
697
- style: import_visually_hidden.visuallyHiddenStyle,
701
+ style: import_dom_query2.visuallyHiddenStyle,
698
702
  defaultValue: valueAsString
699
703
  }),
700
704
  eyeDropperTriggerProps: normalize.button({
701
705
  ...parts.eyeDropperTrigger.attrs,
702
706
  type: "button",
703
707
  dir: state.context.dir,
704
- disabled: isDisabled,
705
- "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
708
+ disabled,
709
+ "data-disabled": (0, import_dom_query2.dataAttr)(disabled),
706
710
  "aria-label": "Pick a color from the screen",
707
711
  onClick() {
708
- if (!isInteractive)
712
+ if (!interactive)
709
713
  return;
710
714
  send("EYEDROPPER.CLICK");
711
715
  }
@@ -719,15 +723,15 @@ function connect(state, send, normalize) {
719
723
  const triggerState = getSwatchTriggerState(props);
720
724
  return normalize.button({
721
725
  ...parts.swatchTrigger.attrs,
722
- disabled: triggerState.isDisabled,
726
+ disabled: triggerState.disabled,
723
727
  dir: state.context.dir,
724
728
  type: "button",
725
729
  "aria-label": `select ${triggerState.valueAsString} as the color`,
726
- "data-state": triggerState.isChecked ? "checked" : "unchecked",
730
+ "data-state": triggerState.checked ? "checked" : "unchecked",
727
731
  "data-value": triggerState.valueAsString,
728
- "data-disabled": (0, import_dom_query2.dataAttr)(triggerState.isDisabled),
732
+ "data-disabled": (0, import_dom_query2.dataAttr)(triggerState.disabled),
729
733
  onClick() {
730
- if (triggerState.isDisabled)
734
+ if (triggerState.disabled)
731
735
  return;
732
736
  send({ type: "SWATCH_TRIGGER.CLICK", value: triggerState.value });
733
737
  },
@@ -741,7 +745,7 @@ function connect(state, send, normalize) {
741
745
  return normalize.element({
742
746
  ...parts.swatchIndicator.attrs,
743
747
  dir: state.context.dir,
744
- hidden: !triggerState.isChecked
748
+ hidden: !triggerState.checked
745
749
  });
746
750
  },
747
751
  getSwatchProps(props) {
@@ -750,7 +754,7 @@ function connect(state, send, normalize) {
750
754
  return normalize.element({
751
755
  ...parts.swatch.attrs,
752
756
  dir: state.context.dir,
753
- "data-state": triggerState.isChecked ? "checked" : "unchecked",
757
+ "data-state": triggerState.checked ? "checked" : "unchecked",
754
758
  "data-value": triggerState.valueAsString,
755
759
  style: {
756
760
  position: "relative",
@@ -775,7 +779,7 @@ function connect(state, send, normalize) {
775
779
  "aria-label": "change color format",
776
780
  dir: state.context.dir,
777
781
  defaultValue: state.context.format,
778
- disabled: isDisabled,
782
+ disabled,
779
783
  onChange(event) {
780
784
  const format = assertFormat(event.currentTarget.value);
781
785
  send({ type: "FORMAT.SET", format, src: "format-select" });