@zag-js/color-picker 0.23.0 → 0.25.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 +101 -32
- package/dist/index.d.ts +101 -32
- package/dist/index.js +516 -300
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +515 -303
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -12
- package/src/color-picker.anatomy.ts +11 -5
- package/src/color-picker.connect.ts +206 -124
- package/src/color-picker.dom.ts +26 -4
- package/src/color-picker.machine.ts +240 -128
- package/src/color-picker.parse.ts +14 -0
- package/src/color-picker.types.ts +110 -30
- package/src/index.ts +9 -6
- package/src/utils/get-channel-input-value.ts +45 -11
- package/src/utils/get-slider-background.ts +14 -12
- package/src/utils/get-channel-details.ts +0 -60
package/dist/index.mjs
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
// src/color-picker.anatomy.ts
|
|
2
2
|
import { createAnatomy } from "@zag-js/anatomy";
|
|
3
3
|
var anatomy = createAnatomy("color-picker", [
|
|
4
|
+
"root",
|
|
5
|
+
"label",
|
|
6
|
+
"control",
|
|
7
|
+
"trigger",
|
|
8
|
+
"positioner",
|
|
9
|
+
"content",
|
|
4
10
|
"area",
|
|
5
11
|
"areaThumb",
|
|
6
|
-
"
|
|
12
|
+
"areaBackground",
|
|
13
|
+
"channelSlider",
|
|
7
14
|
"channelSliderTrack",
|
|
8
|
-
"channelSliderTrackBackground",
|
|
9
15
|
"channelSliderThumb",
|
|
10
16
|
"channelInput",
|
|
17
|
+
"transparencyGrid",
|
|
18
|
+
"swatchGroup",
|
|
19
|
+
"swatchTrigger",
|
|
11
20
|
"swatch",
|
|
12
|
-
"swatchBackground",
|
|
13
|
-
"content",
|
|
14
|
-
"label",
|
|
15
21
|
"eyeDropperTrigger"
|
|
16
22
|
]);
|
|
17
23
|
var parts = anatomy.build();
|
|
18
24
|
|
|
19
25
|
// src/color-picker.connect.ts
|
|
20
|
-
import {
|
|
21
|
-
getColorAreaGradient,
|
|
22
|
-
normalizeColor
|
|
23
|
-
} from "@zag-js/color-utils";
|
|
26
|
+
import { getColorAreaGradient, normalizeColor } from "@zag-js/color-utils";
|
|
24
27
|
import {
|
|
25
28
|
getEventKey,
|
|
26
29
|
getEventPoint,
|
|
@@ -29,21 +32,29 @@ import {
|
|
|
29
32
|
isLeftClick,
|
|
30
33
|
isModifiedEvent
|
|
31
34
|
} from "@zag-js/dom-event";
|
|
32
|
-
import { dataAttr,
|
|
35
|
+
import { dataAttr, query } from "@zag-js/dom-query";
|
|
36
|
+
import { getPlacementStyles } from "@zag-js/popper";
|
|
33
37
|
import { visuallyHiddenStyle } from "@zag-js/visually-hidden";
|
|
34
38
|
|
|
35
39
|
// src/color-picker.dom.ts
|
|
36
40
|
import { getRelativePoint } from "@zag-js/dom-event";
|
|
37
41
|
import { createScope, queryAll } from "@zag-js/dom-query";
|
|
42
|
+
import { getFirstFocusable } from "@zag-js/tabbable";
|
|
43
|
+
import { runIfFn } from "@zag-js/utils";
|
|
38
44
|
var dom = createScope({
|
|
45
|
+
getRootId: (ctx) => ctx.ids?.root ?? `color-picker:${ctx.id}`,
|
|
46
|
+
getLabelId: (ctx) => ctx.ids?.label ?? `color-picker:${ctx.id}:label`,
|
|
47
|
+
getHiddenInputId: (ctx) => `color-picker:${ctx.id}:hidden-input`,
|
|
48
|
+
getControlId: (ctx) => ctx.ids?.control ?? `color-picker:${ctx.id}:control`,
|
|
49
|
+
getTriggerId: (ctx) => ctx.ids?.trigger ?? `color-picker:${ctx.id}:trigger`,
|
|
39
50
|
getContentId: (ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`,
|
|
51
|
+
getPositionerId: (ctx) => `color-picker:${ctx.id}:positioner`,
|
|
40
52
|
getAreaId: (ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`,
|
|
41
53
|
getAreaGradientId: (ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`,
|
|
42
54
|
getAreaThumbId: (ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`,
|
|
43
|
-
|
|
55
|
+
getChannelSliderId: (ctx, channel) => ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
|
|
44
56
|
getChannelInputId: (ctx, channel) => ctx.ids?.channelInput?.(channel) ?? `color-picker:${ctx.id}:input:${channel}`,
|
|
45
57
|
getChannelSliderThumbId: (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
|
|
46
|
-
getHiddenInputId: (ctx) => `color-picker:${ctx.id}:hidden-input`,
|
|
47
58
|
getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
|
|
48
59
|
getAreaThumbEl: (ctx) => dom.getById(ctx, dom.getAreaThumbId(ctx)),
|
|
49
60
|
getChannelSliderThumbEl: (ctx, channel) => dom.getById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
|
|
@@ -57,8 +68,11 @@ var dom = createScope({
|
|
|
57
68
|
const { percent } = getRelativePoint(point, areaEl);
|
|
58
69
|
return percent;
|
|
59
70
|
},
|
|
71
|
+
getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
|
|
72
|
+
getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
|
|
73
|
+
getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
|
|
60
74
|
getChannelSliderTrackEl: (ctx, channel) => {
|
|
61
|
-
return dom.getById(ctx, dom.
|
|
75
|
+
return dom.getById(ctx, dom.getChannelSliderId(ctx, channel));
|
|
62
76
|
},
|
|
63
77
|
getChannelSliderValueFromPoint(ctx, point, channel) {
|
|
64
78
|
const trackEl = dom.getChannelSliderTrackEl(ctx, channel);
|
|
@@ -68,62 +82,22 @@ var dom = createScope({
|
|
|
68
82
|
return percent;
|
|
69
83
|
},
|
|
70
84
|
getChannelInputEls: (ctx) => {
|
|
71
|
-
return
|
|
85
|
+
return [
|
|
86
|
+
...queryAll(dom.getContentEl(ctx), "input[data-channel]"),
|
|
87
|
+
...queryAll(dom.getControlEl(ctx), "input[data-channel]")
|
|
88
|
+
];
|
|
89
|
+
},
|
|
90
|
+
getFirstFocusableEl: (ctx) => getFirstFocusable(dom.getContentEl(ctx), "if-empty"),
|
|
91
|
+
getInitialFocusEl: (ctx) => {
|
|
92
|
+
let el = runIfFn(ctx.initialFocusEl);
|
|
93
|
+
if (!el && ctx.autoFocus)
|
|
94
|
+
el = dom.getFirstFocusableEl(ctx);
|
|
95
|
+
if (!el)
|
|
96
|
+
el = dom.getContentEl(ctx);
|
|
97
|
+
return el;
|
|
72
98
|
}
|
|
73
99
|
});
|
|
74
100
|
|
|
75
|
-
// src/utils/get-channel-details.ts
|
|
76
|
-
import { getPercentValue, snapValueToStep } from "@zag-js/numeric-range";
|
|
77
|
-
function getChannelDetails(color, xChannel, yChannel) {
|
|
78
|
-
const channels = color.getColorSpaceAxes({ xChannel, yChannel });
|
|
79
|
-
const xChannelRange = color.getChannelRange(channels.xChannel);
|
|
80
|
-
const yChannelRange = color.getChannelRange(channels.yChannel);
|
|
81
|
-
const { minValue: minValueX, maxValue: maxValueX, step: stepX, pageSize: pageSizeX } = xChannelRange;
|
|
82
|
-
const { minValue: minValueY, maxValue: maxValueY, step: stepY, pageSize: pageSizeY } = yChannelRange;
|
|
83
|
-
const xValue = color.getChannelValue(channels.xChannel);
|
|
84
|
-
const yValue = color.getChannelValue(channels.yChannel);
|
|
85
|
-
return {
|
|
86
|
-
channels,
|
|
87
|
-
xChannelStep: stepX,
|
|
88
|
-
yChannelStep: stepY,
|
|
89
|
-
xChannelPageStep: pageSizeX,
|
|
90
|
-
yChannelPageStep: pageSizeY,
|
|
91
|
-
xValue,
|
|
92
|
-
yValue,
|
|
93
|
-
getThumbPosition() {
|
|
94
|
-
let x = (xValue - minValueX) / (maxValueX - minValueX);
|
|
95
|
-
let y = 1 - (yValue - minValueY) / (maxValueY - minValueY);
|
|
96
|
-
return { x, y };
|
|
97
|
-
},
|
|
98
|
-
incrementX(stepSize) {
|
|
99
|
-
return xValue + stepSize > maxValueX ? maxValueX : snapValueToStep(xValue + stepSize, minValueX, maxValueX, stepX);
|
|
100
|
-
},
|
|
101
|
-
incrementY(stepSize) {
|
|
102
|
-
return yValue + stepSize > maxValueY ? maxValueY : snapValueToStep(yValue + stepSize, minValueY, maxValueY, stepY);
|
|
103
|
-
},
|
|
104
|
-
decrementX(stepSize) {
|
|
105
|
-
return snapValueToStep(xValue - stepSize, minValueX, maxValueX, stepX);
|
|
106
|
-
},
|
|
107
|
-
decrementY(stepSize) {
|
|
108
|
-
return snapValueToStep(yValue - stepSize, minValueY, maxValueY, stepY);
|
|
109
|
-
},
|
|
110
|
-
getColorFromPoint(x, y) {
|
|
111
|
-
let newXValue = getPercentValue(x, minValueX, maxValueX, stepX);
|
|
112
|
-
let newYValue = getPercentValue(1 - y, minValueY, maxValueY, stepY);
|
|
113
|
-
let newColor;
|
|
114
|
-
if (newXValue !== xValue) {
|
|
115
|
-
newXValue = snapValueToStep(newXValue, minValueX, maxValueX, stepX);
|
|
116
|
-
newColor = color.withChannelValue(channels.xChannel, newXValue);
|
|
117
|
-
}
|
|
118
|
-
if (newYValue !== yValue) {
|
|
119
|
-
newYValue = snapValueToStep(newYValue, minValueY, maxValueY, stepY);
|
|
120
|
-
newColor = (newColor || color).withChannelValue(channels.yChannel, newYValue);
|
|
121
|
-
}
|
|
122
|
-
return newColor;
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
101
|
// src/utils/get-channel-display-color.ts
|
|
128
102
|
import { parseColor } from "@zag-js/color-utils";
|
|
129
103
|
function getChannelDisplayColor(color, channel) {
|
|
@@ -146,31 +120,48 @@ function getChannelDisplayColor(color, channel) {
|
|
|
146
120
|
}
|
|
147
121
|
|
|
148
122
|
// src/utils/get-channel-input-value.ts
|
|
149
|
-
|
|
123
|
+
import { parseColor as parseColor2 } from "@zag-js/color-utils";
|
|
124
|
+
function getChannelValue(color, channel) {
|
|
150
125
|
if (channel == null)
|
|
151
|
-
return;
|
|
126
|
+
return "";
|
|
127
|
+
if (channel === "hex") {
|
|
128
|
+
return color.toString("hex");
|
|
129
|
+
}
|
|
130
|
+
if (channel === "css") {
|
|
131
|
+
return color.toString("css");
|
|
132
|
+
}
|
|
133
|
+
if (channel in color) {
|
|
134
|
+
return color.getChannelValue(channel).toString();
|
|
135
|
+
}
|
|
136
|
+
const isHSL = color.getFormat() === "hsl";
|
|
152
137
|
switch (channel) {
|
|
153
|
-
case "hex":
|
|
154
|
-
return color.toString("hex");
|
|
155
|
-
case "css":
|
|
156
|
-
return color.toString("css");
|
|
157
138
|
case "hue":
|
|
139
|
+
return isHSL ? color.toFormat("hsla").getChannelValue("hue").toString() : color.toFormat("hsba").getChannelValue("hue").toString();
|
|
158
140
|
case "saturation":
|
|
141
|
+
return isHSL ? color.toFormat("hsl").getChannelValue("saturation").toString() : color.toFormat("hsb").getChannelValue("saturation").toString();
|
|
159
142
|
case "lightness":
|
|
160
|
-
return color.toFormat("
|
|
143
|
+
return color.toFormat("hsla").getChannelValue("lightness").toString();
|
|
161
144
|
case "brightness":
|
|
162
|
-
return color.toFormat("
|
|
145
|
+
return color.toFormat("hsba").getChannelValue("brightness").toString();
|
|
163
146
|
case "red":
|
|
164
147
|
case "green":
|
|
165
148
|
case "blue":
|
|
166
|
-
return color.toFormat("
|
|
149
|
+
return color.toFormat("rgba").getChannelValue(channel).toString();
|
|
167
150
|
default:
|
|
168
151
|
return color.getChannelValue(channel).toString();
|
|
169
152
|
}
|
|
170
153
|
}
|
|
171
|
-
function
|
|
154
|
+
function getChannelRange(color, channel) {
|
|
172
155
|
switch (channel) {
|
|
173
156
|
case "hex":
|
|
157
|
+
const minColor = parseColor2("#000000");
|
|
158
|
+
const maxColor = parseColor2("#FFFFFF");
|
|
159
|
+
return {
|
|
160
|
+
minValue: minColor.toHexInt(),
|
|
161
|
+
maxValue: maxColor.toHexInt(),
|
|
162
|
+
pageSize: 10,
|
|
163
|
+
step: 1
|
|
164
|
+
};
|
|
174
165
|
case "css":
|
|
175
166
|
return void 0;
|
|
176
167
|
case "hue":
|
|
@@ -189,7 +180,7 @@ function getChannelInputRange(color, channel) {
|
|
|
189
180
|
}
|
|
190
181
|
|
|
191
182
|
// src/utils/get-slider-background.ts
|
|
192
|
-
function
|
|
183
|
+
function getSliderBackgroundDirection(orientation, dir) {
|
|
193
184
|
if (orientation === "vertical") {
|
|
194
185
|
return "top";
|
|
195
186
|
} else if (dir === "ltr") {
|
|
@@ -198,19 +189,18 @@ function getSliderBgDirection(orientation, dir) {
|
|
|
198
189
|
return "left";
|
|
199
190
|
}
|
|
200
191
|
}
|
|
201
|
-
var
|
|
202
|
-
const { channel } = props;
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
const { minValue, maxValue } = ctx.valueAsColor.getChannelRange(channel);
|
|
192
|
+
var getSliderBackground = (props) => {
|
|
193
|
+
const { channel, value, dir } = props;
|
|
194
|
+
const bgDirection = getSliderBackgroundDirection(props.orientation, dir);
|
|
195
|
+
const { minValue, maxValue } = value.getChannelRange(channel);
|
|
206
196
|
switch (channel) {
|
|
207
197
|
case "hue":
|
|
208
|
-
return `linear-gradient(to ${
|
|
198
|
+
return `linear-gradient(to ${bgDirection}, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`;
|
|
209
199
|
case "lightness": {
|
|
210
|
-
let start =
|
|
200
|
+
let start = value.withChannelValue(channel, minValue).toString("css");
|
|
211
201
|
let middle = value.withChannelValue(channel, (maxValue - minValue) / 2).toString("css");
|
|
212
202
|
let end = value.withChannelValue(channel, maxValue).toString("css");
|
|
213
|
-
return `linear-gradient(to ${
|
|
203
|
+
return `linear-gradient(to ${bgDirection}, ${start}, ${middle}, ${end})`;
|
|
214
204
|
}
|
|
215
205
|
case "saturation":
|
|
216
206
|
case "brightness":
|
|
@@ -220,7 +210,7 @@ var getSliderBgImage = (ctx, props) => {
|
|
|
220
210
|
case "alpha": {
|
|
221
211
|
let start = value.withChannelValue(channel, minValue).toString("css");
|
|
222
212
|
let end = value.withChannelValue(channel, maxValue).toString("css");
|
|
223
|
-
return `linear-gradient(to ${
|
|
213
|
+
return `linear-gradient(to ${bgDirection}, ${start}, ${end})`;
|
|
224
214
|
}
|
|
225
215
|
default:
|
|
226
216
|
throw new Error("Unknown color channel: " + channel);
|
|
@@ -229,41 +219,113 @@ var getSliderBgImage = (ctx, props) => {
|
|
|
229
219
|
|
|
230
220
|
// src/color-picker.connect.ts
|
|
231
221
|
function connect(state, send, normalize) {
|
|
232
|
-
const valueAsColor = state.context.valueAsColor;
|
|
233
222
|
const value = state.context.value;
|
|
223
|
+
const valueAsString = state.context.valueAsString;
|
|
234
224
|
const isDisabled = state.context.isDisabled;
|
|
235
225
|
const isInteractive = state.context.isInteractive;
|
|
236
|
-
const isDragging = state.
|
|
237
|
-
const
|
|
226
|
+
const isDragging = state.hasTag("dragging");
|
|
227
|
+
const isOpen = state.hasTag("open");
|
|
228
|
+
const channels = value.getChannels();
|
|
229
|
+
const getAreaChannels = (props) => {
|
|
230
|
+
const channels2 = value.getChannels();
|
|
231
|
+
return {
|
|
232
|
+
xChannel: props.xChannel ?? channels2[1],
|
|
233
|
+
yChannel: props.yChannel ?? channels2[2]
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
const currentPlacement = state.context.currentPlacement;
|
|
237
|
+
const popperStyles = getPlacementStyles({
|
|
238
|
+
...state.context.positioning,
|
|
239
|
+
placement: currentPlacement
|
|
240
|
+
});
|
|
238
241
|
return {
|
|
239
242
|
isDragging,
|
|
243
|
+
isOpen,
|
|
244
|
+
valueAsString,
|
|
240
245
|
value,
|
|
241
|
-
valueAsColor,
|
|
242
|
-
alpha: valueAsColor.getChannelValue("alpha"),
|
|
243
246
|
channels,
|
|
244
247
|
setColor(value2) {
|
|
245
248
|
send({ type: "VALUE.SET", value: normalizeColor(value2), src: "set-color" });
|
|
246
249
|
},
|
|
247
|
-
|
|
248
|
-
|
|
250
|
+
getChannelValue(channel) {
|
|
251
|
+
return getChannelValue(value, channel);
|
|
252
|
+
},
|
|
253
|
+
setChannelValue(channel, channelValue) {
|
|
254
|
+
const color = value.withChannelValue(channel, channelValue);
|
|
249
255
|
send({ type: "VALUE.SET", value: color, src: "set-channel" });
|
|
250
256
|
},
|
|
257
|
+
format: value.outputFormat ?? value.getFormat(),
|
|
251
258
|
setFormat(format) {
|
|
252
|
-
const
|
|
253
|
-
send({ type: "VALUE.SET", value:
|
|
259
|
+
const formatValue = value.toFormat(format);
|
|
260
|
+
send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
|
|
254
261
|
},
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
alpha: value.getChannelValue("alpha"),
|
|
263
|
+
setAlpha(alphaValue) {
|
|
264
|
+
const color = value.withChannelValue("alpha", alphaValue);
|
|
257
265
|
send({ type: "VALUE.SET", value: color, src: "set-alpha" });
|
|
258
266
|
},
|
|
267
|
+
rootProps: normalize.element({
|
|
268
|
+
...parts.root.attrs,
|
|
269
|
+
dir: state.context.dir,
|
|
270
|
+
id: dom.getRootId(state.context),
|
|
271
|
+
"data-disabled": dataAttr(isDisabled),
|
|
272
|
+
"data-readonly": dataAttr(state.context.readOnly),
|
|
273
|
+
style: {
|
|
274
|
+
"--value": value.toString("css")
|
|
275
|
+
}
|
|
276
|
+
}),
|
|
277
|
+
labelProps: normalize.element({
|
|
278
|
+
...parts.label.attrs,
|
|
279
|
+
dir: state.context.dir,
|
|
280
|
+
id: dom.getLabelId(state.context),
|
|
281
|
+
htmlFor: dom.getHiddenInputId(state.context),
|
|
282
|
+
"data-disabled": dataAttr(isDisabled),
|
|
283
|
+
"data-readonly": dataAttr(state.context.readOnly),
|
|
284
|
+
onClick(event) {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
const inputEl = query(dom.getControlEl(state.context), "[data-channel=hex]");
|
|
287
|
+
inputEl?.focus({ preventScroll: true });
|
|
288
|
+
}
|
|
289
|
+
}),
|
|
290
|
+
controlProps: normalize.element({
|
|
291
|
+
...parts.control.attrs,
|
|
292
|
+
id: dom.getControlId(state.context),
|
|
293
|
+
dir: state.context.dir,
|
|
294
|
+
"data-disabled": dataAttr(isDisabled),
|
|
295
|
+
"data-readonly": dataAttr(state.context.readOnly)
|
|
296
|
+
}),
|
|
297
|
+
triggerProps: normalize.button({
|
|
298
|
+
...parts.trigger.attrs,
|
|
299
|
+
id: dom.getTriggerId(state.context),
|
|
300
|
+
dir: state.context.dir,
|
|
301
|
+
"aria-labelledby": dom.getLabelId(state.context),
|
|
302
|
+
"data-disabled": dataAttr(isDisabled),
|
|
303
|
+
"data-readonly": dataAttr(state.context.readOnly),
|
|
304
|
+
"data-placement": currentPlacement,
|
|
305
|
+
type: "button",
|
|
306
|
+
onClick() {
|
|
307
|
+
send({ type: "TRIGGER.CLICK" });
|
|
308
|
+
},
|
|
309
|
+
style: {
|
|
310
|
+
position: "relative"
|
|
311
|
+
}
|
|
312
|
+
}),
|
|
313
|
+
positionerProps: normalize.element({
|
|
314
|
+
...parts.positioner.attrs,
|
|
315
|
+
id: dom.getPositionerId(state.context),
|
|
316
|
+
dir: state.context.dir,
|
|
317
|
+
style: popperStyles.floating
|
|
318
|
+
}),
|
|
259
319
|
contentProps: normalize.element({
|
|
260
320
|
...parts.content.attrs,
|
|
261
321
|
id: dom.getContentId(state.context),
|
|
262
|
-
dir: state.context.dir
|
|
322
|
+
dir: state.context.dir,
|
|
323
|
+
"data-placement": currentPlacement,
|
|
324
|
+
hidden: !isOpen
|
|
263
325
|
}),
|
|
264
|
-
getAreaProps(props) {
|
|
265
|
-
const { xChannel, yChannel } = props;
|
|
266
|
-
const { areaStyles } = getColorAreaGradient(
|
|
326
|
+
getAreaProps(props = {}) {
|
|
327
|
+
const { xChannel, yChannel } = getAreaChannels(props);
|
|
328
|
+
const { areaStyles } = getColorAreaGradient(value, {
|
|
267
329
|
xChannel,
|
|
268
330
|
yChannel,
|
|
269
331
|
dir: state.context.dir
|
|
@@ -281,6 +343,7 @@ function connect(state, send, normalize) {
|
|
|
281
343
|
const point = getEventPoint(evt);
|
|
282
344
|
const channel = { xChannel, yChannel };
|
|
283
345
|
send({ type: "AREA.POINTER_DOWN", point, channel, id: "area" });
|
|
346
|
+
event.preventDefault();
|
|
284
347
|
},
|
|
285
348
|
style: {
|
|
286
349
|
position: "relative",
|
|
@@ -290,15 +353,15 @@ function connect(state, send, normalize) {
|
|
|
290
353
|
}
|
|
291
354
|
});
|
|
292
355
|
},
|
|
293
|
-
|
|
294
|
-
const { xChannel, yChannel } = props;
|
|
295
|
-
const { areaGradientStyles } = getColorAreaGradient(
|
|
356
|
+
getAreaBackgroundProps(props = {}) {
|
|
357
|
+
const { xChannel, yChannel } = getAreaChannels(props);
|
|
358
|
+
const { areaGradientStyles } = getColorAreaGradient(value, {
|
|
296
359
|
xChannel,
|
|
297
360
|
yChannel,
|
|
298
361
|
dir: state.context.dir
|
|
299
362
|
});
|
|
300
363
|
return normalize.element({
|
|
301
|
-
...parts.
|
|
364
|
+
...parts.areaBackground.attrs,
|
|
302
365
|
id: dom.getAreaGradientId(state.context),
|
|
303
366
|
style: {
|
|
304
367
|
position: "relative",
|
|
@@ -308,14 +371,15 @@ function connect(state, send, normalize) {
|
|
|
308
371
|
}
|
|
309
372
|
});
|
|
310
373
|
},
|
|
311
|
-
getAreaThumbProps(props) {
|
|
312
|
-
const { xChannel, yChannel } = props;
|
|
313
|
-
const { getThumbPosition } = getChannelDetails(valueAsColor, xChannel, yChannel);
|
|
314
|
-
const { x, y } = getThumbPosition();
|
|
374
|
+
getAreaThumbProps(props = {}) {
|
|
375
|
+
const { xChannel, yChannel } = getAreaChannels(props);
|
|
315
376
|
const channel = { xChannel, yChannel };
|
|
377
|
+
const x = value.getChannelValuePercent(xChannel);
|
|
378
|
+
const y = 1 - value.getChannelValuePercent(yChannel);
|
|
316
379
|
return normalize.element({
|
|
317
380
|
...parts.areaThumb.attrs,
|
|
318
381
|
id: dom.getAreaThumbId(state.context),
|
|
382
|
+
dir: state.context.dir,
|
|
319
383
|
tabIndex: isDisabled ? void 0 : 0,
|
|
320
384
|
"data-disabled": dataAttr(isDisabled),
|
|
321
385
|
role: "presentation",
|
|
@@ -326,13 +390,10 @@ function connect(state, send, normalize) {
|
|
|
326
390
|
transform: "translate(-50%, -50%)",
|
|
327
391
|
touchAction: "none",
|
|
328
392
|
forcedColorAdjust: "none",
|
|
329
|
-
background:
|
|
330
|
-
},
|
|
331
|
-
onBlur() {
|
|
332
|
-
send("AREA.BLUR");
|
|
393
|
+
background: value.withChannelValue("alpha", 1).toString("css")
|
|
333
394
|
},
|
|
334
395
|
onFocus() {
|
|
335
|
-
send({ type: "AREA.FOCUS", id: "area" });
|
|
396
|
+
send({ type: "AREA.FOCUS", id: "area", channel });
|
|
336
397
|
},
|
|
337
398
|
onKeyDown(event) {
|
|
338
399
|
if (!isInteractive)
|
|
@@ -356,6 +417,9 @@ function connect(state, send, normalize) {
|
|
|
356
417
|
},
|
|
357
418
|
PageDown() {
|
|
358
419
|
send({ type: "AREA.PAGE_DOWN", channel, step });
|
|
420
|
+
},
|
|
421
|
+
Escape(event2) {
|
|
422
|
+
event2.stopPropagation();
|
|
359
423
|
}
|
|
360
424
|
};
|
|
361
425
|
const exec = keyMap[getEventKey(event, state.context)];
|
|
@@ -366,14 +430,31 @@ function connect(state, send, normalize) {
|
|
|
366
430
|
}
|
|
367
431
|
});
|
|
368
432
|
},
|
|
369
|
-
|
|
433
|
+
getTransparencyGridProps(props = {}) {
|
|
434
|
+
const { size = "12px" } = props;
|
|
435
|
+
return normalize.element({
|
|
436
|
+
...parts.transparencyGrid.attrs,
|
|
437
|
+
style: {
|
|
438
|
+
"--size": size,
|
|
439
|
+
width: "100%",
|
|
440
|
+
height: "100%",
|
|
441
|
+
position: "absolute",
|
|
442
|
+
backgroundColor: "#fff",
|
|
443
|
+
backgroundImage: "conic-gradient(#eeeeee 0 25%, transparent 0 50%, #eeeeee 0 75%, transparent 0)",
|
|
444
|
+
backgroundSize: "var(--size) var(--size)",
|
|
445
|
+
inset: "0px",
|
|
446
|
+
zIndex: "auto",
|
|
447
|
+
pointerEvents: "none"
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
},
|
|
451
|
+
getChannelSliderProps(props) {
|
|
370
452
|
const { orientation = "horizontal", channel } = props;
|
|
371
453
|
return normalize.element({
|
|
372
|
-
...parts.
|
|
373
|
-
id: dom.getChannelSliderTrackId(state.context, channel),
|
|
374
|
-
role: "group",
|
|
454
|
+
...parts.channelSlider.attrs,
|
|
375
455
|
"data-channel": channel,
|
|
376
456
|
"data-orientation": orientation,
|
|
457
|
+
role: "presentation",
|
|
377
458
|
onPointerDown(event) {
|
|
378
459
|
if (!isInteractive)
|
|
379
460
|
return;
|
|
@@ -382,41 +463,38 @@ function connect(state, send, normalize) {
|
|
|
382
463
|
return;
|
|
383
464
|
const point = getEventPoint(evt);
|
|
384
465
|
send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, point, id: channel, orientation });
|
|
466
|
+
event.preventDefault();
|
|
385
467
|
},
|
|
386
468
|
style: {
|
|
387
469
|
position: "relative",
|
|
388
|
-
touchAction: "none"
|
|
389
|
-
forcedColorAdjust: "none",
|
|
390
|
-
backgroundImage: getSliderBgImage(state.context, { orientation, channel })
|
|
470
|
+
touchAction: "none"
|
|
391
471
|
}
|
|
392
472
|
});
|
|
393
473
|
},
|
|
394
|
-
|
|
474
|
+
getChannelSliderTrackProps(props) {
|
|
395
475
|
const { orientation = "horizontal", channel } = props;
|
|
396
476
|
return normalize.element({
|
|
397
|
-
...parts.
|
|
398
|
-
|
|
477
|
+
...parts.channelSliderTrack.attrs,
|
|
478
|
+
id: dom.getChannelSliderId(state.context, channel),
|
|
479
|
+
role: "group",
|
|
399
480
|
"data-channel": channel,
|
|
481
|
+
"data-orientation": orientation,
|
|
400
482
|
style: {
|
|
401
|
-
position: "
|
|
402
|
-
|
|
403
|
-
backgroundImage:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
backgroundSize: "16px 16px",
|
|
410
|
-
backgroundPosition: "-2px -2px,-2px 6px,6px -10px,-10px -2px",
|
|
411
|
-
inset: 0,
|
|
412
|
-
zIndex: -1
|
|
483
|
+
position: "relative",
|
|
484
|
+
forcedColorAdjust: "none",
|
|
485
|
+
backgroundImage: getSliderBackground({
|
|
486
|
+
orientation,
|
|
487
|
+
channel,
|
|
488
|
+
dir: state.context.dir,
|
|
489
|
+
value
|
|
490
|
+
})
|
|
413
491
|
}
|
|
414
492
|
});
|
|
415
493
|
},
|
|
416
494
|
getChannelSliderThumbProps(props) {
|
|
417
495
|
const { orientation = "horizontal", channel } = props;
|
|
418
|
-
const { minValue, maxValue, step: stepValue } =
|
|
419
|
-
const channelValue =
|
|
496
|
+
const { minValue, maxValue, step: stepValue } = value.getChannelRange(channel);
|
|
497
|
+
const channelValue = value.getChannelValue(channel);
|
|
420
498
|
const offset = (channelValue - minValue) / (maxValue - minValue);
|
|
421
499
|
const placementStyles = orientation === "horizontal" ? { left: `${offset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
|
|
422
500
|
return normalize.element({
|
|
@@ -436,7 +514,7 @@ function connect(state, send, normalize) {
|
|
|
436
514
|
style: {
|
|
437
515
|
forcedColorAdjust: "none",
|
|
438
516
|
position: "absolute",
|
|
439
|
-
background: getChannelDisplayColor(
|
|
517
|
+
background: getChannelDisplayColor(value, channel).toString("css"),
|
|
440
518
|
...placementStyles
|
|
441
519
|
},
|
|
442
520
|
onFocus() {
|
|
@@ -444,11 +522,6 @@ function connect(state, send, normalize) {
|
|
|
444
522
|
return;
|
|
445
523
|
send({ type: "CHANNEL_SLIDER.FOCUS", channel });
|
|
446
524
|
},
|
|
447
|
-
onBlur() {
|
|
448
|
-
if (!isInteractive)
|
|
449
|
-
return;
|
|
450
|
-
send({ type: "CHANNEL_SLIDER.BLUR", channel });
|
|
451
|
-
},
|
|
452
525
|
onKeyDown(event) {
|
|
453
526
|
if (!isInteractive)
|
|
454
527
|
return;
|
|
@@ -477,6 +550,9 @@ function connect(state, send, normalize) {
|
|
|
477
550
|
},
|
|
478
551
|
End() {
|
|
479
552
|
send({ type: "CHANNEL_SLIDER.END", channel });
|
|
553
|
+
},
|
|
554
|
+
Escape(event2) {
|
|
555
|
+
event2.stopPropagation();
|
|
480
556
|
}
|
|
481
557
|
};
|
|
482
558
|
const exec = keyMap[getEventKey(event, state.context)];
|
|
@@ -490,7 +566,7 @@ function connect(state, send, normalize) {
|
|
|
490
566
|
getChannelInputProps(props) {
|
|
491
567
|
const { channel } = props;
|
|
492
568
|
const isTextField = channel === "hex" || channel === "css";
|
|
493
|
-
const range =
|
|
569
|
+
const range = getChannelRange(value, channel);
|
|
494
570
|
return normalize.input({
|
|
495
571
|
...parts.channelInput.attrs,
|
|
496
572
|
type: isTextField ? "text" : "number",
|
|
@@ -500,22 +576,31 @@ function connect(state, send, normalize) {
|
|
|
500
576
|
"data-disabled": dataAttr(isDisabled),
|
|
501
577
|
readOnly: state.context.readOnly,
|
|
502
578
|
id: dom.getChannelInputId(state.context, channel),
|
|
503
|
-
defaultValue:
|
|
579
|
+
defaultValue: getChannelValue(value, channel),
|
|
504
580
|
min: range?.minValue,
|
|
505
581
|
max: range?.maxValue,
|
|
506
582
|
step: range?.step,
|
|
583
|
+
onBeforeInput(event) {
|
|
584
|
+
if (isTextField)
|
|
585
|
+
return;
|
|
586
|
+
const value2 = event.currentTarget.value;
|
|
587
|
+
if (value2.match(/[^0-9.]/g)) {
|
|
588
|
+
event.preventDefault();
|
|
589
|
+
}
|
|
590
|
+
},
|
|
507
591
|
onFocus(event) {
|
|
508
592
|
send({ type: "CHANNEL_INPUT.FOCUS", channel });
|
|
509
|
-
|
|
593
|
+
event.target.select();
|
|
510
594
|
},
|
|
511
595
|
onBlur(event) {
|
|
512
|
-
const value2 = event.currentTarget.value;
|
|
513
|
-
send({ type: "CHANNEL_INPUT.
|
|
596
|
+
const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
|
|
597
|
+
send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
|
|
514
598
|
},
|
|
515
599
|
onKeyDown(event) {
|
|
516
600
|
if (event.key === "Enter") {
|
|
517
|
-
const value2 = event.currentTarget.value;
|
|
601
|
+
const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
|
|
518
602
|
send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
|
|
603
|
+
event.preventDefault();
|
|
519
604
|
}
|
|
520
605
|
},
|
|
521
606
|
style: {
|
|
@@ -531,14 +616,11 @@ function connect(state, send, normalize) {
|
|
|
531
616
|
name: state.context.name,
|
|
532
617
|
id: dom.getHiddenInputId(state.context),
|
|
533
618
|
style: visuallyHiddenStyle,
|
|
534
|
-
defaultValue:
|
|
535
|
-
onChange(event) {
|
|
536
|
-
const value2 = event.currentTarget.value;
|
|
537
|
-
send({ type: "VALUE.SET", value: value2, src: "input.change" });
|
|
538
|
-
}
|
|
619
|
+
defaultValue: valueAsString
|
|
539
620
|
}),
|
|
540
621
|
eyeDropperTriggerProps: normalize.button({
|
|
541
622
|
...parts.eyeDropperTrigger.attrs,
|
|
623
|
+
type: "button",
|
|
542
624
|
disabled: isDisabled,
|
|
543
625
|
"data-disabled": dataAttr(isDisabled),
|
|
544
626
|
"aria-label": "Pick a color from the screen",
|
|
@@ -548,43 +630,39 @@ function connect(state, send, normalize) {
|
|
|
548
630
|
send("EYEDROPPER.CLICK");
|
|
549
631
|
}
|
|
550
632
|
}),
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
633
|
+
swatchGroupProps: normalize.element({
|
|
634
|
+
...parts.swatchGroup.attrs,
|
|
635
|
+
role: "group"
|
|
636
|
+
}),
|
|
637
|
+
getSwatchTriggerProps(props) {
|
|
638
|
+
const { value: valueProp } = props;
|
|
639
|
+
const color = normalizeColor(valueProp).toFormat(value.getFormat());
|
|
640
|
+
return normalize.button({
|
|
641
|
+
...parts.swatchTrigger.attrs,
|
|
642
|
+
disabled: isDisabled,
|
|
643
|
+
type: "button",
|
|
644
|
+
"data-value": color.toString("hex"),
|
|
645
|
+
onClick() {
|
|
646
|
+
if (!isInteractive)
|
|
647
|
+
return;
|
|
648
|
+
send({ type: "VALUE.SET", value: color });
|
|
649
|
+
},
|
|
557
650
|
style: {
|
|
558
|
-
|
|
559
|
-
height: "100%",
|
|
560
|
-
background: "#fff",
|
|
561
|
-
backgroundImage: [
|
|
562
|
-
"linear-gradient(-45deg,#0000 75.5%,#bcbcbc 75.5%)",
|
|
563
|
-
"linear-gradient(45deg,#0000 75.5%,#bcbcbc 75.5%)",
|
|
564
|
-
"linear-gradient(-45deg,#bcbcbc 25.5%,#0000 25.5%)",
|
|
565
|
-
"linear-gradient(45deg,#bcbcbc 25.5%,#0000 25.5%)"
|
|
566
|
-
].join(","),
|
|
567
|
-
backgroundPosition: "-2px -2px,-2px 6px,6px -10px,-10px -2px",
|
|
568
|
-
backgroundSize: "16px 16px",
|
|
569
|
-
position: "absolute",
|
|
570
|
-
inset: "0px",
|
|
571
|
-
zIndex: -1
|
|
651
|
+
position: "relative"
|
|
572
652
|
}
|
|
573
653
|
});
|
|
574
654
|
},
|
|
575
655
|
getSwatchProps(props) {
|
|
576
|
-
const { value:
|
|
577
|
-
const
|
|
656
|
+
const { value: valueProp, respectAlpha = true } = props;
|
|
657
|
+
const colorValue = normalizeColor(valueProp);
|
|
658
|
+
const color = colorValue.toFormat(value.getFormat());
|
|
578
659
|
return normalize.element({
|
|
579
660
|
...parts.swatch.attrs,
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return;
|
|
583
|
-
send({ type: "VALUE.SET", value: color });
|
|
584
|
-
},
|
|
661
|
+
"data-state": colorValue.isEqual(value) ? "selected" : "unselected",
|
|
662
|
+
"data-value": color.toString("hex"),
|
|
585
663
|
style: {
|
|
586
664
|
position: "relative",
|
|
587
|
-
background: color.toString("css")
|
|
665
|
+
background: color.toString(respectAlpha ? "css" : "hex")
|
|
588
666
|
}
|
|
589
667
|
});
|
|
590
668
|
}
|
|
@@ -592,86 +670,145 @@ function connect(state, send, normalize) {
|
|
|
592
670
|
}
|
|
593
671
|
|
|
594
672
|
// src/color-picker.machine.ts
|
|
595
|
-
import { parseColor as
|
|
596
|
-
import { createMachine } from "@zag-js/core";
|
|
673
|
+
import { parseColor as parseColor4 } from "@zag-js/color-utils";
|
|
674
|
+
import { createMachine, guards, ref as ref2 } from "@zag-js/core";
|
|
675
|
+
import { trackDismissableElement } from "@zag-js/dismissable";
|
|
597
676
|
import { trackPointerMove } from "@zag-js/dom-event";
|
|
598
|
-
import { raf
|
|
599
|
-
import { trackFormControl } from "@zag-js/form-utils";
|
|
600
|
-
import {
|
|
677
|
+
import { raf } from "@zag-js/dom-query";
|
|
678
|
+
import { dispatchInputValueEvent, trackFormControl } from "@zag-js/form-utils";
|
|
679
|
+
import { getPlacement } from "@zag-js/popper";
|
|
601
680
|
import { disableTextSelection } from "@zag-js/text-selection";
|
|
602
681
|
import { compact, tryCatch } from "@zag-js/utils";
|
|
682
|
+
|
|
683
|
+
// src/color-picker.parse.ts
|
|
684
|
+
import { parseColor as parseColor3 } from "@zag-js/color-utils";
|
|
685
|
+
import { ref } from "@zag-js/core";
|
|
686
|
+
var parse = (color) => {
|
|
687
|
+
const value = parseColor3(color);
|
|
688
|
+
const colorFormat = value.getFormat();
|
|
689
|
+
const lockedFormat = colorFormat.startsWith("hsl") ? "hsla" : "hsba";
|
|
690
|
+
const result = value.toFormat(lockedFormat);
|
|
691
|
+
result.outputFormat = colorFormat;
|
|
692
|
+
return ref(result);
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// src/color-picker.machine.ts
|
|
696
|
+
var { stateIn } = guards;
|
|
603
697
|
function machine(userContext) {
|
|
604
698
|
const ctx = compact(userContext);
|
|
605
699
|
return createMachine(
|
|
606
700
|
{
|
|
607
701
|
id: "color-picker",
|
|
608
|
-
initial: "idle",
|
|
702
|
+
initial: ctx.open ? "open" : "idle",
|
|
609
703
|
context: {
|
|
610
704
|
dir: "ltr",
|
|
611
|
-
value: "#
|
|
705
|
+
value: parse("#000000"),
|
|
612
706
|
disabled: false,
|
|
613
707
|
...ctx,
|
|
614
708
|
activeId: null,
|
|
615
709
|
activeChannel: null,
|
|
616
710
|
activeOrientation: null,
|
|
617
|
-
fieldsetDisabled: false
|
|
711
|
+
fieldsetDisabled: false,
|
|
712
|
+
autoFocus: true,
|
|
713
|
+
positioning: {
|
|
714
|
+
...ctx.positioning,
|
|
715
|
+
placement: "bottom"
|
|
716
|
+
}
|
|
618
717
|
},
|
|
619
718
|
computed: {
|
|
620
719
|
isRtl: (ctx2) => ctx2.dir === "rtl",
|
|
621
720
|
isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
|
|
622
721
|
isInteractive: (ctx2) => !(ctx2.isDisabled || ctx2.readOnly),
|
|
623
|
-
|
|
722
|
+
valueAsString: (ctx2) => {
|
|
723
|
+
const color = ctx2.value.outputFormat ? ctx2.value.toFormat(ctx2.value.outputFormat) : ctx2.value;
|
|
724
|
+
return color.toString("css");
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
activities: ["trackFormControl"],
|
|
728
|
+
watch: {
|
|
729
|
+
valueAsString: ["syncInputElements"],
|
|
730
|
+
open: ["toggleVisibility"]
|
|
624
731
|
},
|
|
625
732
|
on: {
|
|
626
733
|
"VALUE.SET": {
|
|
627
734
|
actions: ["setValue"]
|
|
735
|
+
},
|
|
736
|
+
"CHANNEL_INPUT.FOCUS": [
|
|
737
|
+
{
|
|
738
|
+
guard: stateIn("idle"),
|
|
739
|
+
target: "focused",
|
|
740
|
+
actions: ["setActiveChannel"]
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
actions: ["setActiveChannel"]
|
|
744
|
+
}
|
|
745
|
+
],
|
|
746
|
+
"CHANNEL_INPUT.BLUR": [
|
|
747
|
+
{
|
|
748
|
+
guard: stateIn("focused"),
|
|
749
|
+
target: "idle",
|
|
750
|
+
actions: ["setChannelColorFromInput"]
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
actions: ["setChannelColorFromInput"]
|
|
754
|
+
}
|
|
755
|
+
],
|
|
756
|
+
"CHANNEL_INPUT.CHANGE": {
|
|
757
|
+
actions: ["setChannelColorFromInput"]
|
|
628
758
|
}
|
|
629
759
|
},
|
|
630
|
-
activities: ["trackFormControl"],
|
|
631
|
-
watch: {
|
|
632
|
-
value: ["syncInputElements"]
|
|
633
|
-
},
|
|
634
760
|
states: {
|
|
635
761
|
idle: {
|
|
762
|
+
tags: ["closed"],
|
|
636
763
|
on: {
|
|
764
|
+
OPEN: {
|
|
765
|
+
target: "open",
|
|
766
|
+
actions: ["setInitialFocus", "invokeOnOpen"]
|
|
767
|
+
},
|
|
768
|
+
"TRIGGER.CLICK": {
|
|
769
|
+
target: "open",
|
|
770
|
+
actions: ["setInitialFocus", "invokeOnOpen"]
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
focused: {
|
|
775
|
+
tags: ["closed", "focused"],
|
|
776
|
+
on: {
|
|
777
|
+
OPEN: {
|
|
778
|
+
target: "open",
|
|
779
|
+
actions: ["setInitialFocus", "invokeOnOpen"]
|
|
780
|
+
},
|
|
781
|
+
"TRIGGER.CLICK": {
|
|
782
|
+
target: "open",
|
|
783
|
+
actions: ["setInitialFocus", "invokeOnOpen"]
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
},
|
|
787
|
+
open: {
|
|
788
|
+
tags: ["open"],
|
|
789
|
+
activities: ["trackPositioning", "trackDismissableElement"],
|
|
790
|
+
on: {
|
|
791
|
+
"TRIGGER.CLICK": {
|
|
792
|
+
target: "idle",
|
|
793
|
+
actions: ["invokeOnClose"]
|
|
794
|
+
},
|
|
637
795
|
"EYEDROPPER.CLICK": {
|
|
638
796
|
actions: ["openEyeDropper"]
|
|
639
797
|
},
|
|
640
798
|
"AREA.POINTER_DOWN": {
|
|
641
|
-
target: "dragging",
|
|
799
|
+
target: "open:dragging",
|
|
642
800
|
actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
|
|
643
801
|
},
|
|
644
802
|
"AREA.FOCUS": {
|
|
645
|
-
target: "focused",
|
|
646
803
|
actions: ["setActiveChannel"]
|
|
647
804
|
},
|
|
648
805
|
"CHANNEL_SLIDER.POINTER_DOWN": {
|
|
649
|
-
target: "dragging",
|
|
806
|
+
target: "open:dragging",
|
|
650
807
|
actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
|
|
651
808
|
},
|
|
652
809
|
"CHANNEL_SLIDER.FOCUS": {
|
|
653
|
-
target: "focused",
|
|
654
|
-
actions: ["setActiveChannel"]
|
|
655
|
-
},
|
|
656
|
-
"CHANNEL_INPUT.FOCUS": {
|
|
657
|
-
target: "focused",
|
|
658
810
|
actions: ["setActiveChannel"]
|
|
659
811
|
},
|
|
660
|
-
"CHANNEL_INPUT.CHANGE": {
|
|
661
|
-
actions: ["setChannelColorFromInput"]
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
},
|
|
665
|
-
focused: {
|
|
666
|
-
on: {
|
|
667
|
-
"AREA.POINTER_DOWN": {
|
|
668
|
-
target: "dragging",
|
|
669
|
-
actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
|
|
670
|
-
},
|
|
671
|
-
"CHANNEL_SLIDER.POINTER_DOWN": {
|
|
672
|
-
target: "dragging",
|
|
673
|
-
actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
|
|
674
|
-
},
|
|
675
812
|
"AREA.ARROW_LEFT": {
|
|
676
813
|
actions: ["decrementXChannel"]
|
|
677
814
|
},
|
|
@@ -714,44 +851,100 @@ function machine(userContext) {
|
|
|
714
851
|
"CHANNEL_SLIDER.END": {
|
|
715
852
|
actions: ["setChannelToMax"]
|
|
716
853
|
},
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
854
|
+
INTERACT_OUTSIDE: [
|
|
855
|
+
{
|
|
856
|
+
guard: "shouldRestoreFocus",
|
|
857
|
+
target: "focused",
|
|
858
|
+
actions: ["setReturnFocus", "invokeOnClose"]
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
target: "idle",
|
|
862
|
+
actions: ["invokeOnClose"]
|
|
863
|
+
}
|
|
864
|
+
],
|
|
865
|
+
CLOSE: {
|
|
866
|
+
target: "idle",
|
|
867
|
+
actions: ["invokeOnClose"]
|
|
728
868
|
}
|
|
729
869
|
}
|
|
730
870
|
},
|
|
731
|
-
dragging: {
|
|
871
|
+
"open:dragging": {
|
|
872
|
+
tags: ["open"],
|
|
732
873
|
exit: ["clearActiveChannel"],
|
|
733
|
-
activities: ["trackPointerMove", "disableTextSelection"],
|
|
874
|
+
activities: ["trackPointerMove", "disableTextSelection", "trackPositioning", "trackDismissableElement"],
|
|
734
875
|
on: {
|
|
735
876
|
"AREA.POINTER_MOVE": {
|
|
736
|
-
actions: ["setAreaColorFromPoint"]
|
|
877
|
+
actions: ["setAreaColorFromPoint", "focusAreaThumb"]
|
|
737
878
|
},
|
|
738
879
|
"AREA.POINTER_UP": {
|
|
739
|
-
target: "
|
|
880
|
+
target: "open",
|
|
740
881
|
actions: ["invokeOnChangeEnd"]
|
|
741
882
|
},
|
|
742
883
|
"CHANNEL_SLIDER.POINTER_MOVE": {
|
|
743
|
-
actions: ["setChannelColorFromPoint"]
|
|
884
|
+
actions: ["setChannelColorFromPoint", "focusChannelThumb"]
|
|
744
885
|
},
|
|
745
886
|
"CHANNEL_SLIDER.POINTER_UP": {
|
|
746
|
-
target: "
|
|
887
|
+
target: "open",
|
|
747
888
|
actions: ["invokeOnChangeEnd"]
|
|
889
|
+
},
|
|
890
|
+
INTERACT_OUTSIDE: [
|
|
891
|
+
{
|
|
892
|
+
guard: "shouldRestoreFocus",
|
|
893
|
+
target: "focused",
|
|
894
|
+
actions: ["setReturnFocus", "invokeOnClose"]
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
target: "idle",
|
|
898
|
+
actions: ["invokeOnClose"]
|
|
899
|
+
}
|
|
900
|
+
],
|
|
901
|
+
CLOSE: {
|
|
902
|
+
target: "idle",
|
|
903
|
+
actions: ["invokeOnClose"]
|
|
748
904
|
}
|
|
749
905
|
}
|
|
750
906
|
}
|
|
751
907
|
}
|
|
752
908
|
},
|
|
753
909
|
{
|
|
910
|
+
guards: {
|
|
911
|
+
isTargetFocusable: (_ctx, evt) => evt.restoreFocus
|
|
912
|
+
},
|
|
754
913
|
activities: {
|
|
914
|
+
trackPositioning(ctx2) {
|
|
915
|
+
ctx2.currentPlacement = ctx2.positioning.placement;
|
|
916
|
+
const anchorEl = dom.getTriggerEl(ctx2);
|
|
917
|
+
const getPositionerEl = () => dom.getPositionerEl(ctx2);
|
|
918
|
+
return getPlacement(anchorEl, getPositionerEl, {
|
|
919
|
+
...ctx2.positioning,
|
|
920
|
+
defer: true,
|
|
921
|
+
onComplete(data) {
|
|
922
|
+
ctx2.currentPlacement = data.placement;
|
|
923
|
+
},
|
|
924
|
+
onCleanup() {
|
|
925
|
+
ctx2.currentPlacement = void 0;
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
},
|
|
929
|
+
trackDismissableElement(ctx2, _evt, { send }) {
|
|
930
|
+
const getContentEl = () => dom.getContentEl(ctx2);
|
|
931
|
+
let restoreFocus = true;
|
|
932
|
+
return trackDismissableElement(getContentEl, {
|
|
933
|
+
exclude: dom.getTriggerEl(ctx2),
|
|
934
|
+
defer: true,
|
|
935
|
+
onInteractOutside(event) {
|
|
936
|
+
ctx2.onInteractOutside?.(event);
|
|
937
|
+
if (event.defaultPrevented)
|
|
938
|
+
return;
|
|
939
|
+
restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
|
|
940
|
+
},
|
|
941
|
+
onPointerDownOutside: ctx2.onPointerDownOutside,
|
|
942
|
+
onFocusOutside: ctx2.onFocusOutside,
|
|
943
|
+
onDismiss() {
|
|
944
|
+
send({ type: "INTERACT_OUTSIDE", restoreFocus });
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
},
|
|
755
948
|
trackFormControl(ctx2, _evt, { send, initialContext }) {
|
|
756
949
|
const inputEl = dom.getHiddenInputEl(ctx2);
|
|
757
950
|
return trackFormControl(inputEl, {
|
|
@@ -787,20 +980,18 @@ function machine(userContext) {
|
|
|
787
980
|
const win = dom.getWin(ctx2);
|
|
788
981
|
const picker = new win.EyeDropper();
|
|
789
982
|
picker.open().then(({ sRGBHex }) => {
|
|
790
|
-
const format = ctx2.
|
|
791
|
-
const color =
|
|
983
|
+
const format = ctx2.value.getFormat();
|
|
984
|
+
const color = parseColor4(sRGBHex).toFormat(format);
|
|
792
985
|
set.value(ctx2, color);
|
|
793
|
-
ctx2.onValueChangeEnd?.({ value: ctx2.value,
|
|
986
|
+
ctx2.onValueChangeEnd?.({ value: ctx2.value, valueAsString: ctx2.valueAsString });
|
|
794
987
|
}).catch(() => void 0);
|
|
795
988
|
},
|
|
796
989
|
setActiveChannel(ctx2, evt) {
|
|
797
990
|
ctx2.activeId = evt.id;
|
|
798
|
-
if (evt.channel)
|
|
991
|
+
if (evt.channel)
|
|
799
992
|
ctx2.activeChannel = evt.channel;
|
|
800
|
-
|
|
801
|
-
if (evt.orientation) {
|
|
993
|
+
if (evt.orientation)
|
|
802
994
|
ctx2.activeOrientation = evt.orientation;
|
|
803
|
-
}
|
|
804
995
|
},
|
|
805
996
|
clearActiveChannel(ctx2) {
|
|
806
997
|
ctx2.activeChannel = null;
|
|
@@ -812,10 +1003,9 @@ function machine(userContext) {
|
|
|
812
1003
|
const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
813
1004
|
if (!percent)
|
|
814
1005
|
return;
|
|
815
|
-
const
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
return;
|
|
1006
|
+
const xValue = ctx2.value.getChannelPercentValue(xChannel, percent.x);
|
|
1007
|
+
const yValue = ctx2.value.getChannelPercentValue(yChannel, 1 - percent.y);
|
|
1008
|
+
const color = ctx2.value.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
|
|
819
1009
|
set.value(ctx2, color);
|
|
820
1010
|
},
|
|
821
1011
|
setChannelColorFromPoint(ctx2, evt) {
|
|
@@ -823,24 +1013,17 @@ function machine(userContext) {
|
|
|
823
1013
|
const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
|
|
824
1014
|
if (!percent)
|
|
825
1015
|
return;
|
|
826
|
-
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(channel);
|
|
827
1016
|
const orientation = ctx2.activeOrientation || "horizontal";
|
|
828
|
-
const
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
set.value(ctx2, newColor);
|
|
1017
|
+
const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
|
|
1018
|
+
const value = ctx2.value.getChannelPercentValue(channel, channelPercent);
|
|
1019
|
+
const color = ctx2.value.withChannelValue(channel, value);
|
|
1020
|
+
set.value(ctx2, color);
|
|
833
1021
|
},
|
|
834
1022
|
setValue(ctx2, evt) {
|
|
835
1023
|
set.value(ctx2, evt.value);
|
|
836
1024
|
},
|
|
837
1025
|
syncInputElements(ctx2) {
|
|
838
|
-
|
|
839
|
-
inputs.forEach((input) => {
|
|
840
|
-
const channel = input.dataset.channel;
|
|
841
|
-
dom.setValue(input, getChannelInputValue(ctx2.valueAsColor, channel));
|
|
842
|
-
});
|
|
843
|
-
dom.setValue(dom.getHiddenInputEl(ctx2), ctx2.value);
|
|
1026
|
+
sync.inputs(ctx2);
|
|
844
1027
|
},
|
|
845
1028
|
invokeOnChangeEnd(ctx2) {
|
|
846
1029
|
invoke.changeEnd(ctx2);
|
|
@@ -848,112 +1031,141 @@ function machine(userContext) {
|
|
|
848
1031
|
setChannelColorFromInput(ctx2, evt) {
|
|
849
1032
|
const { channel, isTextField, value } = evt;
|
|
850
1033
|
if (channel === "alpha") {
|
|
851
|
-
const
|
|
852
|
-
set.value(ctx2,
|
|
1034
|
+
const newColor = ctx2.value.withChannelValue("alpha", parseFloat(value));
|
|
1035
|
+
set.value(ctx2, newColor);
|
|
853
1036
|
return;
|
|
854
1037
|
}
|
|
855
1038
|
if (isTextField) {
|
|
856
|
-
const
|
|
857
|
-
const
|
|
858
|
-
|
|
859
|
-
() =>
|
|
860
|
-
() => ctx2.valueAsColor
|
|
1039
|
+
const currentAlpha = ctx2.value.getChannelValue("alpha");
|
|
1040
|
+
const color2 = tryCatch(
|
|
1041
|
+
() => parse(value).withChannelValue("alpha", currentAlpha),
|
|
1042
|
+
() => ctx2.value
|
|
861
1043
|
);
|
|
862
1044
|
const inputEl = dom.getChannelInputEl(ctx2, channel);
|
|
863
|
-
dom.setValue(inputEl,
|
|
864
|
-
set.value(ctx2,
|
|
1045
|
+
dom.setValue(inputEl, getChannelValue(color2, channel));
|
|
1046
|
+
set.value(ctx2, color2);
|
|
865
1047
|
return;
|
|
866
1048
|
}
|
|
867
|
-
const
|
|
868
|
-
set.value(ctx2,
|
|
1049
|
+
const color = ctx2.value.toFormat(ctx2.value.outputFormat).withChannelValue(channel, value);
|
|
1050
|
+
set.value(ctx2, color);
|
|
869
1051
|
},
|
|
870
1052
|
incrementChannel(ctx2, evt) {
|
|
871
|
-
const
|
|
872
|
-
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
873
|
-
const value = snapValueToStep2(channelValue + evt.step, minValue, maxValue, step);
|
|
874
|
-
const color = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
|
|
1053
|
+
const color = ctx2.value.incrementChannel(evt.channel, evt.step);
|
|
875
1054
|
set.value(ctx2, color);
|
|
876
1055
|
},
|
|
877
1056
|
decrementChannel(ctx2, evt) {
|
|
878
|
-
const
|
|
879
|
-
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
880
|
-
const value = snapValueToStep2(channelValue - evt.step, minValue, maxValue, step);
|
|
881
|
-
const color = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
|
|
1057
|
+
const color = ctx2.value.decrementChannel(evt.channel, evt.step);
|
|
882
1058
|
set.value(ctx2, color);
|
|
883
1059
|
},
|
|
884
1060
|
incrementXChannel(ctx2, evt) {
|
|
885
|
-
const { xChannel
|
|
886
|
-
const
|
|
887
|
-
const color = ctx2.valueAsColor.withChannelValue(xChannel, incrementX(evt.step));
|
|
1061
|
+
const { xChannel } = evt.channel;
|
|
1062
|
+
const color = ctx2.value.incrementChannel(xChannel, evt.step);
|
|
888
1063
|
set.value(ctx2, color);
|
|
889
1064
|
},
|
|
890
1065
|
decrementXChannel(ctx2, evt) {
|
|
891
|
-
const { xChannel
|
|
892
|
-
const
|
|
893
|
-
const color = ctx2.valueAsColor.withChannelValue(xChannel, decrementX(evt.step));
|
|
1066
|
+
const { xChannel } = evt.channel;
|
|
1067
|
+
const color = ctx2.value.decrementChannel(xChannel, evt.step);
|
|
894
1068
|
set.value(ctx2, color);
|
|
895
1069
|
},
|
|
896
1070
|
incrementYChannel(ctx2, evt) {
|
|
897
|
-
const {
|
|
898
|
-
const
|
|
899
|
-
const color = ctx2.valueAsColor.withChannelValue(yChannel, incrementY(evt.step));
|
|
1071
|
+
const { yChannel } = evt.channel;
|
|
1072
|
+
const color = ctx2.value.incrementChannel(yChannel, evt.step);
|
|
900
1073
|
set.value(ctx2, color);
|
|
901
1074
|
},
|
|
902
1075
|
decrementYChannel(ctx2, evt) {
|
|
903
|
-
const {
|
|
904
|
-
const
|
|
905
|
-
const color = ctx2.valueAsColor.withChannelValue(yChannel, decrementY(evt.step));
|
|
1076
|
+
const { yChannel } = evt.channel;
|
|
1077
|
+
const color = ctx2.value.decrementChannel(yChannel, evt.step);
|
|
906
1078
|
set.value(ctx2, color);
|
|
907
1079
|
},
|
|
908
1080
|
setChannelToMax(ctx2, evt) {
|
|
909
|
-
const
|
|
910
|
-
const color = ctx2.
|
|
1081
|
+
const range = ctx2.value.getChannelRange(evt.channel);
|
|
1082
|
+
const color = ctx2.value.withChannelValue(evt.channel, range.maxValue);
|
|
911
1083
|
set.value(ctx2, color);
|
|
912
1084
|
},
|
|
913
1085
|
setChannelToMin(ctx2, evt) {
|
|
914
|
-
const
|
|
915
|
-
const color = ctx2.
|
|
1086
|
+
const range = ctx2.value.getChannelRange(evt.channel);
|
|
1087
|
+
const color = ctx2.value.withChannelValue(evt.channel, range.minValue);
|
|
916
1088
|
set.value(ctx2, color);
|
|
917
1089
|
},
|
|
918
1090
|
focusAreaThumb(ctx2) {
|
|
919
|
-
|
|
920
|
-
dom.getAreaThumbEl(ctx2)
|
|
1091
|
+
raf(() => {
|
|
1092
|
+
dom?.focus(ctx2, dom.getAreaThumbEl(ctx2));
|
|
921
1093
|
});
|
|
922
1094
|
},
|
|
923
1095
|
focusChannelThumb(ctx2, evt) {
|
|
924
|
-
|
|
925
|
-
dom.getChannelSliderThumbEl(ctx2, evt.channel)
|
|
1096
|
+
raf(() => {
|
|
1097
|
+
dom?.focus(ctx2, dom.getChannelSliderThumbEl(ctx2, evt.channel));
|
|
1098
|
+
});
|
|
1099
|
+
},
|
|
1100
|
+
setInitialFocus(ctx2) {
|
|
1101
|
+
raf(() => {
|
|
1102
|
+
dom.getInitialFocusEl(ctx2)?.focus({ preventScroll: true });
|
|
926
1103
|
});
|
|
1104
|
+
},
|
|
1105
|
+
setReturnFocus(ctx2) {
|
|
1106
|
+
raf(() => {
|
|
1107
|
+
dom?.focus(ctx2, dom.getTriggerEl(ctx2));
|
|
1108
|
+
});
|
|
1109
|
+
},
|
|
1110
|
+
invokeOnOpen(ctx2) {
|
|
1111
|
+
ctx2.onOpenChange?.({ open: true });
|
|
1112
|
+
},
|
|
1113
|
+
invokeOnClose(ctx2) {
|
|
1114
|
+
ctx2.onOpenChange?.({ open: false });
|
|
1115
|
+
},
|
|
1116
|
+
toggleVisibility(ctx2, _evt, { send }) {
|
|
1117
|
+
send({ type: ctx2.open ? "OPEN" : "CLOSE", src: "controlled" });
|
|
927
1118
|
}
|
|
1119
|
+
},
|
|
1120
|
+
compareFns: {
|
|
1121
|
+
value: (a, b) => a.isEqual(b)
|
|
928
1122
|
}
|
|
929
1123
|
}
|
|
930
1124
|
);
|
|
931
1125
|
}
|
|
1126
|
+
var sync = {
|
|
1127
|
+
inputs(ctx) {
|
|
1128
|
+
const channelInputs = dom.getChannelInputEls(ctx);
|
|
1129
|
+
channelInputs.forEach((inputEl) => {
|
|
1130
|
+
const channel = inputEl.dataset.channel;
|
|
1131
|
+
dom.setValue(inputEl, getChannelValue(ctx.value, channel));
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
932
1135
|
var invoke = {
|
|
933
1136
|
changeEnd(ctx) {
|
|
934
1137
|
ctx.onValueChangeEnd?.({
|
|
935
1138
|
value: ctx.value,
|
|
936
|
-
|
|
1139
|
+
valueAsString: ctx.valueAsString
|
|
937
1140
|
});
|
|
938
1141
|
},
|
|
939
1142
|
change(ctx) {
|
|
940
1143
|
ctx.onValueChange?.({
|
|
941
1144
|
value: ctx.value,
|
|
942
|
-
|
|
1145
|
+
valueAsString: ctx.valueAsString
|
|
943
1146
|
});
|
|
1147
|
+
dispatchInputValueEvent(dom.getHiddenInputEl(ctx), { value: ctx.valueAsString });
|
|
944
1148
|
}
|
|
945
1149
|
};
|
|
946
1150
|
var set = {
|
|
947
1151
|
value(ctx, color) {
|
|
948
|
-
|
|
1152
|
+
sync.inputs(ctx);
|
|
1153
|
+
if (!color || ctx.value.isEqual(color))
|
|
949
1154
|
return;
|
|
950
|
-
|
|
1155
|
+
const currentFormat = ctx.value.getFormat();
|
|
1156
|
+
const outputColor = color.toFormat(currentFormat);
|
|
1157
|
+
try {
|
|
1158
|
+
outputColor.outputFormat = ctx.value.outputFormat;
|
|
1159
|
+
} catch {
|
|
1160
|
+
}
|
|
1161
|
+
ctx.value = ref2(outputColor);
|
|
951
1162
|
invoke.change(ctx);
|
|
952
1163
|
}
|
|
953
1164
|
};
|
|
954
1165
|
export {
|
|
955
1166
|
anatomy,
|
|
956
1167
|
connect,
|
|
957
|
-
machine
|
|
1168
|
+
machine,
|
|
1169
|
+
parse
|
|
958
1170
|
};
|
|
959
1171
|
//# sourceMappingURL=index.mjs.map
|