@zag-js/color-picker 1.34.1 → 1.35.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.
Files changed (49) hide show
  1. package/dist/color-picker.anatomy.d.mts +6 -0
  2. package/dist/color-picker.anatomy.d.ts +6 -0
  3. package/dist/color-picker.anatomy.js +59 -0
  4. package/dist/color-picker.anatomy.mjs +33 -0
  5. package/dist/color-picker.connect.d.mts +10 -0
  6. package/dist/color-picker.connect.d.ts +10 -0
  7. package/dist/color-picker.connect.js +681 -0
  8. package/dist/color-picker.connect.mjs +646 -0
  9. package/dist/color-picker.dom.d.mts +39 -0
  10. package/dist/color-picker.dom.d.ts +39 -0
  11. package/dist/color-picker.dom.js +136 -0
  12. package/dist/color-picker.dom.mjs +85 -0
  13. package/dist/color-picker.machine.d.mts +10 -0
  14. package/dist/color-picker.machine.d.ts +10 -0
  15. package/dist/color-picker.machine.js +636 -0
  16. package/dist/color-picker.machine.mjs +609 -0
  17. package/dist/color-picker.parse.d.mts +5 -0
  18. package/dist/color-picker.parse.d.ts +5 -0
  19. package/dist/color-picker.parse.js +33 -0
  20. package/dist/color-picker.parse.mjs +8 -0
  21. package/dist/color-picker.props.d.mts +21 -0
  22. package/dist/color-picker.props.d.ts +21 -0
  23. package/dist/color-picker.props.js +94 -0
  24. package/dist/color-picker.props.mjs +58 -0
  25. package/dist/color-picker.types.d.mts +303 -0
  26. package/dist/color-picker.types.d.ts +303 -0
  27. package/dist/color-picker.types.js +18 -0
  28. package/dist/color-picker.types.mjs +0 -0
  29. package/dist/index.d.mts +9 -324
  30. package/dist/index.d.ts +9 -324
  31. package/dist/index.js +37 -1517
  32. package/dist/index.mjs +11 -1504
  33. package/dist/utils/get-channel-display-color.d.mts +5 -0
  34. package/dist/utils/get-channel-display-color.d.ts +5 -0
  35. package/dist/utils/get-channel-display-color.js +48 -0
  36. package/dist/utils/get-channel-display-color.mjs +23 -0
  37. package/dist/utils/get-channel-input-value.d.mts +11 -0
  38. package/dist/utils/get-channel-input-value.d.ts +11 -0
  39. package/dist/utils/get-channel-input-value.js +88 -0
  40. package/dist/utils/get-channel-input-value.mjs +62 -0
  41. package/dist/utils/get-slider-background.d.mts +14 -0
  42. package/dist/utils/get-slider-background.d.ts +14 -0
  43. package/dist/utils/get-slider-background.js +65 -0
  44. package/dist/utils/get-slider-background.mjs +40 -0
  45. package/dist/utils/is-valid-hex.d.mts +4 -0
  46. package/dist/utils/is-valid-hex.d.ts +4 -0
  47. package/dist/utils/is-valid-hex.js +40 -0
  48. package/dist/utils/is-valid-hex.mjs +14 -0
  49. package/package.json +20 -10
