@zag-js/color-picker 0.12.0 → 0.14.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 +51 -37
- package/dist/index.d.ts +51 -37
- package/dist/index.js +98 -51
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -51
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -10
- package/src/color-picker.anatomy.ts +4 -3
- package/src/color-picker.connect.ts +31 -5
- package/src/color-picker.dom.ts +14 -8
- package/src/color-picker.machine.ts +33 -16
- package/src/color-picker.types.ts +57 -44
package/dist/index.mjs
CHANGED
|
@@ -5,14 +5,15 @@ var anatomy = createAnatomy("color-picker", [
|
|
|
5
5
|
"areaThumb",
|
|
6
6
|
"areaGradient",
|
|
7
7
|
"channelSliderTrack",
|
|
8
|
-
"
|
|
8
|
+
"channelSliderTrackBackground",
|
|
9
9
|
"channelSliderThumb",
|
|
10
10
|
"channelInput",
|
|
11
11
|
"swatch",
|
|
12
|
-
"
|
|
12
|
+
"swatchBackground",
|
|
13
13
|
"content",
|
|
14
14
|
"label",
|
|
15
|
-
"
|
|
15
|
+
"hiddenInput",
|
|
16
|
+
"eyeDropperTrigger"
|
|
16
17
|
]);
|
|
17
18
|
var parts = anatomy.build();
|
|
18
19
|
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
isModifiedEvent
|
|
28
29
|
} from "@zag-js/dom-event";
|
|
29
30
|
import { dataAttr } from "@zag-js/dom-query";
|
|
31
|
+
import { visuallyHiddenStyle } from "@zag-js/visually-hidden";
|
|
30
32
|
|
|
31
33
|
// src/color-picker.dom.ts
|
|
32
34
|
import { getRelativePoint } from "@zag-js/dom-event";
|
|
@@ -39,20 +41,28 @@ var dom = createScope({
|
|
|
39
41
|
getChannelSliderTrackId: (ctx, channel) => ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
|
|
40
42
|
getChannelInputId: (ctx, channel) => ctx.ids?.channelInput?.(channel) ?? `color-picker:${ctx.id}:input:${channel}`,
|
|
41
43
|
getChannelSliderThumbId: (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
getHiddenInputId: (ctx) => `color-picker:${ctx.id}:hidden-input`,
|
|
45
|
+
getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
|
|
46
|
+
getAreaThumbEl: (ctx) => dom.getById(ctx, dom.getAreaThumbId(ctx)),
|
|
47
|
+
getChannelSliderThumbEl: (ctx, channel) => dom.getById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
|
|
48
|
+
getChannelInputEl: (ctx, channel) => dom.getById(ctx, dom.getChannelInputId(ctx, channel)),
|
|
49
|
+
getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
|
|
50
|
+
getAreaEl: (ctx) => dom.getById(ctx, dom.getAreaId(ctx)),
|
|
47
51
|
getAreaValueFromPoint(ctx, point) {
|
|
48
|
-
const
|
|
52
|
+
const areaEl = dom.getAreaEl(ctx);
|
|
53
|
+
if (!areaEl)
|
|
54
|
+
return;
|
|
55
|
+
const { percent } = getRelativePoint(point, areaEl);
|
|
49
56
|
return percent;
|
|
50
57
|
},
|
|
51
58
|
getChannelSliderTrackEl: (ctx, channel) => {
|
|
52
|
-
return dom.
|
|
59
|
+
return dom.getById(ctx, dom.getChannelSliderTrackId(ctx, channel));
|
|
53
60
|
},
|
|
54
61
|
getChannelSliderValueFromPoint(ctx, point, channel) {
|
|
55
|
-
const
|
|
62
|
+
const trackEl = dom.getChannelSliderTrackEl(ctx, channel);
|
|
63
|
+
if (!trackEl)
|
|
64
|
+
return;
|
|
65
|
+
const { percent } = getRelativePoint(point, trackEl);
|
|
56
66
|
return percent;
|
|
57
67
|
},
|
|
58
68
|
getChannelInputEls: (ctx) => {
|
|
@@ -376,25 +386,31 @@ var getSliderBgImage = (ctx, props) => {
|
|
|
376
386
|
// src/color-picker.connect.ts
|
|
377
387
|
function connect(state, send, normalize) {
|
|
378
388
|
const valueAsColor = state.context.valueAsColor;
|
|
389
|
+
const value = state.context.value;
|
|
379
390
|
const isDisabled = state.context.disabled;
|
|
380
391
|
const isInteractive = state.context.isInteractive;
|
|
381
392
|
const isDragging = state.matches("dragging");
|
|
382
393
|
const channels = valueAsColor.getColorChannels();
|
|
383
394
|
return {
|
|
384
395
|
isDragging,
|
|
385
|
-
value
|
|
396
|
+
value,
|
|
386
397
|
valueAsColor,
|
|
398
|
+
alpha: valueAsColor.getChannelValue("alpha"),
|
|
387
399
|
channels,
|
|
388
|
-
setColor(
|
|
389
|
-
send({ type: "VALUE.SET", value: normalizeColor(
|
|
400
|
+
setColor(value2) {
|
|
401
|
+
send({ type: "VALUE.SET", value: normalizeColor(value2), src: "set-color" });
|
|
390
402
|
},
|
|
391
|
-
setChannelValue(channel,
|
|
392
|
-
const color = valueAsColor.withChannelValue(channel,
|
|
403
|
+
setChannelValue(channel, value2) {
|
|
404
|
+
const color = valueAsColor.withChannelValue(channel, value2);
|
|
393
405
|
send({ type: "VALUE.SET", value: color, src: "set-channel" });
|
|
394
406
|
},
|
|
395
407
|
setFormat(format) {
|
|
396
|
-
const
|
|
397
|
-
send({ type: "VALUE.SET", value, src: "set-format" });
|
|
408
|
+
const value2 = valueAsColor.toFormat(format);
|
|
409
|
+
send({ type: "VALUE.SET", value: value2, src: "set-format" });
|
|
410
|
+
},
|
|
411
|
+
setAlpha(value2) {
|
|
412
|
+
const color = valueAsColor.withChannelValue("alpha", value2);
|
|
413
|
+
send({ type: "VALUE.SET", value: color, src: "set-alpha" });
|
|
398
414
|
},
|
|
399
415
|
contentProps: normalize.element({
|
|
400
416
|
...parts.content.attrs,
|
|
@@ -525,7 +541,7 @@ function connect(state, send, normalize) {
|
|
|
525
541
|
getChannelSliderBackgroundProps(props) {
|
|
526
542
|
const { orientation = "horizontal", channel } = props;
|
|
527
543
|
return normalize.element({
|
|
528
|
-
...parts.
|
|
544
|
+
...parts.channelSliderTrackBackground.attrs,
|
|
529
545
|
"data-orientation": orientation,
|
|
530
546
|
"data-channel": channel,
|
|
531
547
|
style: {
|
|
@@ -641,19 +657,19 @@ function connect(state, send, normalize) {
|
|
|
641
657
|
onChange(event) {
|
|
642
658
|
if (isTextField)
|
|
643
659
|
return;
|
|
644
|
-
const
|
|
645
|
-
send({ type: "CHANNEL_INPUT.CHANGE", channel, value, isTextField });
|
|
660
|
+
const value2 = event.currentTarget.value;
|
|
661
|
+
send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
|
|
646
662
|
},
|
|
647
663
|
onBlur(event) {
|
|
648
|
-
const
|
|
649
|
-
send({ type: "CHANNEL_INPUT.BLUR", channel, value, isTextField });
|
|
664
|
+
const value2 = event.currentTarget.value;
|
|
665
|
+
send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
|
|
650
666
|
},
|
|
651
667
|
onKeyDown(event) {
|
|
652
668
|
if (!isTextField)
|
|
653
669
|
return;
|
|
654
670
|
if (event.key === "Enter") {
|
|
655
|
-
const
|
|
656
|
-
send({ type: "CHANNEL_INPUT.CHANGE", channel, value, isTextField });
|
|
671
|
+
const value2 = event.currentTarget.value;
|
|
672
|
+
send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
|
|
657
673
|
}
|
|
658
674
|
},
|
|
659
675
|
style: {
|
|
@@ -663,17 +679,35 @@ function connect(state, send, normalize) {
|
|
|
663
679
|
}
|
|
664
680
|
});
|
|
665
681
|
},
|
|
682
|
+
hiddenInputProps: normalize.input({
|
|
683
|
+
...parts.hiddenInput.attrs,
|
|
684
|
+
type: "text",
|
|
685
|
+
disabled: isDisabled,
|
|
686
|
+
name: state.context.name,
|
|
687
|
+
id: dom.getHiddenInputId(state.context),
|
|
688
|
+
style: visuallyHiddenStyle,
|
|
689
|
+
defaultValue: value,
|
|
690
|
+
onChange(event) {
|
|
691
|
+
const value2 = event.currentTarget.value;
|
|
692
|
+
send({ type: "VALUE.SET", value: value2, src: "input.change" });
|
|
693
|
+
}
|
|
694
|
+
}),
|
|
666
695
|
eyeDropperTriggerProps: normalize.button({
|
|
667
|
-
...parts.
|
|
696
|
+
...parts.eyeDropperTrigger.attrs,
|
|
697
|
+
disabled: isDisabled,
|
|
698
|
+
"data-disabled": dataAttr(isDisabled),
|
|
699
|
+
"aria-label": "Pick a color from the screen",
|
|
668
700
|
onClick() {
|
|
701
|
+
if (!isInteractive)
|
|
702
|
+
return;
|
|
669
703
|
send("EYEDROPPER.CLICK");
|
|
670
704
|
}
|
|
671
705
|
}),
|
|
672
706
|
getSwatchBackgroundProps(props) {
|
|
673
|
-
const { value } = props;
|
|
674
|
-
const alpha = normalizeColor(
|
|
707
|
+
const { value: value2 } = props;
|
|
708
|
+
const alpha = normalizeColor(value2).getChannelValue("alpha");
|
|
675
709
|
return normalize.element({
|
|
676
|
-
...parts.
|
|
710
|
+
...parts.swatchBackground.attrs,
|
|
677
711
|
"data-alpha": alpha,
|
|
678
712
|
style: {
|
|
679
713
|
width: "100%",
|
|
@@ -694,12 +728,12 @@ function connect(state, send, normalize) {
|
|
|
694
728
|
});
|
|
695
729
|
},
|
|
696
730
|
getSwatchProps(props) {
|
|
697
|
-
const { value, readOnly } = props;
|
|
698
|
-
const color = normalizeColor(
|
|
731
|
+
const { value: value2, readOnly } = props;
|
|
732
|
+
const color = normalizeColor(value2).toFormat(valueAsColor.getColorSpace());
|
|
699
733
|
return normalize.element({
|
|
700
734
|
...parts.swatch.attrs,
|
|
701
735
|
onClick() {
|
|
702
|
-
if (readOnly)
|
|
736
|
+
if (readOnly || !isInteractive)
|
|
703
737
|
return;
|
|
704
738
|
send({ type: "VALUE.SET", value: color });
|
|
705
739
|
},
|
|
@@ -717,6 +751,7 @@ import { parseColor as parseColor2 } from "@zag-js/color-utils";
|
|
|
717
751
|
import { createMachine } from "@zag-js/core";
|
|
718
752
|
import { trackPointerMove } from "@zag-js/dom-event";
|
|
719
753
|
import { raf } from "@zag-js/dom-query";
|
|
754
|
+
import { trackFormControl } from "@zag-js/form-utils";
|
|
720
755
|
import { clampValue, getPercentValue as getPercentValue2, snapValueToStep as snapValueToStep2 } from "@zag-js/numeric-range";
|
|
721
756
|
import { disableTextSelection } from "@zag-js/text-selection";
|
|
722
757
|
import { compact } from "@zag-js/utils";
|
|
@@ -732,21 +767,21 @@ function machine(userContext) {
|
|
|
732
767
|
activeChannel: null,
|
|
733
768
|
activeOrientation: null,
|
|
734
769
|
value: "#D9D9D9",
|
|
735
|
-
...ctx
|
|
736
|
-
valueAsColor: parseColor2(ctx.value || "#D9D9D9")
|
|
770
|
+
...ctx
|
|
737
771
|
},
|
|
738
772
|
computed: {
|
|
739
773
|
isRtl: (ctx2) => ctx2.dir === "rtl",
|
|
740
|
-
isInteractive: (ctx2) => !(ctx2.disabled || ctx2.readOnly)
|
|
774
|
+
isInteractive: (ctx2) => !(ctx2.disabled || ctx2.readOnly),
|
|
775
|
+
valueAsColor: (ctx2) => parseColor2(ctx2.value)
|
|
741
776
|
},
|
|
742
777
|
on: {
|
|
743
778
|
"VALUE.SET": {
|
|
744
779
|
actions: ["setValue"]
|
|
745
780
|
}
|
|
746
781
|
},
|
|
747
|
-
|
|
782
|
+
activities: ["trackFormControl"],
|
|
748
783
|
watch: {
|
|
749
|
-
value: ["
|
|
784
|
+
value: ["syncInputElements", "invokeOnChange"]
|
|
750
785
|
},
|
|
751
786
|
states: {
|
|
752
787
|
idle: {
|
|
@@ -766,6 +801,10 @@ function machine(userContext) {
|
|
|
766
801
|
target: "dragging",
|
|
767
802
|
actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
|
|
768
803
|
},
|
|
804
|
+
"CHANNEL_SLIDER.FOCUS": {
|
|
805
|
+
target: "focused",
|
|
806
|
+
actions: ["setActiveChannel"]
|
|
807
|
+
},
|
|
769
808
|
"CHANNEL_INPUT.FOCUS": {
|
|
770
809
|
target: "focused",
|
|
771
810
|
actions: ["setActiveChannel"]
|
|
@@ -876,6 +915,17 @@ function machine(userContext) {
|
|
|
876
915
|
isTextField: (_ctx, evt) => !!evt.isTextField
|
|
877
916
|
},
|
|
878
917
|
activities: {
|
|
918
|
+
trackFormControl(ctx2, _evt, { send, initialContext }) {
|
|
919
|
+
const inputEl = dom.getHiddenInputEl(ctx2);
|
|
920
|
+
return trackFormControl(inputEl, {
|
|
921
|
+
onFieldsetDisabled() {
|
|
922
|
+
ctx2.disabled = true;
|
|
923
|
+
},
|
|
924
|
+
onFormReset() {
|
|
925
|
+
send({ type: "VALUE.SET", value: initialContext.value, src: "form.reset" });
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
},
|
|
879
929
|
trackPointerMove(ctx2, _evt, { send }) {
|
|
880
930
|
return trackPointerMove(dom.getDoc(ctx2), {
|
|
881
931
|
onPointerMove({ point }) {
|
|
@@ -923,6 +973,8 @@ function machine(userContext) {
|
|
|
923
973
|
setAreaColorFromPoint(ctx2, evt) {
|
|
924
974
|
const { xChannel, yChannel } = evt.channel || ctx2.activeChannel;
|
|
925
975
|
const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
976
|
+
if (!percent)
|
|
977
|
+
return;
|
|
926
978
|
const { getColorFromPoint } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
927
979
|
const color = getColorFromPoint(percent.x, percent.y);
|
|
928
980
|
if (!color)
|
|
@@ -932,6 +984,8 @@ function machine(userContext) {
|
|
|
932
984
|
setChannelColorFromPoint(ctx2, evt) {
|
|
933
985
|
const channel = evt.channel || ctx2.activeId;
|
|
934
986
|
const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
|
|
987
|
+
if (!percent)
|
|
988
|
+
return;
|
|
935
989
|
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(channel);
|
|
936
990
|
const orientation = ctx2.activeOrientation || "horizontal";
|
|
937
991
|
const point = orientation === "horizontal" ? percent.x : percent.y;
|
|
@@ -943,24 +997,18 @@ function machine(userContext) {
|
|
|
943
997
|
setValue(ctx2, evt) {
|
|
944
998
|
setColor(ctx2, evt.value);
|
|
945
999
|
},
|
|
946
|
-
|
|
947
|
-
try {
|
|
948
|
-
const color = parseColor2(ctx2.value);
|
|
949
|
-
if (color.isEqual(ctx2.valueAsColor))
|
|
950
|
-
return;
|
|
951
|
-
ctx2.valueAsColor = color;
|
|
952
|
-
} catch {
|
|
953
|
-
}
|
|
954
|
-
},
|
|
955
|
-
syncChannelInputs(ctx2) {
|
|
1000
|
+
syncInputElements(ctx2) {
|
|
956
1001
|
const inputs = dom.getChannelInputEls(ctx2);
|
|
957
1002
|
inputs.forEach((input) => {
|
|
958
|
-
const channel = input.
|
|
1003
|
+
const channel = input.dataset.channel;
|
|
959
1004
|
if (!channel)
|
|
960
1005
|
return;
|
|
961
|
-
|
|
962
|
-
input.value = value.toString();
|
|
1006
|
+
input.value = getChannelInputValue(ctx2.valueAsColor, channel);
|
|
963
1007
|
});
|
|
1008
|
+
const hiddenInput = dom.getHiddenInputEl(ctx2);
|
|
1009
|
+
if (!hiddenInput)
|
|
1010
|
+
return;
|
|
1011
|
+
hiddenInput.value = ctx2.value;
|
|
964
1012
|
},
|
|
965
1013
|
setChannelColorFromInput(ctx2, evt) {
|
|
966
1014
|
const { channel, isTextField, value } = evt;
|
|
@@ -1045,7 +1093,6 @@ function machine(userContext) {
|
|
|
1045
1093
|
}
|
|
1046
1094
|
var setColor = (ctx, color) => {
|
|
1047
1095
|
ctx.value = color.toString("css");
|
|
1048
|
-
ctx.valueAsColor = color;
|
|
1049
1096
|
};
|
|
1050
1097
|
export {
|
|
1051
1098
|
anatomy,
|