@zag-js/color-picker 0.29.0 → 0.31.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 +46 -9
- package/dist/index.d.ts +46 -9
- package/dist/index.js +219 -89
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +219 -89
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -14
- package/src/color-picker.anatomy.ts +3 -0
- package/src/color-picker.connect.ts +133 -28
- package/src/color-picker.dom.ts +3 -2
- package/src/color-picker.machine.ts +90 -49
- package/src/color-picker.parse.ts +2 -10
- package/src/color-picker.types.ts +48 -7
- package/src/index.ts +1 -0
- package/src/utils/get-channel-input-value.ts +5 -5
package/dist/index.mjs
CHANGED
|
@@ -17,8 +17,11 @@ var anatomy = createAnatomy("color-picker", [
|
|
|
17
17
|
"transparencyGrid",
|
|
18
18
|
"swatchGroup",
|
|
19
19
|
"swatchTrigger",
|
|
20
|
+
"swatchIndicator",
|
|
20
21
|
"swatch",
|
|
21
|
-
"eyeDropperTrigger"
|
|
22
|
+
"eyeDropperTrigger",
|
|
23
|
+
"formatTrigger",
|
|
24
|
+
"formatSelect"
|
|
22
25
|
]);
|
|
23
26
|
var parts = anatomy.build();
|
|
24
27
|
|
|
@@ -49,6 +52,7 @@ var dom = createScope({
|
|
|
49
52
|
getTriggerId: (ctx) => ctx.ids?.trigger ?? `color-picker:${ctx.id}:trigger`,
|
|
50
53
|
getContentId: (ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`,
|
|
51
54
|
getPositionerId: (ctx) => `color-picker:${ctx.id}:positioner`,
|
|
55
|
+
getFormatSelectId: (ctx) => `color-picker:${ctx.id}:format-select`,
|
|
52
56
|
getAreaId: (ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`,
|
|
53
57
|
getAreaGradientId: (ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`,
|
|
54
58
|
getAreaThumbId: (ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`,
|
|
@@ -63,6 +67,7 @@ var dom = createScope({
|
|
|
63
67
|
...queryAll(dom.getControlEl(ctx), `input[data-channel="${channel}"]`)
|
|
64
68
|
];
|
|
65
69
|
},
|
|
70
|
+
getFormatSelectEl: (ctx) => dom.getById(ctx, dom.getFormatSelectId(ctx)),
|
|
66
71
|
getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
|
|
67
72
|
getAreaEl: (ctx) => dom.getById(ctx, dom.getAreaId(ctx)),
|
|
68
73
|
getAreaValueFromPoint(ctx, point) {
|
|
@@ -94,10 +99,7 @@ var dom = createScope({
|
|
|
94
99
|
getFirstFocusableEl: (ctx) => getFirstFocusable(dom.getContentEl(ctx), "if-empty"),
|
|
95
100
|
getInitialFocusEl: (ctx) => {
|
|
96
101
|
let el = runIfFn(ctx.initialFocusEl);
|
|
97
|
-
|
|
98
|
-
el = dom.getFirstFocusableEl(ctx);
|
|
99
|
-
if (!el)
|
|
100
|
-
el = dom.getContentEl(ctx);
|
|
102
|
+
el = dom.getFirstFocusableEl(ctx) ?? dom.getContentEl(ctx);
|
|
101
103
|
return el;
|
|
102
104
|
}
|
|
103
105
|
});
|
|
@@ -142,7 +144,7 @@ function getChannelValue(color, channel) {
|
|
|
142
144
|
case "hue":
|
|
143
145
|
return isHSL ? color.toFormat("hsla").getChannelValue("hue").toString() : color.toFormat("hsba").getChannelValue("hue").toString();
|
|
144
146
|
case "saturation":
|
|
145
|
-
return isHSL ? color.toFormat("
|
|
147
|
+
return isHSL ? color.toFormat("hsla").getChannelValue("saturation").toString() : color.toFormat("hsba").getChannelValue("saturation").toString();
|
|
146
148
|
case "lightness":
|
|
147
149
|
return color.toFormat("hsla").getChannelValue("lightness").toString();
|
|
148
150
|
case "brightness":
|
|
@@ -171,13 +173,13 @@ function getChannelRange(color, channel) {
|
|
|
171
173
|
case "hue":
|
|
172
174
|
case "saturation":
|
|
173
175
|
case "lightness":
|
|
174
|
-
return color.toFormat("
|
|
176
|
+
return color.toFormat("hsla").getChannelRange(channel);
|
|
175
177
|
case "brightness":
|
|
176
|
-
return color.toFormat("
|
|
178
|
+
return color.toFormat("hsba").getChannelRange(channel);
|
|
177
179
|
case "red":
|
|
178
180
|
case "green":
|
|
179
181
|
case "blue":
|
|
180
|
-
return color.toFormat("
|
|
182
|
+
return color.toFormat("rgba").getChannelRange(channel);
|
|
181
183
|
default:
|
|
182
184
|
return color.getChannelRange(channel);
|
|
183
185
|
}
|
|
@@ -224,13 +226,15 @@ var getSliderBackground = (props) => {
|
|
|
224
226
|
// src/color-picker.connect.ts
|
|
225
227
|
function connect(state, send, normalize) {
|
|
226
228
|
const value = state.context.value;
|
|
229
|
+
const areaValue = state.context.areaValue;
|
|
227
230
|
const valueAsString = state.context.valueAsString;
|
|
228
231
|
const isDisabled = state.context.isDisabled;
|
|
229
232
|
const isInteractive = state.context.isInteractive;
|
|
230
233
|
const isDragging = state.hasTag("dragging");
|
|
231
234
|
const isOpen = state.hasTag("open");
|
|
235
|
+
const isFocused = state.hasTag("focused");
|
|
232
236
|
const getAreaChannels = (props) => {
|
|
233
|
-
const channels =
|
|
237
|
+
const channels = areaValue.getChannels();
|
|
234
238
|
return {
|
|
235
239
|
xChannel: props.xChannel ?? channels[1],
|
|
236
240
|
yChannel: props.yChannel ?? channels[2]
|
|
@@ -241,11 +245,26 @@ function connect(state, send, normalize) {
|
|
|
241
245
|
...state.context.positioning,
|
|
242
246
|
placement: currentPlacement
|
|
243
247
|
});
|
|
248
|
+
function getSwatchTriggerState(props) {
|
|
249
|
+
const color = normalizeColor(props.value).toFormat(state.context.format);
|
|
250
|
+
return {
|
|
251
|
+
value: color,
|
|
252
|
+
valueAsString: color.toString("hex"),
|
|
253
|
+
isChecked: color.isEqual(value),
|
|
254
|
+
isDisabled: props.disabled || !isInteractive
|
|
255
|
+
};
|
|
256
|
+
}
|
|
244
257
|
return {
|
|
245
258
|
isDragging,
|
|
246
259
|
isOpen,
|
|
247
260
|
valueAsString,
|
|
248
261
|
value,
|
|
262
|
+
open() {
|
|
263
|
+
send({ type: "OPEN" });
|
|
264
|
+
},
|
|
265
|
+
close() {
|
|
266
|
+
send({ type: "CLOSE" });
|
|
267
|
+
},
|
|
249
268
|
setValue(value2) {
|
|
250
269
|
send({ type: "VALUE.SET", value: normalizeColor(value2), src: "set-color" });
|
|
251
270
|
},
|
|
@@ -256,7 +275,7 @@ function connect(state, send, normalize) {
|
|
|
256
275
|
const color = value.withChannelValue(channel, channelValue);
|
|
257
276
|
send({ type: "VALUE.SET", value: color, src: "set-channel" });
|
|
258
277
|
},
|
|
259
|
-
format:
|
|
278
|
+
format: state.context.format,
|
|
260
279
|
setFormat(format) {
|
|
261
280
|
const formatValue = value.toFormat(format);
|
|
262
281
|
send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
|
|
@@ -283,6 +302,7 @@ function connect(state, send, normalize) {
|
|
|
283
302
|
htmlFor: dom.getHiddenInputId(state.context),
|
|
284
303
|
"data-disabled": dataAttr(isDisabled),
|
|
285
304
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
305
|
+
"data-focus": dataAttr(isFocused),
|
|
286
306
|
onClick(event) {
|
|
287
307
|
event.preventDefault();
|
|
288
308
|
const inputEl = query(dom.getControlEl(state.context), "[data-channel=hex]");
|
|
@@ -294,21 +314,35 @@ function connect(state, send, normalize) {
|
|
|
294
314
|
id: dom.getControlId(state.context),
|
|
295
315
|
dir: state.context.dir,
|
|
296
316
|
"data-disabled": dataAttr(isDisabled),
|
|
297
|
-
"data-readonly": dataAttr(state.context.readOnly)
|
|
317
|
+
"data-readonly": dataAttr(state.context.readOnly),
|
|
318
|
+
"data-state": isOpen ? "open" : "closed",
|
|
319
|
+
"data-focus": dataAttr(isFocused)
|
|
298
320
|
}),
|
|
299
321
|
triggerProps: normalize.button({
|
|
300
322
|
...parts.trigger.attrs,
|
|
301
323
|
id: dom.getTriggerId(state.context),
|
|
302
324
|
dir: state.context.dir,
|
|
325
|
+
disabled: isDisabled,
|
|
326
|
+
"aria-label": `select color. current color is ${valueAsString}`,
|
|
303
327
|
"aria-controls": dom.getContentId(state.context),
|
|
304
328
|
"aria-labelledby": dom.getLabelId(state.context),
|
|
305
329
|
"data-disabled": dataAttr(isDisabled),
|
|
306
330
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
307
331
|
"data-placement": currentPlacement,
|
|
332
|
+
"aria-expanded": dataAttr(isOpen),
|
|
333
|
+
"data-state": isOpen ? "open" : "closed",
|
|
334
|
+
"data-focus": dataAttr(isFocused),
|
|
308
335
|
type: "button",
|
|
309
336
|
onClick() {
|
|
337
|
+
if (!isInteractive)
|
|
338
|
+
return;
|
|
310
339
|
send({ type: "TRIGGER.CLICK" });
|
|
311
340
|
},
|
|
341
|
+
onBlur() {
|
|
342
|
+
if (!isInteractive)
|
|
343
|
+
return;
|
|
344
|
+
send({ type: "TRIGGER.BLUR" });
|
|
345
|
+
},
|
|
312
346
|
style: {
|
|
313
347
|
position: "relative"
|
|
314
348
|
}
|
|
@@ -324,11 +358,12 @@ function connect(state, send, normalize) {
|
|
|
324
358
|
id: dom.getContentId(state.context),
|
|
325
359
|
dir: state.context.dir,
|
|
326
360
|
"data-placement": currentPlacement,
|
|
361
|
+
"data-state": isOpen ? "open" : "closed",
|
|
327
362
|
hidden: !isOpen
|
|
328
363
|
}),
|
|
329
364
|
getAreaProps(props = {}) {
|
|
330
365
|
const { xChannel, yChannel } = getAreaChannels(props);
|
|
331
|
-
const { areaStyles } = getColorAreaGradient(
|
|
366
|
+
const { areaStyles } = getColorAreaGradient(areaValue, {
|
|
332
367
|
xChannel,
|
|
333
368
|
yChannel,
|
|
334
369
|
dir: state.context.dir
|
|
@@ -358,7 +393,7 @@ function connect(state, send, normalize) {
|
|
|
358
393
|
},
|
|
359
394
|
getAreaBackgroundProps(props = {}) {
|
|
360
395
|
const { xChannel, yChannel } = getAreaChannels(props);
|
|
361
|
-
const { areaGradientStyles } = getColorAreaGradient(
|
|
396
|
+
const { areaGradientStyles } = getColorAreaGradient(areaValue, {
|
|
362
397
|
xChannel,
|
|
363
398
|
yChannel,
|
|
364
399
|
dir: state.context.dir
|
|
@@ -377,25 +412,35 @@ function connect(state, send, normalize) {
|
|
|
377
412
|
getAreaThumbProps(props = {}) {
|
|
378
413
|
const { xChannel, yChannel } = getAreaChannels(props);
|
|
379
414
|
const channel = { xChannel, yChannel };
|
|
380
|
-
const
|
|
381
|
-
const
|
|
415
|
+
const xPercent = areaValue.getChannelValuePercent(xChannel);
|
|
416
|
+
const yPercent = 1 - areaValue.getChannelValuePercent(yChannel);
|
|
417
|
+
const xValue = areaValue.getChannelValue(xChannel);
|
|
418
|
+
const yValue = areaValue.getChannelValue(yChannel);
|
|
382
419
|
return normalize.element({
|
|
383
420
|
...parts.areaThumb.attrs,
|
|
384
421
|
id: dom.getAreaThumbId(state.context),
|
|
385
422
|
dir: state.context.dir,
|
|
386
423
|
tabIndex: isDisabled ? void 0 : 0,
|
|
387
424
|
"data-disabled": dataAttr(isDisabled),
|
|
388
|
-
role: "
|
|
425
|
+
role: "slider",
|
|
426
|
+
"aria-valuemin": 0,
|
|
427
|
+
"aria-valuemax": 100,
|
|
428
|
+
"aria-valuenow": xValue,
|
|
429
|
+
"aria-label": `${xChannel} and ${yChannel}`,
|
|
430
|
+
"aria-roledescription": "2d slider",
|
|
431
|
+
"aria-valuetext": `${xChannel} ${xValue}, ${yChannel} ${yValue}`,
|
|
389
432
|
style: {
|
|
390
433
|
position: "absolute",
|
|
391
|
-
left: `${
|
|
392
|
-
top: `${
|
|
434
|
+
left: `${xPercent * 100}%`,
|
|
435
|
+
top: `${yPercent * 100}%`,
|
|
393
436
|
transform: "translate(-50%, -50%)",
|
|
394
437
|
touchAction: "none",
|
|
395
438
|
forcedColorAdjust: "none",
|
|
396
|
-
background:
|
|
439
|
+
background: areaValue.withChannelValue("alpha", 1).toString("css")
|
|
397
440
|
},
|
|
398
441
|
onFocus() {
|
|
442
|
+
if (!isInteractive)
|
|
443
|
+
return;
|
|
399
444
|
send({ type: "AREA.FOCUS", id: "area", channel });
|
|
400
445
|
},
|
|
401
446
|
onKeyDown(event) {
|
|
@@ -489,15 +534,15 @@ function connect(state, send, normalize) {
|
|
|
489
534
|
orientation,
|
|
490
535
|
channel,
|
|
491
536
|
dir: state.context.dir,
|
|
492
|
-
value
|
|
537
|
+
value: areaValue
|
|
493
538
|
})
|
|
494
539
|
}
|
|
495
540
|
});
|
|
496
541
|
},
|
|
497
542
|
getChannelSliderThumbProps(props) {
|
|
498
543
|
const { orientation = "horizontal", channel } = props;
|
|
499
|
-
const { minValue, maxValue, step: stepValue } =
|
|
500
|
-
const channelValue =
|
|
544
|
+
const { minValue, maxValue, step: stepValue } = areaValue.getChannelRange(channel);
|
|
545
|
+
const channelValue = areaValue.getChannelValue(channel);
|
|
501
546
|
const offset = (channelValue - minValue) / (maxValue - minValue);
|
|
502
547
|
const placementStyles = orientation === "horizontal" ? { left: `${offset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
|
|
503
548
|
return normalize.element({
|
|
@@ -514,10 +559,11 @@ function connect(state, send, normalize) {
|
|
|
514
559
|
"aria-valuemax": maxValue,
|
|
515
560
|
"aria-valuemin": minValue,
|
|
516
561
|
"aria-valuenow": channelValue,
|
|
562
|
+
"aria-valuetext": `${channel} ${channelValue}`,
|
|
517
563
|
style: {
|
|
518
564
|
forcedColorAdjust: "none",
|
|
519
565
|
position: "absolute",
|
|
520
|
-
background: getChannelDisplayColor(
|
|
566
|
+
background: getChannelDisplayColor(areaValue, channel).toString("css"),
|
|
521
567
|
...placementStyles
|
|
522
568
|
},
|
|
523
569
|
onFocus() {
|
|
@@ -576,6 +622,8 @@ function connect(state, send, normalize) {
|
|
|
576
622
|
type: isTextField ? "text" : "number",
|
|
577
623
|
"data-channel": channel,
|
|
578
624
|
"aria-label": channel,
|
|
625
|
+
spellCheck: false,
|
|
626
|
+
autoComplete: "off",
|
|
579
627
|
disabled: isDisabled,
|
|
580
628
|
"data-disabled": dataAttr(isDisabled),
|
|
581
629
|
readOnly: state.context.readOnly,
|
|
@@ -584,7 +632,7 @@ function connect(state, send, normalize) {
|
|
|
584
632
|
max: range?.maxValue,
|
|
585
633
|
step: range?.step,
|
|
586
634
|
onBeforeInput(event) {
|
|
587
|
-
if (isTextField)
|
|
635
|
+
if (isTextField || !isInteractive)
|
|
588
636
|
return;
|
|
589
637
|
const value2 = event.currentTarget.value;
|
|
590
638
|
if (value2.match(/[^0-9.]/g)) {
|
|
@@ -592,14 +640,20 @@ function connect(state, send, normalize) {
|
|
|
592
640
|
}
|
|
593
641
|
},
|
|
594
642
|
onFocus(event) {
|
|
643
|
+
if (!isInteractive)
|
|
644
|
+
return;
|
|
595
645
|
send({ type: "CHANNEL_INPUT.FOCUS", channel });
|
|
596
646
|
event.target.select();
|
|
597
647
|
},
|
|
598
648
|
onBlur(event) {
|
|
649
|
+
if (!isInteractive)
|
|
650
|
+
return;
|
|
599
651
|
const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
|
|
600
652
|
send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
|
|
601
653
|
},
|
|
602
654
|
onKeyDown(event) {
|
|
655
|
+
if (!isInteractive)
|
|
656
|
+
return;
|
|
603
657
|
if (event.key === "Enter") {
|
|
604
658
|
const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
|
|
605
659
|
send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
|
|
@@ -638,42 +692,86 @@ function connect(state, send, normalize) {
|
|
|
638
692
|
...parts.swatchGroup.attrs,
|
|
639
693
|
role: "group"
|
|
640
694
|
}),
|
|
695
|
+
getSwatchTriggerState,
|
|
641
696
|
getSwatchTriggerProps(props) {
|
|
642
|
-
const
|
|
643
|
-
const color = normalizeColor(valueProp).toFormat(value.getFormat());
|
|
697
|
+
const triggerState = getSwatchTriggerState(props);
|
|
644
698
|
return normalize.button({
|
|
645
699
|
...parts.swatchTrigger.attrs,
|
|
646
|
-
disabled: isDisabled,
|
|
700
|
+
disabled: triggerState.isDisabled,
|
|
647
701
|
dir: state.context.dir,
|
|
648
702
|
type: "button",
|
|
649
|
-
"
|
|
703
|
+
"aria-label": `select ${triggerState.valueAsString} as the color`,
|
|
704
|
+
"data-state": triggerState.isChecked ? "checked" : "unchecked",
|
|
705
|
+
"data-value": triggerState.valueAsString,
|
|
706
|
+
"data-disabled": dataAttr(triggerState.isDisabled),
|
|
650
707
|
onClick() {
|
|
651
|
-
if (
|
|
708
|
+
if (triggerState.isDisabled)
|
|
652
709
|
return;
|
|
653
|
-
send({ type: "
|
|
710
|
+
send({ type: "SWATCH_TRIGGER.CLICK", value: triggerState.value });
|
|
654
711
|
},
|
|
655
712
|
style: {
|
|
656
713
|
position: "relative"
|
|
657
714
|
}
|
|
658
715
|
});
|
|
659
716
|
},
|
|
717
|
+
getSwatchIndicatorProps(props) {
|
|
718
|
+
const triggerState = getSwatchTriggerState(props);
|
|
719
|
+
return normalize.element({
|
|
720
|
+
...parts.swatchIndicator.attrs,
|
|
721
|
+
dir: state.context.dir,
|
|
722
|
+
hidden: !triggerState.isChecked
|
|
723
|
+
});
|
|
724
|
+
},
|
|
660
725
|
getSwatchProps(props) {
|
|
661
|
-
const {
|
|
662
|
-
const
|
|
663
|
-
const color = colorValue.toFormat(value.getFormat());
|
|
726
|
+
const { respectAlpha = true } = props;
|
|
727
|
+
const triggerState = getSwatchTriggerState(props);
|
|
664
728
|
return normalize.element({
|
|
665
729
|
...parts.swatch.attrs,
|
|
666
730
|
dir: state.context.dir,
|
|
667
|
-
"data-state":
|
|
668
|
-
"data-value":
|
|
731
|
+
"data-state": triggerState.isChecked ? "checked" : "unchecked",
|
|
732
|
+
"data-value": triggerState.valueAsString,
|
|
669
733
|
style: {
|
|
670
734
|
position: "relative",
|
|
671
|
-
background:
|
|
735
|
+
background: triggerState.value.toString(respectAlpha ? "css" : "hex")
|
|
672
736
|
}
|
|
673
737
|
});
|
|
674
|
-
}
|
|
738
|
+
},
|
|
739
|
+
formatTriggerProps: normalize.button({
|
|
740
|
+
...parts.formatTrigger.attrs,
|
|
741
|
+
dir: state.context.dir,
|
|
742
|
+
type: "button",
|
|
743
|
+
"aria-label": `change color format to ${getNextFormat(state.context.format)}`,
|
|
744
|
+
onClick(event) {
|
|
745
|
+
if (event.currentTarget.disabled)
|
|
746
|
+
return;
|
|
747
|
+
const nextFormat = getNextFormat(state.context.format);
|
|
748
|
+
send({ type: "FORMAT.SET", format: nextFormat, src: "format-trigger" });
|
|
749
|
+
}
|
|
750
|
+
}),
|
|
751
|
+
formatSelectProps: normalize.select({
|
|
752
|
+
...parts.formatSelect.attrs,
|
|
753
|
+
"aria-label": "change color format",
|
|
754
|
+
dir: state.context.dir,
|
|
755
|
+
defaultValue: state.context.format,
|
|
756
|
+
disabled: isDisabled,
|
|
757
|
+
onChange(event) {
|
|
758
|
+
const format = assertFormat(event.currentTarget.value);
|
|
759
|
+
send({ type: "FORMAT.SET", format, src: "format-select" });
|
|
760
|
+
}
|
|
761
|
+
})
|
|
675
762
|
};
|
|
676
763
|
}
|
|
764
|
+
var formats = ["hsba", "hsla", "rgba"];
|
|
765
|
+
var formatRegex = new RegExp(`^(${formats.join("|")})$`);
|
|
766
|
+
function getNextFormat(format) {
|
|
767
|
+
const index = formats.indexOf(format);
|
|
768
|
+
return formats[index + 1] ?? formats[0];
|
|
769
|
+
}
|
|
770
|
+
function assertFormat(format) {
|
|
771
|
+
if (formatRegex.test(format))
|
|
772
|
+
return format;
|
|
773
|
+
throw new Error(`Unsupported color format: ${format}`);
|
|
774
|
+
}
|
|
677
775
|
|
|
678
776
|
// src/color-picker.machine.ts
|
|
679
777
|
import { parseColor as parseColor4 } from "@zag-js/color-utils";
|
|
@@ -688,13 +786,8 @@ import { compact, tryCatch } from "@zag-js/utils";
|
|
|
688
786
|
|
|
689
787
|
// src/color-picker.parse.ts
|
|
690
788
|
import { parseColor as parseColor3 } from "@zag-js/color-utils";
|
|
691
|
-
var parse = (
|
|
692
|
-
|
|
693
|
-
const colorFormat = value.getFormat();
|
|
694
|
-
const lockedFormat = colorFormat === "hsla" ? "hsla" : "hsba";
|
|
695
|
-
const result = value.toFormat(lockedFormat);
|
|
696
|
-
result.outputFormat = colorFormat;
|
|
697
|
-
return result;
|
|
789
|
+
var parse = (colorString) => {
|
|
790
|
+
return parseColor3(colorString);
|
|
698
791
|
};
|
|
699
792
|
|
|
700
793
|
// src/color-picker.machine.ts
|
|
@@ -707,13 +800,14 @@ function machine(userContext) {
|
|
|
707
800
|
context: {
|
|
708
801
|
dir: "ltr",
|
|
709
802
|
value: parse("#000000"),
|
|
803
|
+
format: "rgba",
|
|
710
804
|
disabled: false,
|
|
805
|
+
closeOnSelect: false,
|
|
711
806
|
...ctx,
|
|
712
807
|
activeId: null,
|
|
713
808
|
activeChannel: null,
|
|
714
809
|
activeOrientation: null,
|
|
715
810
|
fieldsetDisabled: false,
|
|
716
|
-
autoFocus: true,
|
|
717
811
|
positioning: {
|
|
718
812
|
...ctx.positioning,
|
|
719
813
|
placement: "bottom"
|
|
@@ -723,22 +817,30 @@ function machine(userContext) {
|
|
|
723
817
|
isRtl: (ctx2) => ctx2.dir === "rtl",
|
|
724
818
|
isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
|
|
725
819
|
isInteractive: (ctx2) => !(ctx2.isDisabled || ctx2.readOnly),
|
|
726
|
-
valueAsString: (ctx2) =>
|
|
727
|
-
|
|
728
|
-
|
|
820
|
+
valueAsString: (ctx2) => ctx2.value.toString(ctx2.format),
|
|
821
|
+
areaValue: (ctx2) => {
|
|
822
|
+
const format = ctx2.format.startsWith("hsl") ? "hsla" : "hsba";
|
|
823
|
+
return ctx2.value.toFormat(format);
|
|
729
824
|
}
|
|
730
825
|
},
|
|
731
826
|
activities: ["trackFormControl"],
|
|
732
827
|
watch: {
|
|
733
828
|
value: ["syncInputElements"],
|
|
829
|
+
format: ["syncFormatSelectElement"],
|
|
734
830
|
open: ["toggleVisibility"]
|
|
735
831
|
},
|
|
736
832
|
on: {
|
|
737
833
|
"VALUE.SET": {
|
|
738
834
|
actions: ["setValue"]
|
|
739
835
|
},
|
|
836
|
+
"FORMAT.SET": {
|
|
837
|
+
actions: ["setFormat"]
|
|
838
|
+
},
|
|
740
839
|
"CHANNEL_INPUT.CHANGE": {
|
|
741
840
|
actions: ["setChannelColorFromInput"]
|
|
841
|
+
},
|
|
842
|
+
"EYEDROPPER.CLICK": {
|
|
843
|
+
actions: ["openEyeDropper"]
|
|
742
844
|
}
|
|
743
845
|
},
|
|
744
846
|
states: {
|
|
@@ -776,6 +878,9 @@ function machine(userContext) {
|
|
|
776
878
|
"CHANNEL_INPUT.BLUR": {
|
|
777
879
|
target: "idle",
|
|
778
880
|
actions: ["setChannelColorFromInput"]
|
|
881
|
+
},
|
|
882
|
+
"TRIGGER.BLUR": {
|
|
883
|
+
target: "idle"
|
|
779
884
|
}
|
|
780
885
|
}
|
|
781
886
|
},
|
|
@@ -787,9 +892,6 @@ function machine(userContext) {
|
|
|
787
892
|
target: "idle",
|
|
788
893
|
actions: ["invokeOnClose"]
|
|
789
894
|
},
|
|
790
|
-
"EYEDROPPER.CLICK": {
|
|
791
|
-
actions: ["openEyeDropper"]
|
|
792
|
-
},
|
|
793
895
|
"AREA.POINTER_DOWN": {
|
|
794
896
|
target: "open:dragging",
|
|
795
897
|
actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
|
|
@@ -863,7 +965,17 @@ function machine(userContext) {
|
|
|
863
965
|
CLOSE: {
|
|
864
966
|
target: "idle",
|
|
865
967
|
actions: ["invokeOnClose"]
|
|
866
|
-
}
|
|
968
|
+
},
|
|
969
|
+
"SWATCH_TRIGGER.CLICK": [
|
|
970
|
+
{
|
|
971
|
+
guard: "closeOnSelect",
|
|
972
|
+
target: "focused",
|
|
973
|
+
actions: ["setValue", "setReturnFocus", "invokeOnClose"]
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
actions: ["setValue"]
|
|
977
|
+
}
|
|
978
|
+
]
|
|
867
979
|
}
|
|
868
980
|
},
|
|
869
981
|
"open:dragging": {
|
|
@@ -906,7 +1018,8 @@ function machine(userContext) {
|
|
|
906
1018
|
},
|
|
907
1019
|
{
|
|
908
1020
|
guards: {
|
|
909
|
-
isTargetFocusable: (_ctx, evt) => evt.restoreFocus
|
|
1021
|
+
isTargetFocusable: (_ctx, evt) => evt.restoreFocus,
|
|
1022
|
+
closeOnSelect: (ctx2) => !!ctx2.closeOnSelect
|
|
910
1023
|
},
|
|
911
1024
|
activities: {
|
|
912
1025
|
trackPositioning(ctx2) {
|
|
@@ -1001,9 +1114,9 @@ function machine(userContext) {
|
|
|
1001
1114
|
const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
1002
1115
|
if (!percent)
|
|
1003
1116
|
return;
|
|
1004
|
-
const xValue = ctx2.
|
|
1005
|
-
const yValue = ctx2.
|
|
1006
|
-
const color = ctx2.
|
|
1117
|
+
const xValue = ctx2.areaValue.getChannelPercentValue(xChannel, percent.x);
|
|
1118
|
+
const yValue = ctx2.areaValue.getChannelPercentValue(yChannel, 1 - percent.y);
|
|
1119
|
+
const color = ctx2.areaValue.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
|
|
1007
1120
|
set.value(ctx2, color);
|
|
1008
1121
|
},
|
|
1009
1122
|
setChannelColorFromPoint(ctx2, evt) {
|
|
@@ -1013,13 +1126,16 @@ function machine(userContext) {
|
|
|
1013
1126
|
return;
|
|
1014
1127
|
const orientation = ctx2.activeOrientation || "horizontal";
|
|
1015
1128
|
const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
|
|
1016
|
-
const value = ctx2.
|
|
1017
|
-
const color = ctx2.
|
|
1129
|
+
const value = ctx2.areaValue.getChannelPercentValue(channel, channelPercent);
|
|
1130
|
+
const color = ctx2.areaValue.withChannelValue(channel, value);
|
|
1018
1131
|
set.value(ctx2, color);
|
|
1019
1132
|
},
|
|
1020
1133
|
setValue(ctx2, evt) {
|
|
1021
1134
|
set.value(ctx2, evt.value);
|
|
1022
1135
|
},
|
|
1136
|
+
setFormat(ctx2, evt) {
|
|
1137
|
+
set.format(ctx2, evt.format);
|
|
1138
|
+
},
|
|
1023
1139
|
syncInputElements(ctx2) {
|
|
1024
1140
|
sync.inputs(ctx2);
|
|
1025
1141
|
},
|
|
@@ -1029,26 +1145,22 @@ function machine(userContext) {
|
|
|
1029
1145
|
setChannelColorFromInput(ctx2, evt) {
|
|
1030
1146
|
const { channel, isTextField, value } = evt;
|
|
1031
1147
|
const currentAlpha = ctx2.value.getChannelValue("alpha");
|
|
1148
|
+
let color;
|
|
1032
1149
|
if (channel === "alpha") {
|
|
1033
1150
|
let valueAsNumber = parseFloat(value);
|
|
1034
1151
|
valueAsNumber = Number.isNaN(valueAsNumber) ? currentAlpha : valueAsNumber;
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
}
|
|
1039
|
-
if (isTextField) {
|
|
1040
|
-
const color2 = tryCatch(
|
|
1152
|
+
color = ctx2.value.withChannelValue("alpha", valueAsNumber);
|
|
1153
|
+
} else if (isTextField) {
|
|
1154
|
+
color = tryCatch(
|
|
1041
1155
|
() => parse(value).withChannelValue("alpha", currentAlpha),
|
|
1042
1156
|
() => ctx2.value
|
|
1043
1157
|
);
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
set.value(ctx2, color2);
|
|
1049
|
-
return;
|
|
1158
|
+
} else {
|
|
1159
|
+
const current = ctx2.value.toFormat(ctx2.format);
|
|
1160
|
+
const valueAsNumber = Number.isNaN(value) ? current.getChannelValue(channel) : value;
|
|
1161
|
+
color = current.withChannelValue(channel, valueAsNumber);
|
|
1050
1162
|
}
|
|
1051
|
-
|
|
1163
|
+
sync.inputs(ctx2, color);
|
|
1052
1164
|
set.value(ctx2, color);
|
|
1053
1165
|
},
|
|
1054
1166
|
incrementChannel(ctx2, evt) {
|
|
@@ -1061,22 +1173,22 @@ function machine(userContext) {
|
|
|
1061
1173
|
},
|
|
1062
1174
|
incrementXChannel(ctx2, evt) {
|
|
1063
1175
|
const { xChannel } = evt.channel;
|
|
1064
|
-
const color = ctx2.
|
|
1176
|
+
const color = ctx2.areaValue.incrementChannel(xChannel, evt.step);
|
|
1065
1177
|
set.value(ctx2, color);
|
|
1066
1178
|
},
|
|
1067
1179
|
decrementXChannel(ctx2, evt) {
|
|
1068
1180
|
const { xChannel } = evt.channel;
|
|
1069
|
-
const color = ctx2.
|
|
1181
|
+
const color = ctx2.areaValue.decrementChannel(xChannel, evt.step);
|
|
1070
1182
|
set.value(ctx2, color);
|
|
1071
1183
|
},
|
|
1072
1184
|
incrementYChannel(ctx2, evt) {
|
|
1073
1185
|
const { yChannel } = evt.channel;
|
|
1074
|
-
const color = ctx2.
|
|
1186
|
+
const color = ctx2.areaValue.incrementChannel(yChannel, evt.step);
|
|
1075
1187
|
set.value(ctx2, color);
|
|
1076
1188
|
},
|
|
1077
1189
|
decrementYChannel(ctx2, evt) {
|
|
1078
1190
|
const { yChannel } = evt.channel;
|
|
1079
|
-
const color = ctx2.
|
|
1191
|
+
const color = ctx2.areaValue.decrementChannel(yChannel, evt.step);
|
|
1080
1192
|
set.value(ctx2, color);
|
|
1081
1193
|
},
|
|
1082
1194
|
setChannelToMax(ctx2, evt) {
|
|
@@ -1109,6 +1221,9 @@ function machine(userContext) {
|
|
|
1109
1221
|
dom?.focus(ctx2, dom.getTriggerEl(ctx2));
|
|
1110
1222
|
});
|
|
1111
1223
|
},
|
|
1224
|
+
syncFormatSelectElement(ctx2) {
|
|
1225
|
+
sync.formatSelect(ctx2);
|
|
1226
|
+
},
|
|
1112
1227
|
invokeOnOpen(ctx2) {
|
|
1113
1228
|
ctx2.onOpenChange?.({ open: true });
|
|
1114
1229
|
},
|
|
@@ -1126,41 +1241,56 @@ function machine(userContext) {
|
|
|
1126
1241
|
);
|
|
1127
1242
|
}
|
|
1128
1243
|
var sync = {
|
|
1129
|
-
inputs
|
|
1244
|
+
// sync channel inputs
|
|
1245
|
+
inputs(ctx, color) {
|
|
1130
1246
|
const channelInputs = dom.getChannelInputEls(ctx);
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1247
|
+
raf(() => {
|
|
1248
|
+
channelInputs.forEach((inputEl) => {
|
|
1249
|
+
const channel = inputEl.dataset.channel;
|
|
1250
|
+
dom.setValue(inputEl, getChannelValue(color || ctx.value, channel));
|
|
1251
|
+
});
|
|
1252
|
+
});
|
|
1253
|
+
},
|
|
1254
|
+
// sync format select
|
|
1255
|
+
formatSelect(ctx) {
|
|
1256
|
+
const selectEl = dom.getFormatSelectEl(ctx);
|
|
1257
|
+
raf(() => {
|
|
1258
|
+
dom.setValue(selectEl, ctx.format);
|
|
1134
1259
|
});
|
|
1135
1260
|
}
|
|
1136
1261
|
};
|
|
1137
1262
|
var invoke = {
|
|
1138
1263
|
changeEnd(ctx) {
|
|
1264
|
+
const value = ctx.value.toFormat(ctx.format);
|
|
1139
1265
|
ctx.onValueChangeEnd?.({
|
|
1140
|
-
value
|
|
1266
|
+
value,
|
|
1141
1267
|
valueAsString: ctx.valueAsString
|
|
1142
1268
|
});
|
|
1143
1269
|
},
|
|
1144
1270
|
change(ctx) {
|
|
1271
|
+
const value = ctx.value.toFormat(ctx.format);
|
|
1145
1272
|
ctx.onValueChange?.({
|
|
1146
|
-
value
|
|
1273
|
+
value,
|
|
1147
1274
|
valueAsString: ctx.valueAsString
|
|
1148
1275
|
});
|
|
1149
1276
|
dispatchInputValueEvent(dom.getHiddenInputEl(ctx), { value: ctx.valueAsString });
|
|
1277
|
+
},
|
|
1278
|
+
formatChange(ctx) {
|
|
1279
|
+
ctx.onFormatChange?.({ format: ctx.format });
|
|
1150
1280
|
}
|
|
1151
1281
|
};
|
|
1152
1282
|
var set = {
|
|
1153
1283
|
value(ctx, color) {
|
|
1154
1284
|
if (!color || ctx.value.isEqual(color))
|
|
1155
1285
|
return;
|
|
1156
|
-
|
|
1157
|
-
const outputColor = color.toFormat(currentFormat);
|
|
1158
|
-
try {
|
|
1159
|
-
outputColor.outputFormat = ctx.value.outputFormat;
|
|
1160
|
-
} catch {
|
|
1161
|
-
}
|
|
1162
|
-
ctx.value = outputColor;
|
|
1286
|
+
ctx.value = color;
|
|
1163
1287
|
invoke.change(ctx);
|
|
1288
|
+
},
|
|
1289
|
+
format(ctx, format) {
|
|
1290
|
+
if (ctx.format === format)
|
|
1291
|
+
return;
|
|
1292
|
+
ctx.format = format;
|
|
1293
|
+
invoke.formatChange(ctx);
|
|
1164
1294
|
}
|
|
1165
1295
|
};
|
|
1166
1296
|
export {
|