@zag-js/color-picker 0.10.2 → 0.10.4
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/color-picker.anatomy.d.ts +3 -6
- package/dist/color-picker.anatomy.js +10 -33
- package/dist/color-picker.anatomy.mjs +19 -8
- package/dist/color-picker.connect.d.ts +4 -8
- package/dist/color-picker.connect.js +56 -436
- package/dist/color-picker.connect.mjs +368 -14
- package/dist/color-picker.dom.d.ts +27 -32
- package/dist/color-picker.dom.js +12 -34
- package/dist/color-picker.dom.mjs +33 -6
- package/dist/color-picker.machine.d.ts +3 -8
- package/dist/color-picker.machine.js +46 -163
- package/dist/color-picker.machine.mjs +335 -8
- package/dist/color-picker.types.d.ts +14 -16
- package/dist/index.d.ts +4 -8
- package/dist/index.js +8 -1085
- package/dist/index.mjs +3 -21
- package/dist/utils/generate-format-background.d.ts +9 -11
- package/dist/utils/generate-format-background.js +22 -53
- package/dist/utils/generate-format-background.mjs +120 -21
- package/dist/utils/get-channel-details.d.ts +3 -7
- package/dist/utils/get-channel-details.js +15 -37
- package/dist/utils/get-channel-details.mjs +53 -6
- package/dist/utils/get-channel-display-color.d.ts +3 -5
- package/dist/utils/get-channel-display-color.js +8 -30
- package/dist/utils/get-channel-display-color.mjs +22 -6
- package/dist/utils/get-channel-input-value.d.ts +5 -10
- package/dist/utils/get-channel-input-value.js +6 -30
- package/dist/utils/get-channel-input-value.mjs +21 -8
- package/dist/utils/get-color-area-gradient.d.ts +6 -10
- package/dist/utils/get-color-area-gradient.js +14 -158
- package/dist/utils/get-color-area-gradient.mjs +61 -7
- package/dist/utils/get-slider-background.d.ts +2 -8
- package/dist/utils/get-slider-background.js +6 -29
- package/dist/utils/get-slider-background.mjs +38 -5
- package/package.json +11 -16
- package/src/color-picker.connect.ts +1 -1
- package/src/color-picker.dom.ts +1 -1
- package/src/color-picker.types.ts +3 -1
- package/src/index.ts +2 -0
- package/src/utils/get-channel-details.ts +2 -2
- package/src/utils/get-channel-display-color.ts +1 -1
- package/src/utils/get-color-area-gradient.ts +1 -1
- package/dist/chunk-2ERX54SV.mjs +0 -25
- package/dist/chunk-3XH465XT.mjs +0 -42
- package/dist/chunk-5QSFKCT5.mjs +0 -393
- package/dist/chunk-75JXJMB5.mjs +0 -22
- package/dist/chunk-JNBNPPMF.mjs +0 -24
- package/dist/chunk-KLLIOTK6.mjs +0 -55
- package/dist/chunk-KO4TBUXB.mjs +0 -74
- package/dist/chunk-ML3WX6YS.mjs +0 -345
- package/dist/chunk-OY3B7NXA.mjs +0 -132
- package/dist/chunk-SPSDVZCT.mjs +0 -35
- package/dist/color-picker.types.js +0 -18
- package/dist/color-picker.types.mjs +0 -0
|
@@ -1,136 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
'use strict';
|
|
19
2
|
|
|
20
|
-
|
|
21
|
-
var color_picker_machine_exports = {};
|
|
22
|
-
__export(color_picker_machine_exports, {
|
|
23
|
-
machine: () => machine
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(color_picker_machine_exports);
|
|
26
|
-
var import_color_utils = require("@zag-js/color-utils");
|
|
27
|
-
var import_core = require("@zag-js/core");
|
|
28
|
-
var import_dom_event2 = require("@zag-js/dom-event");
|
|
29
|
-
var import_dom_query2 = require("@zag-js/dom-query");
|
|
30
|
-
var import_numeric_range2 = require("@zag-js/numeric-range");
|
|
31
|
-
var import_text_selection = require("@zag-js/text-selection");
|
|
32
|
-
var import_utils = require("@zag-js/utils");
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
33
4
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
getChannelSliderThumbId: (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
|
|
45
|
-
getContentEl: (ctx) => dom.queryById(ctx, dom.getContentId(ctx)),
|
|
46
|
-
getAreaThumbEl: (ctx) => dom.queryById(ctx, dom.getAreaThumbId(ctx)),
|
|
47
|
-
getChannelSliderThumbEl: (ctx, channel) => dom.queryById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
|
|
48
|
-
getChannelInputEl: (ctx, channel) => dom.queryById(ctx, dom.getChannelInputId(ctx, channel)),
|
|
49
|
-
getAreaEl: (ctx) => dom.queryById(ctx, dom.getAreaId(ctx)),
|
|
50
|
-
getAreaValueFromPoint(ctx, point) {
|
|
51
|
-
const { percent } = (0, import_dom_event.getRelativePoint)(point, dom.getAreaEl(ctx));
|
|
52
|
-
return percent;
|
|
53
|
-
},
|
|
54
|
-
getChannelSliderTrackEl: (ctx, channel) => {
|
|
55
|
-
return dom.queryById(ctx, dom.getChannelSliderTrackId(ctx, channel));
|
|
56
|
-
},
|
|
57
|
-
getChannelSliderValueFromPoint(ctx, point, channel) {
|
|
58
|
-
const { percent } = (0, import_dom_event.getRelativePoint)(point, dom.getChannelSliderTrackEl(ctx, channel));
|
|
59
|
-
return percent;
|
|
60
|
-
},
|
|
61
|
-
getChannelInputEls: (ctx) => {
|
|
62
|
-
return (0, import_dom_query.queryAll)(dom.getContentEl(ctx), "input[data-channel]");
|
|
63
|
-
}
|
|
64
|
-
});
|
|
5
|
+
const colorUtils = require('@zag-js/color-utils');
|
|
6
|
+
const core = require('@zag-js/core');
|
|
7
|
+
const domEvent = require('@zag-js/dom-event');
|
|
8
|
+
const domQuery = require('@zag-js/dom-query');
|
|
9
|
+
const numericRange = require('@zag-js/numeric-range');
|
|
10
|
+
const textSelection = require('@zag-js/text-selection');
|
|
11
|
+
const utils = require('@zag-js/utils');
|
|
12
|
+
const colorPicker_dom = require('./color-picker.dom.js');
|
|
13
|
+
const getChannelDetails = require('./utils/get-channel-details.js');
|
|
14
|
+
const getChannelInputValue = require('./utils/get-channel-input-value.js');
|
|
65
15
|
|
|
66
|
-
// src/utils/get-channel-details.ts
|
|
67
|
-
var import_numeric_range = require("@zag-js/numeric-range");
|
|
68
|
-
function getChannelDetails(color, xChannel, yChannel) {
|
|
69
|
-
const channels = color.getColorSpaceAxes({ xChannel, yChannel });
|
|
70
|
-
const xChannelRange = color.getChannelRange(channels.xChannel);
|
|
71
|
-
const yChannelRange = color.getChannelRange(channels.yChannel);
|
|
72
|
-
const { minValue: minValueX, maxValue: maxValueX, step: stepX, pageSize: pageSizeX } = xChannelRange;
|
|
73
|
-
const { minValue: minValueY, maxValue: maxValueY, step: stepY, pageSize: pageSizeY } = yChannelRange;
|
|
74
|
-
const xValue = color.getChannelValue(channels.xChannel);
|
|
75
|
-
const yValue = color.getChannelValue(channels.yChannel);
|
|
76
|
-
return {
|
|
77
|
-
channels,
|
|
78
|
-
xChannelStep: stepX,
|
|
79
|
-
yChannelStep: stepY,
|
|
80
|
-
xChannelPageStep: pageSizeX,
|
|
81
|
-
yChannelPageStep: pageSizeY,
|
|
82
|
-
xValue,
|
|
83
|
-
yValue,
|
|
84
|
-
getThumbPosition() {
|
|
85
|
-
let x = (xValue - minValueX) / (maxValueX - minValueX);
|
|
86
|
-
let y = 1 - (yValue - minValueY) / (maxValueY - minValueY);
|
|
87
|
-
return { x, y };
|
|
88
|
-
},
|
|
89
|
-
incrementX(stepSize) {
|
|
90
|
-
return xValue + stepSize > maxValueX ? maxValueX : (0, import_numeric_range.snapValueToStep)(xValue + stepSize, minValueX, maxValueX, stepX);
|
|
91
|
-
},
|
|
92
|
-
incrementY(stepSize) {
|
|
93
|
-
return yValue + stepSize > maxValueY ? maxValueY : (0, import_numeric_range.snapValueToStep)(yValue + stepSize, minValueY, maxValueY, stepY);
|
|
94
|
-
},
|
|
95
|
-
decrementX(stepSize) {
|
|
96
|
-
return (0, import_numeric_range.snapValueToStep)(xValue - stepSize, minValueX, maxValueX, stepX);
|
|
97
|
-
},
|
|
98
|
-
decrementY(stepSize) {
|
|
99
|
-
return (0, import_numeric_range.snapValueToStep)(yValue - stepSize, minValueY, maxValueY, stepY);
|
|
100
|
-
},
|
|
101
|
-
getColorFromPoint(x, y) {
|
|
102
|
-
let newXValue = (0, import_numeric_range.getPercentValue)(x, minValueX, maxValueX, stepX);
|
|
103
|
-
let newYValue = (0, import_numeric_range.getPercentValue)(1 - y, minValueY, maxValueY, stepY);
|
|
104
|
-
let newColor;
|
|
105
|
-
if (newXValue !== xValue) {
|
|
106
|
-
newXValue = (0, import_numeric_range.snapValueToStep)(newXValue, minValueX, maxValueX, stepX);
|
|
107
|
-
newColor = color.withChannelValue(channels.xChannel, newXValue);
|
|
108
|
-
}
|
|
109
|
-
if (newYValue !== yValue) {
|
|
110
|
-
newYValue = (0, import_numeric_range.snapValueToStep)(newYValue, minValueY, maxValueY, stepY);
|
|
111
|
-
newColor = (newColor || color).withChannelValue(channels.yChannel, newYValue);
|
|
112
|
-
}
|
|
113
|
-
return newColor;
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/utils/get-channel-input-value.ts
|
|
119
|
-
function getChannelInputValue(color, channel) {
|
|
120
|
-
switch (channel) {
|
|
121
|
-
case "hex":
|
|
122
|
-
return color.toString("hex");
|
|
123
|
-
case "css":
|
|
124
|
-
return color.toString("css");
|
|
125
|
-
default:
|
|
126
|
-
return color.getChannelValue(channel).toString();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// src/color-picker.machine.ts
|
|
131
16
|
function machine(userContext) {
|
|
132
|
-
const ctx =
|
|
133
|
-
return
|
|
17
|
+
const ctx = utils.compact(userContext);
|
|
18
|
+
return core.createMachine(
|
|
134
19
|
{
|
|
135
20
|
id: "color-picker",
|
|
136
21
|
initial: "idle",
|
|
@@ -141,7 +26,7 @@ function machine(userContext) {
|
|
|
141
26
|
activeOrientation: null,
|
|
142
27
|
value: "#D9D9D9",
|
|
143
28
|
...ctx,
|
|
144
|
-
valueAsColor:
|
|
29
|
+
valueAsColor: colorUtils.parseColor(ctx.value || "#D9D9D9")
|
|
145
30
|
},
|
|
146
31
|
computed: {
|
|
147
32
|
isRtl: (ctx2) => ctx2.dir === "rtl",
|
|
@@ -281,7 +166,7 @@ function machine(userContext) {
|
|
|
281
166
|
},
|
|
282
167
|
activities: {
|
|
283
168
|
trackPointerMove(ctx2, _evt, { send }) {
|
|
284
|
-
return
|
|
169
|
+
return domEvent.trackPointerMove(colorPicker_dom.dom.getDoc(ctx2), {
|
|
285
170
|
onPointerMove({ point }) {
|
|
286
171
|
const type = ctx2.activeId === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
|
|
287
172
|
send({ type, point });
|
|
@@ -293,19 +178,19 @@ function machine(userContext) {
|
|
|
293
178
|
});
|
|
294
179
|
},
|
|
295
180
|
disableTextSelection(ctx2) {
|
|
296
|
-
return
|
|
181
|
+
return textSelection.disableTextSelection({ doc: colorPicker_dom.dom.getDoc(ctx2), target: colorPicker_dom.dom.getContentEl(ctx2) });
|
|
297
182
|
}
|
|
298
183
|
},
|
|
299
184
|
actions: {
|
|
300
185
|
openEyeDropper(ctx2) {
|
|
301
|
-
const isSupported = "EyeDropper" in dom.getWin(ctx2);
|
|
186
|
+
const isSupported = "EyeDropper" in colorPicker_dom.dom.getWin(ctx2);
|
|
302
187
|
if (!isSupported)
|
|
303
188
|
return;
|
|
304
|
-
const win = dom.getWin(ctx2);
|
|
189
|
+
const win = colorPicker_dom.dom.getWin(ctx2);
|
|
305
190
|
const picker = new win.EyeDropper();
|
|
306
191
|
picker.open().then(({ sRGBHex }) => {
|
|
307
192
|
const format = ctx2.valueAsColor.getColorSpace();
|
|
308
|
-
const color =
|
|
193
|
+
const color = colorUtils.parseColor(sRGBHex).toFormat(format);
|
|
309
194
|
setColor(ctx2, color);
|
|
310
195
|
ctx2.onChangeEnd?.({ value: ctx2.value, valueAsColor: color });
|
|
311
196
|
}).catch(() => void 0);
|
|
@@ -326,8 +211,8 @@ function machine(userContext) {
|
|
|
326
211
|
},
|
|
327
212
|
setAreaColorFromPoint(ctx2, evt) {
|
|
328
213
|
const { xChannel, yChannel } = evt.channel || ctx2.activeChannel;
|
|
329
|
-
const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
330
|
-
const { getColorFromPoint } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
214
|
+
const percent = colorPicker_dom.dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
215
|
+
const { getColorFromPoint } = getChannelDetails.getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
331
216
|
const color = getColorFromPoint(percent.x, percent.y);
|
|
332
217
|
if (!color)
|
|
333
218
|
return;
|
|
@@ -335,12 +220,12 @@ function machine(userContext) {
|
|
|
335
220
|
},
|
|
336
221
|
setChannelColorFromPoint(ctx2, evt) {
|
|
337
222
|
const channel = evt.channel || ctx2.activeId;
|
|
338
|
-
const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
|
|
223
|
+
const percent = colorPicker_dom.dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
|
|
339
224
|
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(channel);
|
|
340
225
|
const orientation = ctx2.activeOrientation || "horizontal";
|
|
341
226
|
const point = orientation === "horizontal" ? percent.x : percent.y;
|
|
342
|
-
const channelValue =
|
|
343
|
-
const value =
|
|
227
|
+
const channelValue = numericRange.getPercentValue(point, minValue, maxValue, step);
|
|
228
|
+
const value = numericRange.snapValueToStep(channelValue - step, minValue, maxValue, step);
|
|
344
229
|
const newColor = ctx2.valueAsColor.withChannelValue(channel, value);
|
|
345
230
|
setColor(ctx2, newColor);
|
|
346
231
|
},
|
|
@@ -349,7 +234,7 @@ function machine(userContext) {
|
|
|
349
234
|
},
|
|
350
235
|
setValueAsColor(ctx2) {
|
|
351
236
|
try {
|
|
352
|
-
const color =
|
|
237
|
+
const color = colorUtils.parseColor(ctx2.value);
|
|
353
238
|
if (color.isEqual(ctx2.valueAsColor))
|
|
354
239
|
return;
|
|
355
240
|
ctx2.valueAsColor = color;
|
|
@@ -357,12 +242,12 @@ function machine(userContext) {
|
|
|
357
242
|
}
|
|
358
243
|
},
|
|
359
244
|
syncChannelInputs(ctx2) {
|
|
360
|
-
const inputs = dom.getChannelInputEls(ctx2);
|
|
245
|
+
const inputs = colorPicker_dom.dom.getChannelInputEls(ctx2);
|
|
361
246
|
inputs.forEach((input) => {
|
|
362
247
|
const channel = input.getAttribute("data-channel");
|
|
363
248
|
if (!channel)
|
|
364
249
|
return;
|
|
365
|
-
const value = getChannelInputValue(ctx2.valueAsColor, channel);
|
|
250
|
+
const value = getChannelInputValue.getChannelInputValue(ctx2.valueAsColor, channel);
|
|
366
251
|
input.value = value.toString();
|
|
367
252
|
});
|
|
368
253
|
},
|
|
@@ -370,50 +255,50 @@ function machine(userContext) {
|
|
|
370
255
|
const { channel, isTextField, value } = evt;
|
|
371
256
|
try {
|
|
372
257
|
const format = ctx2.valueAsColor.getColorSpace();
|
|
373
|
-
const newColor = isTextField ?
|
|
258
|
+
const newColor = isTextField ? colorUtils.parseColor(value).toFormat(format) : ctx2.valueAsColor.withChannelValue(channel, value);
|
|
374
259
|
setColor(ctx2, newColor);
|
|
375
260
|
} catch {
|
|
376
|
-
const input = dom.getChannelInputEl(ctx2, channel);
|
|
261
|
+
const input = colorPicker_dom.dom.getChannelInputEl(ctx2, channel);
|
|
377
262
|
if (!input)
|
|
378
263
|
return;
|
|
379
|
-
input.value = getChannelInputValue(ctx2.valueAsColor, channel);
|
|
264
|
+
input.value = getChannelInputValue.getChannelInputValue(ctx2.valueAsColor, channel);
|
|
380
265
|
}
|
|
381
266
|
},
|
|
382
267
|
incrementChannel(ctx2, evt) {
|
|
383
268
|
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
384
269
|
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
385
|
-
const value =
|
|
386
|
-
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel,
|
|
270
|
+
const value = numericRange.snapValueToStep(channelValue + evt.step, minValue, maxValue, step);
|
|
271
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, numericRange.clampValue(value, minValue, maxValue));
|
|
387
272
|
setColor(ctx2, newColor);
|
|
388
273
|
},
|
|
389
274
|
decrementChannel(ctx2, evt) {
|
|
390
275
|
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
391
276
|
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
392
|
-
const value =
|
|
393
|
-
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel,
|
|
277
|
+
const value = numericRange.snapValueToStep(channelValue - evt.step, minValue, maxValue, step);
|
|
278
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, numericRange.clampValue(value, minValue, maxValue));
|
|
394
279
|
setColor(ctx2, newColor);
|
|
395
280
|
},
|
|
396
281
|
incrementXChannel(ctx2, evt) {
|
|
397
282
|
const { xChannel, yChannel } = evt.channel;
|
|
398
|
-
const { incrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
283
|
+
const { incrementX } = getChannelDetails.getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
399
284
|
const newColor = ctx2.valueAsColor.withChannelValue(xChannel, incrementX(evt.step));
|
|
400
285
|
setColor(ctx2, newColor);
|
|
401
286
|
},
|
|
402
287
|
decrementXChannel(ctx2, evt) {
|
|
403
288
|
const { xChannel, yChannel } = evt.channel;
|
|
404
|
-
const { decrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
289
|
+
const { decrementX } = getChannelDetails.getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
405
290
|
const newColor = ctx2.valueAsColor.withChannelValue(xChannel, decrementX(evt.step));
|
|
406
291
|
setColor(ctx2, newColor);
|
|
407
292
|
},
|
|
408
293
|
incrementYChannel(ctx2, evt) {
|
|
409
294
|
const { xChannel, yChannel } = evt.channel;
|
|
410
|
-
const { incrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
295
|
+
const { incrementY } = getChannelDetails.getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
411
296
|
const newColor = ctx2.valueAsColor.withChannelValue(yChannel, incrementY(evt.step));
|
|
412
297
|
setColor(ctx2, newColor);
|
|
413
298
|
},
|
|
414
299
|
decrementYChannel(ctx2, evt) {
|
|
415
300
|
const { xChannel, yChannel } = evt.channel;
|
|
416
|
-
const { decrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
301
|
+
const { decrementY } = getChannelDetails.getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
417
302
|
const newColor = ctx2.valueAsColor.withChannelValue(yChannel, decrementY(evt.step));
|
|
418
303
|
setColor(ctx2, newColor);
|
|
419
304
|
},
|
|
@@ -434,24 +319,22 @@ function machine(userContext) {
|
|
|
434
319
|
ctx2.onChange?.({ value: ctx2.value, valueAsColor: ctx2.valueAsColor });
|
|
435
320
|
},
|
|
436
321
|
focusAreaThumb(ctx2) {
|
|
437
|
-
|
|
438
|
-
dom.getAreaThumbEl(ctx2)?.focus({ preventScroll: true });
|
|
322
|
+
domQuery.raf(() => {
|
|
323
|
+
colorPicker_dom.dom.getAreaThumbEl(ctx2)?.focus({ preventScroll: true });
|
|
439
324
|
});
|
|
440
325
|
},
|
|
441
326
|
focusChannelThumb(ctx2, evt) {
|
|
442
|
-
|
|
443
|
-
dom.getChannelSliderThumbEl(ctx2, evt.channel)?.focus({ preventScroll: true });
|
|
327
|
+
domQuery.raf(() => {
|
|
328
|
+
colorPicker_dom.dom.getChannelSliderThumbEl(ctx2, evt.channel)?.focus({ preventScroll: true });
|
|
444
329
|
});
|
|
445
330
|
}
|
|
446
331
|
}
|
|
447
332
|
}
|
|
448
333
|
);
|
|
449
334
|
}
|
|
450
|
-
|
|
335
|
+
const setColor = (ctx, color) => {
|
|
451
336
|
ctx.value = color.toString("css");
|
|
452
337
|
ctx.valueAsColor = color;
|
|
453
338
|
};
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
machine
|
|
457
|
-
});
|
|
339
|
+
|
|
340
|
+
exports.machine = machine;
|
|
@@ -1,9 +1,336 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { parseColor } from '@zag-js/color-utils';
|
|
2
|
+
import { createMachine } from '@zag-js/core';
|
|
3
|
+
import { trackPointerMove } from '@zag-js/dom-event';
|
|
4
|
+
import { raf } from '@zag-js/dom-query';
|
|
5
|
+
import { getPercentValue, snapValueToStep, clampValue } from '@zag-js/numeric-range';
|
|
6
|
+
import { disableTextSelection } from '@zag-js/text-selection';
|
|
7
|
+
import { compact } from '@zag-js/utils';
|
|
8
|
+
import { dom } from './color-picker.dom.mjs';
|
|
9
|
+
import { getChannelDetails } from './utils/get-channel-details.mjs';
|
|
10
|
+
import { getChannelInputValue } from './utils/get-channel-input-value.mjs';
|
|
11
|
+
|
|
12
|
+
function machine(userContext) {
|
|
13
|
+
const ctx = compact(userContext);
|
|
14
|
+
return createMachine(
|
|
15
|
+
{
|
|
16
|
+
id: "color-picker",
|
|
17
|
+
initial: "idle",
|
|
18
|
+
context: {
|
|
19
|
+
dir: "ltr",
|
|
20
|
+
activeId: null,
|
|
21
|
+
activeChannel: null,
|
|
22
|
+
activeOrientation: null,
|
|
23
|
+
value: "#D9D9D9",
|
|
24
|
+
...ctx,
|
|
25
|
+
valueAsColor: parseColor(ctx.value || "#D9D9D9")
|
|
26
|
+
},
|
|
27
|
+
computed: {
|
|
28
|
+
isRtl: (ctx2) => ctx2.dir === "rtl",
|
|
29
|
+
isInteractive: (ctx2) => !(ctx2.disabled || ctx2.readOnly)
|
|
30
|
+
},
|
|
31
|
+
on: {
|
|
32
|
+
"VALUE.SET": {
|
|
33
|
+
actions: ["setValue"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
created: ["setValueAsColor"],
|
|
37
|
+
watch: {
|
|
38
|
+
value: ["setValueAsColor", "syncChannelInputs", "invokeOnChange"]
|
|
39
|
+
},
|
|
40
|
+
states: {
|
|
41
|
+
idle: {
|
|
42
|
+
on: {
|
|
43
|
+
"EYEDROPPER.CLICK": {
|
|
44
|
+
actions: ["openEyeDropper"]
|
|
45
|
+
},
|
|
46
|
+
"AREA.POINTER_DOWN": {
|
|
47
|
+
target: "dragging",
|
|
48
|
+
actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
|
|
49
|
+
},
|
|
50
|
+
"CHANNEL_SLIDER.POINTER_DOWN": {
|
|
51
|
+
target: "dragging",
|
|
52
|
+
actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
|
|
53
|
+
},
|
|
54
|
+
"CHANNEL_INPUT.FOCUS": {
|
|
55
|
+
target: "focused",
|
|
56
|
+
actions: ["setActiveChannel"]
|
|
57
|
+
},
|
|
58
|
+
"CHANNEL_INPUT.CHANGE": {
|
|
59
|
+
actions: ["setChannelColorFromInput"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
focused: {
|
|
64
|
+
on: {
|
|
65
|
+
"AREA.POINTER_DOWN": {
|
|
66
|
+
target: "dragging",
|
|
67
|
+
actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
|
|
68
|
+
},
|
|
69
|
+
"CHANNEL_SLIDER.POINTER_DOWN": {
|
|
70
|
+
target: "dragging",
|
|
71
|
+
actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
|
|
72
|
+
},
|
|
73
|
+
"AREA.ARROW_LEFT": {
|
|
74
|
+
actions: ["decrementXChannel"]
|
|
75
|
+
},
|
|
76
|
+
"AREA.ARROW_RIGHT": {
|
|
77
|
+
actions: ["incrementXChannel"]
|
|
78
|
+
},
|
|
79
|
+
"AREA.ARROW_UP": {
|
|
80
|
+
actions: ["incrementYChannel"]
|
|
81
|
+
},
|
|
82
|
+
"AREA.ARROW_DOWN": {
|
|
83
|
+
actions: ["decrementYChannel"]
|
|
84
|
+
},
|
|
85
|
+
"AREA.PAGE_UP": {
|
|
86
|
+
actions: ["incrementXChannel"]
|
|
87
|
+
},
|
|
88
|
+
"AREA.PAGE_DOWN": {
|
|
89
|
+
actions: ["decrementXChannel"]
|
|
90
|
+
},
|
|
91
|
+
"CHANNEL_SLIDER.ARROW_LEFT": {
|
|
92
|
+
actions: ["decrementChannel"]
|
|
93
|
+
},
|
|
94
|
+
"CHANNEL_SLIDER.ARROW_RIGHT": {
|
|
95
|
+
actions: ["incrementChannel"]
|
|
96
|
+
},
|
|
97
|
+
"CHANNEL_SLIDER.ARROW_UP": {
|
|
98
|
+
actions: ["incrementChannel"]
|
|
99
|
+
},
|
|
100
|
+
"CHANNEL_SLIDER.ARROW_DOWN": {
|
|
101
|
+
actions: ["decrementChannel"]
|
|
102
|
+
},
|
|
103
|
+
"CHANNEL_SLIDER.PAGE_UP": {
|
|
104
|
+
actions: ["incrementChannel"]
|
|
105
|
+
},
|
|
106
|
+
"CHANNEL_SLIDER.PAGE_DOWN": {
|
|
107
|
+
actions: ["decrementChannel"]
|
|
108
|
+
},
|
|
109
|
+
"CHANNEL_SLIDER.HOME": {
|
|
110
|
+
actions: ["setChannelToMin"]
|
|
111
|
+
},
|
|
112
|
+
"CHANNEL_SLIDER.END": {
|
|
113
|
+
actions: ["setChannelToMax"]
|
|
114
|
+
},
|
|
115
|
+
"CHANNEL_INPUT.FOCUS": {
|
|
116
|
+
actions: ["setActiveChannel"]
|
|
117
|
+
},
|
|
118
|
+
"CHANNEL_INPUT.CHANGE": {
|
|
119
|
+
actions: ["setChannelColorFromInput"]
|
|
120
|
+
},
|
|
121
|
+
"CHANNEL_INPUT.BLUR": [
|
|
122
|
+
{
|
|
123
|
+
guard: "isTextField",
|
|
124
|
+
target: "idle",
|
|
125
|
+
actions: ["setChannelColorFromInput"]
|
|
126
|
+
},
|
|
127
|
+
{ target: "idle" }
|
|
128
|
+
],
|
|
129
|
+
"CHANNEL_SLIDER.BLUR": {
|
|
130
|
+
target: "idle"
|
|
131
|
+
},
|
|
132
|
+
"AREA.BLUR": {
|
|
133
|
+
target: "idle"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
dragging: {
|
|
138
|
+
exit: ["clearActiveChannel"],
|
|
139
|
+
activities: ["trackPointerMove", "disableTextSelection"],
|
|
140
|
+
on: {
|
|
141
|
+
"AREA.POINTER_MOVE": {
|
|
142
|
+
actions: ["setAreaColorFromPoint"]
|
|
143
|
+
},
|
|
144
|
+
"AREA.POINTER_UP": {
|
|
145
|
+
target: "focused",
|
|
146
|
+
actions: ["invokeOnChangeEnd"]
|
|
147
|
+
},
|
|
148
|
+
"CHANNEL_SLIDER.POINTER_MOVE": {
|
|
149
|
+
actions: ["setChannelColorFromPoint"]
|
|
150
|
+
},
|
|
151
|
+
"CHANNEL_SLIDER.POINTER_UP": {
|
|
152
|
+
target: "focused",
|
|
153
|
+
actions: ["invokeOnChangeEnd"]
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
guards: {
|
|
161
|
+
isTextField: (_ctx, evt) => !!evt.isTextField
|
|
162
|
+
},
|
|
163
|
+
activities: {
|
|
164
|
+
trackPointerMove(ctx2, _evt, { send }) {
|
|
165
|
+
return trackPointerMove(dom.getDoc(ctx2), {
|
|
166
|
+
onPointerMove({ point }) {
|
|
167
|
+
const type = ctx2.activeId === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
|
|
168
|
+
send({ type, point });
|
|
169
|
+
},
|
|
170
|
+
onPointerUp() {
|
|
171
|
+
const type = ctx2.activeId === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP";
|
|
172
|
+
send({ type });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
},
|
|
176
|
+
disableTextSelection(ctx2) {
|
|
177
|
+
return disableTextSelection({ doc: dom.getDoc(ctx2), target: dom.getContentEl(ctx2) });
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
actions: {
|
|
181
|
+
openEyeDropper(ctx2) {
|
|
182
|
+
const isSupported = "EyeDropper" in dom.getWin(ctx2);
|
|
183
|
+
if (!isSupported)
|
|
184
|
+
return;
|
|
185
|
+
const win = dom.getWin(ctx2);
|
|
186
|
+
const picker = new win.EyeDropper();
|
|
187
|
+
picker.open().then(({ sRGBHex }) => {
|
|
188
|
+
const format = ctx2.valueAsColor.getColorSpace();
|
|
189
|
+
const color = parseColor(sRGBHex).toFormat(format);
|
|
190
|
+
setColor(ctx2, color);
|
|
191
|
+
ctx2.onChangeEnd?.({ value: ctx2.value, valueAsColor: color });
|
|
192
|
+
}).catch(() => void 0);
|
|
193
|
+
},
|
|
194
|
+
setActiveChannel(ctx2, evt) {
|
|
195
|
+
ctx2.activeId = evt.id;
|
|
196
|
+
if (evt.channel) {
|
|
197
|
+
ctx2.activeChannel = evt.channel;
|
|
198
|
+
}
|
|
199
|
+
if (evt.orientation) {
|
|
200
|
+
ctx2.activeOrientation = evt.orientation;
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
clearActiveChannel(ctx2) {
|
|
204
|
+
ctx2.activeChannel = null;
|
|
205
|
+
ctx2.activeId = null;
|
|
206
|
+
ctx2.activeOrientation = null;
|
|
207
|
+
},
|
|
208
|
+
setAreaColorFromPoint(ctx2, evt) {
|
|
209
|
+
const { xChannel, yChannel } = evt.channel || ctx2.activeChannel;
|
|
210
|
+
const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
|
|
211
|
+
const { getColorFromPoint } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
212
|
+
const color = getColorFromPoint(percent.x, percent.y);
|
|
213
|
+
if (!color)
|
|
214
|
+
return;
|
|
215
|
+
setColor(ctx2, color);
|
|
216
|
+
},
|
|
217
|
+
setChannelColorFromPoint(ctx2, evt) {
|
|
218
|
+
const channel = evt.channel || ctx2.activeId;
|
|
219
|
+
const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
|
|
220
|
+
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(channel);
|
|
221
|
+
const orientation = ctx2.activeOrientation || "horizontal";
|
|
222
|
+
const point = orientation === "horizontal" ? percent.x : percent.y;
|
|
223
|
+
const channelValue = getPercentValue(point, minValue, maxValue, step);
|
|
224
|
+
const value = snapValueToStep(channelValue - step, minValue, maxValue, step);
|
|
225
|
+
const newColor = ctx2.valueAsColor.withChannelValue(channel, value);
|
|
226
|
+
setColor(ctx2, newColor);
|
|
227
|
+
},
|
|
228
|
+
setValue(ctx2, evt) {
|
|
229
|
+
setColor(ctx2, evt.value);
|
|
230
|
+
},
|
|
231
|
+
setValueAsColor(ctx2) {
|
|
232
|
+
try {
|
|
233
|
+
const color = parseColor(ctx2.value);
|
|
234
|
+
if (color.isEqual(ctx2.valueAsColor))
|
|
235
|
+
return;
|
|
236
|
+
ctx2.valueAsColor = color;
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
syncChannelInputs(ctx2) {
|
|
241
|
+
const inputs = dom.getChannelInputEls(ctx2);
|
|
242
|
+
inputs.forEach((input) => {
|
|
243
|
+
const channel = input.getAttribute("data-channel");
|
|
244
|
+
if (!channel)
|
|
245
|
+
return;
|
|
246
|
+
const value = getChannelInputValue(ctx2.valueAsColor, channel);
|
|
247
|
+
input.value = value.toString();
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
setChannelColorFromInput(ctx2, evt) {
|
|
251
|
+
const { channel, isTextField, value } = evt;
|
|
252
|
+
try {
|
|
253
|
+
const format = ctx2.valueAsColor.getColorSpace();
|
|
254
|
+
const newColor = isTextField ? parseColor(value).toFormat(format) : ctx2.valueAsColor.withChannelValue(channel, value);
|
|
255
|
+
setColor(ctx2, newColor);
|
|
256
|
+
} catch {
|
|
257
|
+
const input = dom.getChannelInputEl(ctx2, channel);
|
|
258
|
+
if (!input)
|
|
259
|
+
return;
|
|
260
|
+
input.value = getChannelInputValue(ctx2.valueAsColor, channel);
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
incrementChannel(ctx2, evt) {
|
|
264
|
+
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
265
|
+
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
266
|
+
const value = snapValueToStep(channelValue + evt.step, minValue, maxValue, step);
|
|
267
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
|
|
268
|
+
setColor(ctx2, newColor);
|
|
269
|
+
},
|
|
270
|
+
decrementChannel(ctx2, evt) {
|
|
271
|
+
const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
272
|
+
const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
|
|
273
|
+
const value = snapValueToStep(channelValue - evt.step, minValue, maxValue, step);
|
|
274
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
|
|
275
|
+
setColor(ctx2, newColor);
|
|
276
|
+
},
|
|
277
|
+
incrementXChannel(ctx2, evt) {
|
|
278
|
+
const { xChannel, yChannel } = evt.channel;
|
|
279
|
+
const { incrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
280
|
+
const newColor = ctx2.valueAsColor.withChannelValue(xChannel, incrementX(evt.step));
|
|
281
|
+
setColor(ctx2, newColor);
|
|
282
|
+
},
|
|
283
|
+
decrementXChannel(ctx2, evt) {
|
|
284
|
+
const { xChannel, yChannel } = evt.channel;
|
|
285
|
+
const { decrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
286
|
+
const newColor = ctx2.valueAsColor.withChannelValue(xChannel, decrementX(evt.step));
|
|
287
|
+
setColor(ctx2, newColor);
|
|
288
|
+
},
|
|
289
|
+
incrementYChannel(ctx2, evt) {
|
|
290
|
+
const { xChannel, yChannel } = evt.channel;
|
|
291
|
+
const { incrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
292
|
+
const newColor = ctx2.valueAsColor.withChannelValue(yChannel, incrementY(evt.step));
|
|
293
|
+
setColor(ctx2, newColor);
|
|
294
|
+
},
|
|
295
|
+
decrementYChannel(ctx2, evt) {
|
|
296
|
+
const { xChannel, yChannel } = evt.channel;
|
|
297
|
+
const { decrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
|
|
298
|
+
const newColor = ctx2.valueAsColor.withChannelValue(yChannel, decrementY(evt.step));
|
|
299
|
+
setColor(ctx2, newColor);
|
|
300
|
+
},
|
|
301
|
+
setChannelToMax(ctx2, evt) {
|
|
302
|
+
const { maxValue } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
303
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, maxValue);
|
|
304
|
+
setColor(ctx2, newColor);
|
|
305
|
+
},
|
|
306
|
+
setChannelToMin(ctx2, evt) {
|
|
307
|
+
const { minValue } = ctx2.valueAsColor.getChannelRange(evt.channel);
|
|
308
|
+
const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, minValue);
|
|
309
|
+
setColor(ctx2, newColor);
|
|
310
|
+
},
|
|
311
|
+
invokeOnChangeEnd(ctx2) {
|
|
312
|
+
ctx2.onChangeEnd?.({ value: ctx2.value, valueAsColor: ctx2.valueAsColor });
|
|
313
|
+
},
|
|
314
|
+
invokeOnChange(ctx2) {
|
|
315
|
+
ctx2.onChange?.({ value: ctx2.value, valueAsColor: ctx2.valueAsColor });
|
|
316
|
+
},
|
|
317
|
+
focusAreaThumb(ctx2) {
|
|
318
|
+
raf(() => {
|
|
319
|
+
dom.getAreaThumbEl(ctx2)?.focus({ preventScroll: true });
|
|
320
|
+
});
|
|
321
|
+
},
|
|
322
|
+
focusChannelThumb(ctx2, evt) {
|
|
323
|
+
raf(() => {
|
|
324
|
+
dom.getChannelSliderThumbEl(ctx2, evt.channel)?.focus({ preventScroll: true });
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
const setColor = (ctx, color) => {
|
|
332
|
+
ctx.value = color.toString("css");
|
|
333
|
+
ctx.valueAsColor = color;
|
|
9
334
|
};
|
|
335
|
+
|
|
336
|
+
export { machine };
|