@@ -0,0 +1,646 @@
1
+ // src/color-picker.connect.ts
2
+ import { getColorAreaGradient, normalizeColor } from "@zag-js/color-utils";
3
+ import { getEventKey, getEventPoint, getEventStep, isLeftClick, isModifierKey } from "@zag-js/dom-query";
4
+ import { dataAttr, query, visuallyHiddenStyle } from "@zag-js/dom-query";
5
+ import { getPlacementStyles } from "@zag-js/popper";
6
+ import { parts } from "./color-picker.anatomy.mjs";
7
+ import * as dom from "./color-picker.dom.mjs";
8
+ import { getChannelDisplayColor } from "./utils/get-channel-display-color.mjs";
9
+ import { getChannelRange, getChannelValue } from "./utils/get-channel-input-value.mjs";
10
+ import { getSliderBackground } from "./utils/get-slider-background.mjs";
11
+ function connect(service, normalize) {
12
+ const { context, send, prop, computed, state, scope } = service;
13
+ const value = context.get("value");
14
+ const format = context.get("format");
15
+ const areaValue = computed("areaValue");
16
+ const valueAsString = computed("valueAsString");
17
+ const disabled = computed("disabled");
18
+ const readOnly = !!prop("readOnly");
19
+ const invalid = !!prop("invalid");
20
+ const required = !!prop("required");
21
+ const interactive = computed("interactive");
22
+ const dragging = state.hasTag("dragging");
23
+ const open = state.hasTag("open");
24
+ const focused = state.hasTag("focused");
25
+ const getAreaChannels = (props) => {
26
+ const channels = areaValue.getChannels();
27
+ return {
28
+ xChannel: props.xChannel ?? channels[1],
29
+ yChannel: props.yChannel ?? channels[2]
30
+ };
31
+ };
32
+ const currentPlacement = context.get("currentPlacement");
33
+ const popperStyles = getPlacementStyles({
34
+ ...prop("positioning"),
35
+ placement: currentPlacement
36
+ });
37
+ function getSwatchTriggerState(props) {
38
+ const color = normalizeColor(props.value).toFormat(context.get("format"));
39
+ return {
40
+ value: color,
41
+ valueAsString: color.toString("hex"),
42
+ checked: color.isEqual(value),
43
+ disabled: props.disabled || !interactive
44
+ };
45
+ }
46
+ return {
47
+ dragging,
48
+ open,
49
+ valueAsString,
50
+ value,
51
+ inline: !!prop("inline"),
52
+ setOpen(nextOpen) {
53
+ if (prop("inline")) return;
54
+ const open2 = state.hasTag("open");
55
+ if (open2 === nextOpen) return;
56
+ send({ type: nextOpen ? "OPEN" : "CLOSE" });
57
+ },
58
+ setValue(value2) {
59
+ send({ type: "VALUE.SET", value: normalizeColor(value2), src: "set-color" });
60
+ },
61
+ getChannelValue(channel) {
62
+ return getChannelValue(value, channel);
63
+ },
64
+ getChannelValueText(channel, locale) {
65
+ return value.formatChannelValue(channel, locale);
66
+ },
67
+ setChannelValue(channel, channelValue) {
68
+ const color = value.withChannelValue(channel, channelValue);
69
+ send({ type: "VALUE.SET", value: color, src: "set-channel" });
70
+ },
71
+ format: context.get("format"),
72
+ setFormat(format2) {
73
+ const formatValue = value.toFormat(format2);
74
+ send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
75
+ },
76
+ alpha: value.getChannelValue("alpha"),
77
+ setAlpha(alphaValue) {
78
+ const color = value.withChannelValue("alpha", alphaValue);
79
+ send({ type: "VALUE.SET", value: color, src: "set-alpha" });
80
+ },
81
+ getRootProps() {
82
+ return normalize.element({
83
+ ...parts.root.attrs,
84
+ dir: prop("dir"),
85
+ id: dom.getRootId(scope),
86
+ "data-disabled": dataAttr(disabled),
87
+ "data-readonly": dataAttr(readOnly),
88
+ "data-invalid": dataAttr(invalid),
89
+ style: {
90
+ "--value": value.toString("css")
91
+ }
92
+ });
93
+ },
94
+ getLabelProps() {
95
+ return normalize.element({
96
+ ...parts.label.attrs,
97
+ dir: prop("dir"),
98
+ id: dom.getLabelId(scope),
99
+ htmlFor: dom.getHiddenInputId(scope),
100
+ "data-disabled": dataAttr(disabled),
101
+ "data-readonly": dataAttr(readOnly),
102
+ "data-invalid": dataAttr(invalid),
103
+ "data-required": dataAttr(required),
104
+ "data-focus": dataAttr(focused),
105
+ onClick(event) {
106
+ event.preventDefault();
107
+ const inputEl = query(dom.getControlEl(scope), "[data-channel=hex]");
108
+ inputEl?.focus({ preventScroll: true });
109
+ }
110
+ });
111
+ },
112
+ getControlProps() {
113
+ return normalize.element({
114
+ ...parts.control.attrs,
115
+ id: dom.getControlId(scope),
116
+ dir: prop("dir"),
117
+ "data-disabled": dataAttr(disabled),
118
+ "data-readonly": dataAttr(readOnly),
119
+ "data-invalid": dataAttr(invalid),
120
+ "data-state": open ? "open" : "closed",
121
+ "data-focus": dataAttr(focused)
122
+ });
123
+ },
124
+ getTriggerProps() {
125
+ return normalize.button({
126
+ ...parts.trigger.attrs,
127
+ id: dom.getTriggerId(scope),
128
+ dir: prop("dir"),
129
+ disabled,
130
+ "aria-label": `select color. current color is ${valueAsString}`,
131
+ "aria-controls": dom.getContentId(scope),
132
+ "aria-labelledby": dom.getLabelId(scope),
133
+ "aria-haspopup": prop("inline") ? void 0 : "dialog",
134
+ "data-disabled": dataAttr(disabled),
135
+ "data-readonly": dataAttr(readOnly),
136
+ "data-invalid": dataAttr(invalid),
137
+ "data-placement": currentPlacement,
138
+ "aria-expanded": open,
139
+ "data-state": open ? "open" : "closed",
140
+ "data-focus": dataAttr(focused),
141
+ type: "button",
142
+ onClick() {
143
+ if (!interactive) return;
144
+ send({ type: "TRIGGER.CLICK" });
145
+ },
146
+ onBlur() {
147
+ if (!interactive) return;
148
+ send({ type: "TRIGGER.BLUR" });
149
+ },
150
+ style: {
151
+ position: "relative"
152
+ }
153
+ });
154
+ },
155
+ getPositionerProps() {
156
+ return normalize.element({
157
+ ...parts.positioner.attrs,
158
+ id: dom.getPositionerId(scope),
159
+ dir: prop("dir"),
160
+ style: popperStyles.floating
161
+ });
162
+ },
163
+ getContentProps() {
164
+ return normalize.element({
165
+ ...parts.content.attrs,
166
+ id: dom.getContentId(scope),
167
+ dir: prop("dir"),
168
+ role: prop("inline") ? void 0 : "dialog",
169
+ tabIndex: -1,
170
+ "data-placement": currentPlacement,
171
+ "data-state": open ? "open" : "closed",
172
+ hidden: !open
173
+ });
174
+ },
175
+ getValueTextProps() {
176
+ return normalize.element({
177
+ ...parts.valueText.attrs,
178
+ dir: prop("dir"),
179
+ "data-disabled": dataAttr(disabled),
180
+ "data-focus": dataAttr(focused)
181
+ });
182
+ },
183
+ getAreaProps(props = {}) {
184
+ const { xChannel, yChannel } = getAreaChannels(props);
185
+ const { areaStyles } = getColorAreaGradient(areaValue, {
186
+ xChannel,
187
+ yChannel,
188
+ dir: prop("dir")
189
+ });
190
+ return normalize.element({
191
+ ...parts.area.attrs,
192
+ id: dom.getAreaId(scope),
193
+ role: "group",
194
+ "data-invalid": dataAttr(invalid),
195
+ "data-disabled": dataAttr(disabled),
196
+ "data-readonly": dataAttr(readOnly),
197
+ onPointerDown(event) {
198
+ if (!interactive) return;
199
+ if (!isLeftClick(event)) return;
200
+ if (isModifierKey(event)) return;
201
+ const point = getEventPoint(event);
202
+ const channel = { xChannel, yChannel };
203
+ send({ type: "AREA.POINTER_DOWN", point, channel, id: "area" });
204
+ event.preventDefault();
205
+ },
206
+ style: {
207
+ position: "relative",
208
+ touchAction: "none",
209
+ forcedColorAdjust: "none",
210
+ ...areaStyles
211
+ }
212
+ });
213
+ },
214
+ getAreaBackgroundProps(props = {}) {
215
+ const { xChannel, yChannel } = getAreaChannels(props);
216
+ const { areaGradientStyles } = getColorAreaGradient(areaValue, {
217
+ xChannel,
218
+ yChannel,
219
+ dir: prop("dir")
220
+ });
221
+ return normalize.element({
222
+ ...parts.areaBackground.attrs,
223
+ id: dom.getAreaGradientId(scope),
224
+ "data-invalid": dataAttr(invalid),
225
+ "data-disabled": dataAttr(disabled),
226
+ "data-readonly": dataAttr(readOnly),
227
+ style: {
228
+ position: "relative",
229
+ touchAction: "none",
230
+ forcedColorAdjust: "none",
231
+ ...areaGradientStyles
232
+ }
233
+ });
234
+ },
235
+ getAreaThumbProps(props = {}) {
236
+ const { xChannel, yChannel } = getAreaChannels(props);
237
+ const channel = { xChannel, yChannel };
238
+ const xPercent = areaValue.getChannelValuePercent(xChannel);
239
+ const yPercent = 1 - areaValue.getChannelValuePercent(yChannel);
240
+ const isRtl = prop("dir") === "rtl";
241
+ const finalXPercent = isRtl ? 1 - xPercent : xPercent;
242
+ const xValue = areaValue.getChannelValue(xChannel);
243
+ const yValue = areaValue.getChannelValue(yChannel);
244
+ const color = areaValue.withChannelValue("alpha", 1).toString("css");
245
+ return normalize.element({
246
+ ...parts.areaThumb.attrs,
247
+ id: dom.getAreaThumbId(scope),
248
+ dir: prop("dir"),
249
+ tabIndex: disabled ? void 0 : 0,
250
+ "data-disabled": dataAttr(disabled),
251
+ "data-invalid": dataAttr(invalid),
252
+ "data-readonly": dataAttr(readOnly),
253
+ role: "slider",
254
+ "aria-valuemin": 0,
255
+ "aria-valuemax": 100,
256
+ "aria-valuenow": xValue,
257
+ "aria-label": `${xChannel} and ${yChannel}`,
258
+ "aria-roledescription": "2d slider",
259
+ "aria-valuetext": `${xChannel} ${xValue}, ${yChannel} ${yValue}`,
260
+ style: {
261
+ position: "absolute",
262
+ left: `${finalXPercent * 100}%`,
263
+ top: `${yPercent * 100}%`,
264
+ transform: "translate(-50%, -50%)",
265
+ touchAction: "none",
266
+ forcedColorAdjust: "none",
267
+ "--color": color,
268
+ background: color
269
+ },
270
+ onFocus() {
271
+ if (!interactive) return;
272
+ send({ type: "AREA.FOCUS", id: "area", channel });
273
+ },
274
+ onKeyDown(event) {
275
+ if (event.defaultPrevented) return;
276
+ if (!interactive) return;
277
+ const step = getEventStep(event);
278
+ const keyMap = {
279
+ ArrowUp() {
280
+ send({ type: "AREA.ARROW_UP", channel, step });
281
+ },
282
+ ArrowDown() {
283
+ send({ type: "AREA.ARROW_DOWN", channel, step });
284
+ },
285
+ ArrowLeft() {
286
+ send({ type: "AREA.ARROW_LEFT", channel, step });
287
+ },
288
+ ArrowRight() {
289
+ send({ type: "AREA.ARROW_RIGHT", channel, step });
290
+ },
291
+ PageUp() {
292
+ send({ type: "AREA.PAGE_UP", channel, step });
293
+ },
294
+ PageDown() {
295
+ send({ type: "AREA.PAGE_DOWN", channel, step });
296
+ },
297
+ Escape(event2) {
298
+ event2.stopPropagation();
299
+ }
300
+ };
301
+ const exec = keyMap[getEventKey(event, {
302
+ dir: prop("dir")
303
+ })];
304
+ if (exec) {
305
+ exec(event);
306
+ event.preventDefault();
307
+ }
308
+ }
309
+ });
310
+ },
311
+ getTransparencyGridProps(props = {}) {
312
+ const { size = "12px" } = props;
313
+ return normalize.element({
314
+ ...parts.transparencyGrid.attrs,
315
+ style: {
316
+ "--size": size,
317
+ width: "100%",
318
+ height: "100%",
319
+ position: "absolute",
320
+ backgroundColor: "#fff",
321
+ backgroundImage: "conic-gradient(#eeeeee 0 25%, transparent 0 50%, #eeeeee 0 75%, transparent 0)",
322
+ backgroundSize: "var(--size) var(--size)",
323
+ inset: "0px",
324
+ zIndex: "auto",
325
+ pointerEvents: "none"
326
+ }
327
+ });
328
+ },
329
+ getChannelSliderProps(props) {
330
+ const { orientation = "horizontal", channel, format: format2 } = props;
331
+ return normalize.element({
332
+ ...parts.channelSlider.attrs,
333
+ "data-channel": channel,
334
+ "data-orientation": orientation,
335
+ role: "presentation",
336
+ onPointerDown(event) {
337
+ if (!interactive) return;
338
+ if (!isLeftClick(event)) return;
339
+ if (isModifierKey(event)) return;
340
+ const point = getEventPoint(event);
341
+ send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, format: format2, point, id: channel, orientation });
342
+ event.preventDefault();
343
+ },
344
+ style: {
345
+ position: "relative",
346
+ touchAction: "none"
347
+ }
348
+ });
349
+ },
350
+ getChannelSliderTrackProps(props) {
351
+ const { orientation = "horizontal", channel, format: format2 } = props;
352
+ const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
353
+ return normalize.element({
354
+ ...parts.channelSliderTrack.attrs,
355
+ id: dom.getChannelSliderTrackId(scope, channel),
356
+ role: "group",
357
+ "data-channel": channel,
358
+ "data-orientation": orientation,
359
+ style: {
360
+ position: "relative",
361
+ forcedColorAdjust: "none",
362
+ backgroundImage: getSliderBackground({
363
+ orientation,
364
+ channel,
365
+ dir: prop("dir"),
366
+ value: normalizedValue
367
+ })
368
+ }
369
+ });
370
+ },
371
+ getChannelSliderLabelProps(props) {
372
+ const { channel } = props;
373
+ return normalize.element({
374
+ ...parts.channelSliderLabel.attrs,
375
+ "data-channel": channel,
376
+ onClick(event) {
377
+ if (!interactive) return;
378
+ event.preventDefault();
379
+ const thumbId = dom.getChannelSliderThumbId(scope, channel);
380
+ scope.getById(thumbId)?.focus({ preventScroll: true });
381
+ },
382
+ style: {
383
+ userSelect: "none",
384
+ WebkitUserSelect: "none"
385
+ }
386
+ });
387
+ },
388
+ getChannelSliderValueTextProps(props) {
389
+ return normalize.element({
390
+ ...parts.channelSliderValueText.attrs,
391
+ "data-channel": props.channel
392
+ });
393
+ },
394
+ getChannelSliderThumbProps(props) {
395
+ const { orientation = "horizontal", channel, format: format2 } = props;
396
+ const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
397
+ const channelRange = normalizedValue.getChannelRange(channel);
398
+ const channelValue = normalizedValue.getChannelValue(channel);
399
+ const offset = (channelValue - channelRange.minValue) / (channelRange.maxValue - channelRange.minValue);
400
+ const isRtl = prop("dir") === "rtl";
401
+ const finalOffset = orientation === "horizontal" && isRtl ? 1 - offset : offset;
402
+ const placementStyles = orientation === "horizontal" ? { left: `${finalOffset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
403
+ return normalize.element({
404
+ ...parts.channelSliderThumb.attrs,
405
+ id: dom.getChannelSliderThumbId(scope, channel),
406
+ role: "slider",
407
+ "aria-label": channel,
408
+ tabIndex: disabled ? void 0 : 0,
409
+ "data-channel": channel,
410
+ "data-disabled": dataAttr(disabled),
411
+ "data-orientation": orientation,
412
+ "aria-disabled": dataAttr(disabled),
413
+ "aria-orientation": orientation,
414
+ "aria-valuemax": channelRange.maxValue,
415
+ "aria-valuemin": channelRange.minValue,
416
+ "aria-valuenow": channelValue,
417
+ "aria-valuetext": `${channel} ${channelValue}`,
418
+ style: {
419
+ forcedColorAdjust: "none",
420
+ position: "absolute",
421
+ background: getChannelDisplayColor(areaValue, channel).toString("css"),
422
+ ...placementStyles
423
+ },
424
+ onFocus() {
425
+ if (!interactive) return;
426
+ send({ type: "CHANNEL_SLIDER.FOCUS", channel });
427
+ },
428
+ onKeyDown(event) {
429
+ if (event.defaultPrevented) return;
430
+ if (!interactive) return;
431
+ const step = getEventStep(event) * channelRange.step;
432
+ const keyMap = {
433
+ ArrowUp() {
434
+ send({ type: "CHANNEL_SLIDER.ARROW_UP", channel, step });
435
+ },
436
+ ArrowDown() {
437
+ send({ type: "CHANNEL_SLIDER.ARROW_DOWN", channel, step });
438
+ },
439
+ ArrowLeft() {
440
+ send({ type: "CHANNEL_SLIDER.ARROW_LEFT", channel, step });
441
+ },
442
+ ArrowRight() {
443
+ send({ type: "CHANNEL_SLIDER.ARROW_RIGHT", channel, step });
444
+ },
445
+ PageUp() {
446
+ send({ type: "CHANNEL_SLIDER.PAGE_UP", channel });
447
+ },
448
+ PageDown() {
449
+ send({ type: "CHANNEL_SLIDER.PAGE_DOWN", channel });
450
+ },
451
+ Home() {
452
+ send({ type: "CHANNEL_SLIDER.HOME", channel });
453
+ },
454
+ End() {
455
+ send({ type: "CHANNEL_SLIDER.END", channel });
456
+ },
457
+ Escape(event2) {
458
+ event2.stopPropagation();
459
+ }
460
+ };
461
+ const exec = keyMap[getEventKey(event, {
462
+ dir: prop("dir")
463
+ })];
464
+ if (exec) {
465
+ exec(event);
466
+ event.preventDefault();
467
+ }
468
+ }
469
+ });
470
+ },
471
+ getChannelInputProps(props) {
472
+ const { channel } = props;
473
+ const isTextField = channel === "hex" || channel === "css";
474
+ const channelRange = getChannelRange(value, channel);
475
+ return normalize.input({
476
+ ...parts.channelInput.attrs,
477
+ dir: prop("dir"),
478
+ type: isTextField ? "text" : "number",
479
+ "data-channel": channel,
480
+ "aria-label": channel,
481
+ spellCheck: false,
482
+ autoComplete: "off",
483
+ disabled,
484
+ "data-disabled": dataAttr(disabled),
485
+ "data-invalid": dataAttr(invalid),
486
+ "data-readonly": dataAttr(readOnly),
487
+ readOnly,
488
+ defaultValue: getChannelValue(value, channel),
489
+ min: channelRange?.minValue,
490
+ max: channelRange?.maxValue,
491
+ step: channelRange?.step,
492
+ onBeforeInput(event) {
493
+ if (isTextField || !interactive) return;
494
+ const value2 = event.currentTarget.value;
495
+ if (value2.match(/[^0-9.]/g)) {
496
+ event.preventDefault();
497
+ }
498
+ },
499
+ onFocus(event) {
500
+ if (!interactive) return;
501
+ send({ type: "CHANNEL_INPUT.FOCUS", channel });
502
+ event.currentTarget.select();
503
+ },
504
+ onBlur(event) {
505
+ if (!interactive) return;
506
+ const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
507
+ send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
508
+ },
509
+ onKeyDown(event) {
510
+ if (event.defaultPrevented) return;
511
+ if (!interactive) return;
512
+ if (event.key === "Enter") {
513
+ const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
514
+ send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
515
+ event.preventDefault();
516
+ }
517
+ },
518
+ style: {
519
+ appearance: "none",
520
+ WebkitAppearance: "none",
521
+ MozAppearance: "textfield"
522
+ }
523
+ });
524
+ },
525
+ getHiddenInputProps() {
526
+ return normalize.input({
527
+ type: "text",
528
+ disabled,
529
+ name: prop("name"),
530
+ tabIndex: -1,
531
+ readOnly,
532
+ required,
533
+ id: dom.getHiddenInputId(scope),
534
+ style: visuallyHiddenStyle,
535
+ defaultValue: valueAsString
536
+ });
537
+ },
538
+ getEyeDropperTriggerProps() {
539
+ return normalize.button({
540
+ ...parts.eyeDropperTrigger.attrs,
541
+ type: "button",
542
+ dir: prop("dir"),
543
+ disabled,
544
+ "data-disabled": dataAttr(disabled),
545
+ "data-invalid": dataAttr(invalid),
546
+ "data-readonly": dataAttr(readOnly),
547
+ "aria-label": "Pick a color from the screen",
548
+ onClick() {
549
+ if (!interactive) return;
550
+ send({ type: "EYEDROPPER.CLICK" });
551
+ }
552
+ });
553
+ },
554
+ getSwatchGroupProps() {
555
+ return normalize.element({
556
+ ...parts.swatchGroup.attrs,
557
+ role: "group"
558
+ });
559
+ },
560
+ getSwatchTriggerState,
561
+ getSwatchTriggerProps(props) {
562
+ const swatchState = getSwatchTriggerState(props);
563
+ return normalize.button({
564
+ ...parts.swatchTrigger.attrs,
565
+ disabled: swatchState.disabled,
566
+ dir: prop("dir"),
567
+ type: "button",
568
+ "aria-label": `select ${swatchState.valueAsString} as the color`,
569
+ "data-state": swatchState.checked ? "checked" : "unchecked",
570
+ "data-value": swatchState.valueAsString,
571
+ "data-disabled": dataAttr(swatchState.disabled),
572
+ onClick() {
573
+ if (swatchState.disabled) return;
574
+ send({ type: "SWATCH_TRIGGER.CLICK", value: swatchState.value });
575
+ },
576
+ style: {
577
+ "--color": swatchState.valueAsString,
578
+ position: "relative"
579
+ }
580
+ });
581
+ },
582
+ getSwatchIndicatorProps(props) {
583
+ const swatchState = getSwatchTriggerState(props);
584
+ return normalize.element({
585
+ ...parts.swatchIndicator.attrs,
586
+ dir: prop("dir"),
587
+ hidden: !swatchState.checked
588
+ });
589
+ },
590
+ getSwatchProps(props) {
591
+ const { respectAlpha = true } = props;
592
+ const swatchState = getSwatchTriggerState(props);
593
+ const color = swatchState.value.toString(respectAlpha ? "css" : "hex");
594
+ return normalize.element({
595
+ ...parts.swatch.attrs,
596
+ dir: prop("dir"),
597
+ "data-state": swatchState.checked ? "checked" : "unchecked",
598
+ "data-value": swatchState.valueAsString,
599
+ style: {
600
+ "--color": color,
601
+ position: "relative",
602
+ background: color
603
+ }
604
+ });
605
+ },
606
+ getFormatTriggerProps() {
607
+ return normalize.button({
608
+ ...parts.formatTrigger.attrs,
609
+ dir: prop("dir"),
610
+ type: "button",
611
+ "aria-label": `change color format to ${getNextFormat(format)}`,
612
+ onClick(event) {
613
+ if (event.currentTarget.disabled) return;
614
+ const nextFormat = getNextFormat(format);
615
+ send({ type: "FORMAT.SET", format: nextFormat, src: "format-trigger" });
616
+ }
617
+ });
618
+ },
619
+ getFormatSelectProps() {
620
+ return normalize.select({
621
+ ...parts.formatSelect.attrs,
622
+ "aria-label": "change color format",
623
+ dir: prop("dir"),
624
+ defaultValue: prop("format"),
625
+ disabled,
626
+ onChange(event) {
627
+ const format2 = assertFormat(event.currentTarget.value);
628
+ send({ type: "FORMAT.SET", format: format2, src: "format-select" });
629
+ }
630
+ });
631
+ }
632
+ };
633
+ }
634
+ var formats = ["hsba", "hsla", "rgba"];
635
+ var formatRegex = new RegExp(`^(${formats.join("|")})$`);
636
+ function getNextFormat(format) {
637
+ const index = formats.indexOf(format);
638
+ return formats[index + 1] ?? formats[0];
639
+ }
640
+ function assertFormat(format) {
641
+ if (formatRegex.test(format)) return format;
642
+ throw new Error(`Unsupported color format: ${format}`);
643
+ }
644
+ export {
645
+ connect
646
+ };
@@ -0,0 +1,39 @@
1
+ import { ColorChannel } from '@zag-js/color-utils';
2
+ import { Scope } from '@zag-js/core';
3
+ import { Point, Direction } from '@zag-js/types';
4
+
5
+ declare const getRootId: (ctx: Scope) => any;
6
+ declare const getLabelId: (ctx: Scope) => any;
7
+ declare const getHiddenInputId: (ctx: Scope) => any;
8
+ declare const getControlId: (ctx: Scope) => any;
9
+ declare const getTriggerId: (ctx: Scope) => any;
10
+ declare const getContentId: (ctx: Scope) => any;
11
+ declare const getPositionerId: (ctx: Scope) => any;
12
+ declare const getFormatSelectId: (ctx: Scope) => any;
13
+ declare const getAreaId: (ctx: Scope) => any;
14
+ declare const getAreaGradientId: (ctx: Scope) => any;
15
+ declare const getAreaThumbId: (ctx: Scope) => any;
16
+ declare const getChannelSliderTrackId: (ctx: Scope, channel: ColorChannel) => any;
17
+ declare const getChannelSliderThumbId: (ctx: Scope, channel: ColorChannel) => any;
18
+ declare const getContentEl: (ctx: Scope) => HTMLElement | null;
19
+ declare const getAreaThumbEl: (ctx: Scope) => HTMLElement | null;
20
+ declare const getChannelSliderThumbEl: (ctx: Scope, channel: ColorChannel) => HTMLElement | null;
21
+ declare const getChannelInputEl: (ctx: Scope, channel: string) => HTMLInputElement[];
22
+ declare const getFormatSelectEl: (ctx: Scope) => HTMLSelectElement | null;
23
+ declare const getHiddenInputEl: (ctx: Scope) => HTMLInputElement | null;
24
+ declare const getAreaEl: (ctx: Scope) => HTMLElement | null;
25
+ declare const getAreaValueFromPoint: (ctx: Scope, point: Point, dir?: Direction) => {
26
+ x: number;
27
+ y: number;
28
+ } | undefined;
29
+ declare const getControlEl: (ctx: Scope) => HTMLElement | null;
30
+ declare const getTriggerEl: (ctx: Scope) => HTMLElement | null;
31
+ declare const getPositionerEl: (ctx: Scope) => HTMLElement | null;
32
+ declare const getChannelSliderTrackEl: (ctx: Scope, channel: ColorChannel) => HTMLElement | null;
33
+ declare const getChannelSliderValueFromPoint: (ctx: Scope, point: Point, channel: ColorChannel, dir?: Direction) => {
34
+ x: number;
35
+ y: number;
36
+ } | undefined;
37
+ declare const getChannelInputEls: (ctx: Scope) => HTMLInputElement[];
38
+
39
+ export { getAreaEl, getAreaGradientId, getAreaId, getAreaThumbEl, getAreaThumbId, getAreaValueFromPoint, getChannelInputEl, getChannelInputEls, getChannelSliderThumbEl, getChannelSliderThumbId, getChannelSliderTrackEl, getChannelSliderTrackId, getChannelSliderValueFromPoint, getContentEl, getContentId, getControlEl, getControlId, getFormatSelectEl, getFormatSelectId, getHiddenInputEl, getHiddenInputId, getLabelId, getPositionerEl, getPositionerId, getRootId, getTriggerEl, getTriggerId };