@zag-js/color-picker 0.10.4 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/index.d.mts +150 -0
  2. package/dist/index.d.ts +150 -4
  3. package/dist/index.js +1086 -8
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.mjs +1069 -3
  6. package/dist/index.mjs.map +1 -0
  7. package/package.json +11 -11
  8. package/dist/color-picker.anatomy.d.ts +0 -3
  9. package/dist/color-picker.anatomy.js +0 -24
  10. package/dist/color-picker.anatomy.mjs +0 -19
  11. package/dist/color-picker.connect.d.ts +0 -44
  12. package/dist/color-picker.connect.js +0 -372
  13. package/dist/color-picker.connect.mjs +0 -368
  14. package/dist/color-picker.dom.d.ts +0 -46
  15. package/dist/color-picker.dom.js +0 -37
  16. package/dist/color-picker.dom.mjs +0 -33
  17. package/dist/color-picker.machine.d.ts +0 -3
  18. package/dist/color-picker.machine.js +0 -340
  19. package/dist/color-picker.machine.mjs +0 -336
  20. package/dist/color-picker.types.d.ts +0 -99
  21. package/dist/utils/generate-format-background.d.ts +0 -66
  22. package/dist/utils/generate-format-background.js +0 -133
  23. package/dist/utils/generate-format-background.mjs +0 -121
  24. package/dist/utils/get-channel-details.d.ts +0 -19
  25. package/dist/utils/get-channel-details.js +0 -57
  26. package/dist/utils/get-channel-details.mjs +0 -53
  27. package/dist/utils/get-channel-display-color.d.ts +0 -3
  28. package/dist/utils/get-channel-display-color.js +0 -26
  29. package/dist/utils/get-channel-display-color.mjs +0 -22
  30. package/dist/utils/get-channel-input-value.d.ts +0 -5
  31. package/dist/utils/get-channel-input-value.js +0 -26
  32. package/dist/utils/get-channel-input-value.mjs +0 -21
  33. package/dist/utils/get-color-area-gradient.d.ts +0 -7
  34. package/dist/utils/get-color-area-gradient.js +0 -65
  35. package/dist/utils/get-color-area-gradient.mjs +0 -61
  36. package/dist/utils/get-slider-background.d.ts +0 -2
  37. package/dist/utils/get-slider-background.js +0 -43
  38. package/dist/utils/get-slider-background.mjs +0 -39
package/dist/index.mjs CHANGED
@@ -1,3 +1,1069 @@
1
- export { anatomy } from './color-picker.anatomy.mjs';
2
- export { connect } from './color-picker.connect.mjs';
3
- export { machine } from './color-picker.machine.mjs';
1
+ // src/color-picker.anatomy.ts
2
+ import { createAnatomy } from "@zag-js/anatomy";
3
+ var anatomy = createAnatomy("color-picker", [
4
+ "area",
5
+ "areaThumb",
6
+ "areaGradient",
7
+ "channelSliderTrack",
8
+ "channelSliderTrackBg",
9
+ "channelSliderThumb",
10
+ "channelInput",
11
+ "swatch",
12
+ "swatchBg",
13
+ "content",
14
+ "label",
15
+ "eyeDropTrigger"
16
+ ]);
17
+ var parts = anatomy.build();
18
+
19
+ // src/color-picker.connect.ts
20
+ import { normalizeColor } from "@zag-js/color-utils";
21
+ import {
22
+ getEventKey,
23
+ getEventPoint,
24
+ getEventStep,
25
+ getNativeEvent,
26
+ isLeftClick,
27
+ isModifiedEvent
28
+ } from "@zag-js/dom-event";
29
+ import { dataAttr } from "@zag-js/dom-query";
30
+
31
+ // src/color-picker.dom.ts
32
+ import { getRelativePoint } from "@zag-js/dom-event";
33
+ import { createScope, queryAll } from "@zag-js/dom-query";
34
+ var dom = createScope({
35
+ getContentId: (ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`,
36
+ getAreaId: (ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`,
37
+ getAreaGradientId: (ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`,
38
+ getAreaThumbId: (ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`,
39
+ getChannelSliderTrackId: (ctx, channel) => ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
40
+ getChannelInputId: (ctx, channel) => ctx.ids?.channelInput?.(channel) ?? `color-picker:${ctx.id}:input:${channel}`,
41
+ getChannelSliderThumbId: (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
42
+ getContentEl: (ctx) => dom.queryById(ctx, dom.getContentId(ctx)),
43
+ getAreaThumbEl: (ctx) => dom.queryById(ctx, dom.getAreaThumbId(ctx)),
44
+ getChannelSliderThumbEl: (ctx, channel) => dom.queryById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
45
+ getChannelInputEl: (ctx, channel) => dom.queryById(ctx, dom.getChannelInputId(ctx, channel)),
46
+ getAreaEl: (ctx) => dom.queryById(ctx, dom.getAreaId(ctx)),
47
+ getAreaValueFromPoint(ctx, point) {
48
+ const { percent } = getRelativePoint(point, dom.getAreaEl(ctx));
49
+ return percent;
50
+ },
51
+ getChannelSliderTrackEl: (ctx, channel) => {
52
+ return dom.queryById(ctx, dom.getChannelSliderTrackId(ctx, channel));
53
+ },
54
+ getChannelSliderValueFromPoint(ctx, point, channel) {
55
+ const { percent } = getRelativePoint(point, dom.getChannelSliderTrackEl(ctx, channel));
56
+ return percent;
57
+ },
58
+ getChannelInputEls: (ctx) => {
59
+ return queryAll(dom.getContentEl(ctx), "input[data-channel]");
60
+ }
61
+ });
62
+
63
+ // src/utils/get-channel-details.ts
64
+ import { getPercentValue, snapValueToStep } from "@zag-js/numeric-range";
65
+ function getChannelDetails(color, xChannel, yChannel) {
66
+ const channels = color.getColorSpaceAxes({ xChannel, yChannel });
67
+ const xChannelRange = color.getChannelRange(channels.xChannel);
68
+ const yChannelRange = color.getChannelRange(channels.yChannel);
69
+ const { minValue: minValueX, maxValue: maxValueX, step: stepX, pageSize: pageSizeX } = xChannelRange;
70
+ const { minValue: minValueY, maxValue: maxValueY, step: stepY, pageSize: pageSizeY } = yChannelRange;
71
+ const xValue = color.getChannelValue(channels.xChannel);
72
+ const yValue = color.getChannelValue(channels.yChannel);
73
+ return {
74
+ channels,
75
+ xChannelStep: stepX,
76
+ yChannelStep: stepY,
77
+ xChannelPageStep: pageSizeX,
78
+ yChannelPageStep: pageSizeY,
79
+ xValue,
80
+ yValue,
81
+ getThumbPosition() {
82
+ let x = (xValue - minValueX) / (maxValueX - minValueX);
83
+ let y = 1 - (yValue - minValueY) / (maxValueY - minValueY);
84
+ return { x, y };
85
+ },
86
+ incrementX(stepSize) {
87
+ return xValue + stepSize > maxValueX ? maxValueX : snapValueToStep(xValue + stepSize, minValueX, maxValueX, stepX);
88
+ },
89
+ incrementY(stepSize) {
90
+ return yValue + stepSize > maxValueY ? maxValueY : snapValueToStep(yValue + stepSize, minValueY, maxValueY, stepY);
91
+ },
92
+ decrementX(stepSize) {
93
+ return snapValueToStep(xValue - stepSize, minValueX, maxValueX, stepX);
94
+ },
95
+ decrementY(stepSize) {
96
+ return snapValueToStep(yValue - stepSize, minValueY, maxValueY, stepY);
97
+ },
98
+ getColorFromPoint(x, y) {
99
+ let newXValue = getPercentValue(x, minValueX, maxValueX, stepX);
100
+ let newYValue = getPercentValue(1 - y, minValueY, maxValueY, stepY);
101
+ let newColor;
102
+ if (newXValue !== xValue) {
103
+ newXValue = snapValueToStep(newXValue, minValueX, maxValueX, stepX);
104
+ newColor = color.withChannelValue(channels.xChannel, newXValue);
105
+ }
106
+ if (newYValue !== yValue) {
107
+ newYValue = snapValueToStep(newYValue, minValueY, maxValueY, stepY);
108
+ newColor = (newColor || color).withChannelValue(channels.yChannel, newYValue);
109
+ }
110
+ return newColor;
111
+ }
112
+ };
113
+ }
114
+
115
+ // src/utils/get-channel-display-color.ts
116
+ import { parseColor } from "@zag-js/color-utils";
117
+ function getChannelDisplayColor(color, channel) {
118
+ switch (channel) {
119
+ case "hue":
120
+ return parseColor(`hsl(${color.getChannelValue("hue")}, 100%, 50%)`);
121
+ case "lightness":
122
+ case "brightness":
123
+ case "saturation":
124
+ case "red":
125
+ case "green":
126
+ case "blue":
127
+ return color.withChannelValue("alpha", 1);
128
+ case "alpha": {
129
+ return color;
130
+ }
131
+ default:
132
+ throw new Error("Unknown color channel: " + channel);
133
+ }
134
+ }
135
+
136
+ // src/utils/get-channel-input-value.ts
137
+ function getChannelInputValue(color, channel) {
138
+ switch (channel) {
139
+ case "hex":
140
+ return color.toString("hex");
141
+ case "css":
142
+ return color.toString("css");
143
+ default:
144
+ return color.getChannelValue(channel).toString();
145
+ }
146
+ }
147
+ function getChannelInputRange(color, channel) {
148
+ switch (channel) {
149
+ case "hex":
150
+ case "css":
151
+ return void 0;
152
+ default:
153
+ return color.getChannelRange(channel);
154
+ }
155
+ }
156
+
157
+ // src/utils/generate-format-background.ts
158
+ var generateRGB_R = (orientation, dir, zValue) => {
159
+ const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
160
+ const result = {
161
+ areaStyles: {
162
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,0),rgb(${zValue},255,0))`
163
+ },
164
+ areaGradientStyles: {
165
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,255),rgb(${zValue},255,255))`,
166
+ WebkitMaskImage: maskImage,
167
+ maskImage
168
+ }
169
+ };
170
+ return result;
171
+ };
172
+ var generateRGB_G = (orientation, dir, zValue) => {
173
+ const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
174
+ const result = {
175
+ areaStyles: {
176
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},0),rgb(255,${zValue},0))`
177
+ },
178
+ areaGradientStyles: {
179
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},255),rgb(255,${zValue},255))`,
180
+ WebkitMaskImage: maskImage,
181
+ maskImage
182
+ }
183
+ };
184
+ return result;
185
+ };
186
+ var generateRGB_B = (orientation, dir, zValue) => {
187
+ const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
188
+ const result = {
189
+ areaStyles: {
190
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,0,${zValue}),rgb(255,0,${zValue}))`
191
+ },
192
+ areaGradientStyles: {
193
+ backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,255,${zValue}),rgb(255,255,${zValue}))`,
194
+ WebkitMaskImage: maskImage,
195
+ maskImage
196
+ }
197
+ };
198
+ return result;
199
+ };
200
+ var generateHSL_H = (orientation, dir, zValue) => {
201
+ const result = {
202
+ areaStyles: {},
203
+ areaGradientStyles: {
204
+ background: [
205
+ `linear-gradient(to ${orientation[Number(dir)]}, hsla(0,0%,0%,1) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,1) 100%)`,
206
+ `linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,50%),hsla(0,0%,50%,0))`,
207
+ `hsl(${zValue}, 100%, 50%)`
208
+ ].join(",")
209
+ }
210
+ };
211
+ return result;
212
+ };
213
+ var generateHSL_S = (orientation, dir, alphaValue) => {
214
+ const result = {
215
+ areaStyles: {},
216
+ areaGradientStyles: {
217
+ background: [
218
+ `linear-gradient(to ${orientation[Number(!dir)]}, hsla(0,0%,0%,${alphaValue}) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,${alphaValue}) 100%)`,
219
+ `linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
220
+ "hsl(0, 0%, 50%)"
221
+ ].join(",")
222
+ }
223
+ };
224
+ return result;
225
+ };
226
+ var generateHSL_L = (orientation, dir, zValue) => {
227
+ const result = {
228
+ areaStyles: {},
229
+ areaGradientStyles: {
230
+ backgroundImage: [
231
+ `linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,${zValue}%),hsla(0,0%,${zValue}%,0))`,
232
+ `linear-gradient(to ${orientation[Number(dir)]},hsl(0,100%,${zValue}%),hsl(60,100%,${zValue}%),hsl(120,100%,${zValue}%),hsl(180,100%,${zValue}%),hsl(240,100%,${zValue}%),hsl(300,100%,${zValue}%),hsl(360,100%,${zValue}%))`
233
+ ].join(",")
234
+ }
235
+ };
236
+ return result;
237
+ };
238
+ var generateHSB_H = (orientation, dir, zValue) => {
239
+ const result = {
240
+ areaStyles: {},
241
+ areaGradientStyles: {
242
+ background: [
243
+ `linear-gradient(to ${orientation[Number(dir)]},hsl(0,0%,0%),hsla(0,0%,0%,0))`,
244
+ `linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,100%),hsla(0,0%,100%,0))`,
245
+ `hsl(${zValue}, 100%, 50%)`
246
+ ].join(",")
247
+ }
248
+ };
249
+ return result;
250
+ };
251
+ var generateHSB_S = (orientation, dir, alphaValue) => {
252
+ const result = {
253
+ areaStyles: {},
254
+ areaGradientStyles: {
255
+ background: [
256
+ `linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,0%,${alphaValue}),hsla(0,0%,0%,0))`,
257
+ `linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
258
+ `linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,0%),hsl(0,0%,100%))`
259
+ ].join(",")
260
+ }
261
+ };
262
+ return result;
263
+ };
264
+ var generateHSB_B = (orientation, dir, alphaValue) => {
265
+ const result = {
266
+ areaStyles: {},
267
+ areaGradientStyles: {
268
+ background: [
269
+ `linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,100%,${alphaValue}),hsla(0,0%,100%,0))`,
270
+ `linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
271
+ "#000"
272
+ ].join(",")
273
+ }
274
+ };
275
+ return result;
276
+ };
277
+
278
+ // src/utils/get-color-area-gradient.ts
279
+ function getColorAreaGradient(ctx, xChannel, yChannel) {
280
+ const value = ctx.valueAsColor;
281
+ const { zChannel } = value.getColorSpaceAxes({ xChannel, yChannel });
282
+ const zValue = value.getChannelValue(zChannel);
283
+ const { minValue: zMin, maxValue: zMax } = value.getChannelRange(zChannel);
284
+ const orientation = ["top", ctx.dir === "rtl" ? "left" : "right"];
285
+ let dir = false;
286
+ let background = { areaStyles: {}, areaGradientStyles: {} };
287
+ let alphaValue = (zValue - zMin) / (zMax - zMin);
288
+ let isHSL = value.getColorSpace() === "hsl";
289
+ switch (zChannel) {
290
+ case "red": {
291
+ dir = xChannel === "green";
292
+ background = generateRGB_R(orientation, dir, zValue);
293
+ break;
294
+ }
295
+ case "green": {
296
+ dir = xChannel === "red";
297
+ background = generateRGB_G(orientation, dir, zValue);
298
+ break;
299
+ }
300
+ case "blue": {
301
+ dir = xChannel === "red";
302
+ background = generateRGB_B(orientation, dir, zValue);
303
+ break;
304
+ }
305
+ case "hue": {
306
+ dir = xChannel !== "saturation";
307
+ if (isHSL) {
308
+ background = generateHSL_H(orientation, dir, zValue);
309
+ } else {
310
+ background = generateHSB_H(orientation, dir, zValue);
311
+ }
312
+ break;
313
+ }
314
+ case "saturation": {
315
+ dir = xChannel === "hue";
316
+ if (isHSL) {
317
+ background = generateHSL_S(orientation, dir, alphaValue);
318
+ } else {
319
+ background = generateHSB_S(orientation, dir, alphaValue);
320
+ }
321
+ break;
322
+ }
323
+ case "brightness": {
324
+ dir = xChannel === "hue";
325
+ background = generateHSB_B(orientation, dir, alphaValue);
326
+ break;
327
+ }
328
+ case "lightness": {
329
+ dir = xChannel === "hue";
330
+ background = generateHSL_L(orientation, dir, zValue);
331
+ break;
332
+ }
333
+ }
334
+ return background;
335
+ }
336
+
337
+ // src/utils/get-slider-background.ts
338
+ function getSliderBgDirection(orientation, dir) {
339
+ if (orientation === "vertical") {
340
+ return "top";
341
+ } else if (dir === "ltr") {
342
+ return "right";
343
+ } else {
344
+ return "left";
345
+ }
346
+ }
347
+ var getSliderBgImage = (ctx, props) => {
348
+ const { channel } = props;
349
+ const dir = getSliderBgDirection(props.orientation, ctx.dir);
350
+ const value = ctx.valueAsColor;
351
+ const { minValue, maxValue } = ctx.valueAsColor.getChannelRange(channel);
352
+ switch (channel) {
353
+ case "hue":
354
+ return `linear-gradient(to ${dir}, 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%)`;
355
+ case "lightness": {
356
+ let start = ctx.valueAsColor.withChannelValue(channel, minValue).toString("css");
357
+ let middle = value.withChannelValue(channel, (maxValue - minValue) / 2).toString("css");
358
+ let end = value.withChannelValue(channel, maxValue).toString("css");
359
+ return `linear-gradient(to ${dir}, ${start}, ${middle}, ${end})`;
360
+ }
361
+ case "saturation":
362
+ case "brightness":
363
+ case "red":
364
+ case "green":
365
+ case "blue":
366
+ case "alpha": {
367
+ let start = value.withChannelValue(channel, minValue).toString("css");
368
+ let end = value.withChannelValue(channel, maxValue).toString("css");
369
+ return `linear-gradient(to ${dir}, ${start}, ${end})`;
370
+ }
371
+ default:
372
+ throw new Error("Unknown color channel: " + channel);
373
+ }
374
+ };
375
+
376
+ // src/color-picker.connect.ts
377
+ function connect(state, send, normalize) {
378
+ const valueAsColor = state.context.valueAsColor;
379
+ const isDisabled = state.context.disabled;
380
+ const isInteractive = state.context.isInteractive;
381
+ const isDragging = state.matches("dragging");
382
+ const channels = valueAsColor.getColorChannels();
383
+ return {
384
+ /**
385
+ * Whether the color picker is being dragged
386
+ */
387
+ isDragging,
388
+ /**
389
+ * The current color value (as a string)
390
+ */
391
+ value: state.context.value,
392
+ /**
393
+ * The current color value (as a Color object)
394
+ */
395
+ valueAsColor,
396
+ /**
397
+ * The current color channels of the color
398
+ */
399
+ channels,
400
+ /**
401
+ * Function to set the color value
402
+ */
403
+ setColor(value) {
404
+ send({ type: "VALUE.SET", value: normalizeColor(value), src: "set-color" });
405
+ },
406
+ /**
407
+ * Function to set the color value of a specific channel
408
+ */
409
+ setChannelValue(channel, value) {
410
+ const color = valueAsColor.withChannelValue(channel, value);
411
+ send({ type: "VALUE.SET", value: color, src: "set-channel" });
412
+ },
413
+ /**
414
+ * Function to set the color format
415
+ */
416
+ setFormat(format) {
417
+ const value = valueAsColor.toFormat(format);
418
+ send({ type: "VALUE.SET", value, src: "set-format" });
419
+ },
420
+ contentProps: normalize.element({
421
+ ...parts.content.attrs,
422
+ id: dom.getContentId(state.context)
423
+ }),
424
+ getAreaProps(props) {
425
+ const { xChannel, yChannel } = props;
426
+ const { areaStyles } = getColorAreaGradient(state.context, xChannel, yChannel);
427
+ return normalize.element({
428
+ ...parts.area.attrs,
429
+ id: dom.getAreaId(state.context),
430
+ role: "group",
431
+ onPointerDown(event) {
432
+ if (!isInteractive)
433
+ return;
434
+ const evt = getNativeEvent(event);
435
+ if (!isLeftClick(evt) || isModifiedEvent(evt))
436
+ return;
437
+ const point = getEventPoint(evt);
438
+ const channel = { xChannel, yChannel };
439
+ send({ type: "AREA.POINTER_DOWN", point, channel, id: "area" });
440
+ },
441
+ style: {
442
+ position: "relative",
443
+ touchAction: "none",
444
+ forcedColorAdjust: "none",
445
+ ...areaStyles
446
+ }
447
+ });
448
+ },
449
+ getAreaGradientProps(props) {
450
+ const { xChannel, yChannel } = props;
451
+ const { areaGradientStyles } = getColorAreaGradient(state.context, xChannel, yChannel);
452
+ return normalize.element({
453
+ ...parts.areaGradient.attrs,
454
+ id: dom.getAreaGradientId(state.context),
455
+ style: {
456
+ position: "relative",
457
+ touchAction: "none",
458
+ forcedColorAdjust: "none",
459
+ ...areaGradientStyles
460
+ }
461
+ });
462
+ },
463
+ getAreaThumbProps(props) {
464
+ const { xChannel, yChannel } = props;
465
+ const { getThumbPosition } = getChannelDetails(valueAsColor, xChannel, yChannel);
466
+ const { x, y } = getThumbPosition();
467
+ const channel = { xChannel, yChannel };
468
+ return normalize.element({
469
+ ...parts.areaThumb.attrs,
470
+ id: dom.getAreaThumbId(state.context),
471
+ tabIndex: isDisabled ? void 0 : 0,
472
+ "data-disabled": dataAttr(isDisabled),
473
+ role: "presentation",
474
+ style: {
475
+ position: "absolute",
476
+ left: `${x * 100}%`,
477
+ top: `${y * 100}%`,
478
+ transform: "translate(-50%, -50%)",
479
+ touchAction: "none",
480
+ forcedColorAdjust: "none",
481
+ background: valueAsColor.withChannelValue("alpha", 1).toString("css")
482
+ },
483
+ onBlur() {
484
+ send("AREA.BLUR");
485
+ },
486
+ onKeyDown(event) {
487
+ if (!isInteractive)
488
+ return;
489
+ const step = getEventStep(event);
490
+ const keyMap = {
491
+ ArrowUp() {
492
+ send({ type: "AREA.ARROW_UP", channel, step });
493
+ },
494
+ ArrowDown() {
495
+ send({ type: "AREA.ARROW_DOWN", channel, step });
496
+ },
497
+ ArrowLeft() {
498
+ send({ type: "AREA.ARROW_LEFT", channel, step });
499
+ },
500
+ ArrowRight() {
501
+ send({ type: "AREA.ARROW_RIGHT", channel, step });
502
+ },
503
+ PageUp() {
504
+ send({ type: "AREA.PAGE_UP", channel, step });
505
+ },
506
+ PageDown() {
507
+ send({ type: "AREA.PAGE_DOWN", channel, step });
508
+ }
509
+ };
510
+ const exec = keyMap[getEventKey(event, state.context)];
511
+ if (exec) {
512
+ exec(event);
513
+ event.preventDefault();
514
+ }
515
+ }
516
+ });
517
+ },
518
+ getChannelSliderTrackProps(props) {
519
+ const { orientation = "horizontal", channel } = props;
520
+ return normalize.element({
521
+ ...parts.channelSliderTrack.attrs,
522
+ id: dom.getChannelSliderTrackId(state.context, channel),
523
+ role: "group",
524
+ "data-channel": channel,
525
+ "data-orientation": orientation,
526
+ onPointerDown(event) {
527
+ if (!isInteractive)
528
+ return;
529
+ const evt = getNativeEvent(event);
530
+ if (!isLeftClick(evt) || isModifiedEvent(evt))
531
+ return;
532
+ const point = getEventPoint(evt);
533
+ send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, point, id: channel, orientation });
534
+ },
535
+ style: {
536
+ position: "relative",
537
+ touchAction: "none",
538
+ forcedColorAdjust: "none",
539
+ backgroundImage: getSliderBgImage(state.context, { orientation, channel })
540
+ }
541
+ });
542
+ },
543
+ getChannelSliderBackgroundProps(props) {
544
+ const { orientation = "horizontal", channel } = props;
545
+ return normalize.element({
546
+ ...parts.channelSliderTrackBg.attrs,
547
+ "data-orientation": orientation,
548
+ "data-channel": channel,
549
+ style: {
550
+ position: "absolute",
551
+ backgroundColor: "#fff",
552
+ backgroundImage: [
553
+ "linear-gradient(-45deg,#0000 75.5%,#bcbcbc 75.5%)",
554
+ "linear-gradient(45deg,#0000 75.5%,#bcbcbc 75.5%)",
555
+ "linear-gradient(-45deg,#bcbcbc 25.5%,#0000 25.5%)",
556
+ "linear-gradient(45deg,#bcbcbc 25.5%,#0000 25.5%)"
557
+ ].join(","),
558
+ backgroundSize: "16px 16px",
559
+ backgroundPosition: "-2px -2px,-2px 6px,6px -10px,-10px -2px",
560
+ inset: 0,
561
+ zIndex: -1
562
+ }
563
+ });
564
+ },
565
+ getChannelSliderThumbProps(props) {
566
+ const { orientation = "horizontal", channel } = props;
567
+ const { minValue, maxValue, step: stepValue } = valueAsColor.getChannelRange(channel);
568
+ const channelValue = valueAsColor.getChannelValue(channel);
569
+ const offset = (channelValue - minValue) / (maxValue - minValue);
570
+ const placementStyles = orientation === "horizontal" ? { left: `${offset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
571
+ return normalize.element({
572
+ ...parts.channelSliderThumb.attrs,
573
+ id: dom.getChannelSliderThumbId(state.context, channel),
574
+ role: "slider",
575
+ "aria-label": channel,
576
+ tabIndex: isDisabled ? void 0 : 0,
577
+ "data-channel": channel,
578
+ "data-disabled": dataAttr(isDisabled),
579
+ "data-orientation": orientation,
580
+ "aria-disabled": dataAttr(isDisabled),
581
+ "aria-orientation": orientation,
582
+ "aria-valuemax": maxValue,
583
+ "aria-valuemin": minValue,
584
+ "aria-valuenow": channelValue,
585
+ style: {
586
+ forcedColorAdjust: "none",
587
+ position: "absolute",
588
+ background: getChannelDisplayColor(valueAsColor, channel).toString("css"),
589
+ ...placementStyles
590
+ },
591
+ onFocus() {
592
+ if (!isInteractive)
593
+ return;
594
+ send({ type: "CHANNEL_SLIDER.FOCUS", channel });
595
+ },
596
+ onBlur() {
597
+ if (!isInteractive)
598
+ return;
599
+ send({ type: "CHANNEL_SLIDER.BLUR", channel });
600
+ },
601
+ onKeyDown(event) {
602
+ if (!isInteractive)
603
+ return;
604
+ const step = getEventStep(event) * stepValue;
605
+ const keyMap = {
606
+ ArrowUp() {
607
+ send({ type: "CHANNEL_SLIDER.ARROW_UP", channel, step });
608
+ },
609
+ ArrowDown() {
610
+ send({ type: "CHANNEL_SLIDER.ARROW_DOWN", channel, step });
611
+ },
612
+ ArrowLeft() {
613
+ send({ type: "CHANNEL_SLIDER.ARROW_LEFT", channel, step });
614
+ },
615
+ ArrowRight() {
616
+ send({ type: "CHANNEL_SLIDER.ARROW_RIGHT", channel, step });
617
+ },
618
+ PageUp() {
619
+ send({ type: "CHANNEL_SLIDER.PAGE_UP", channel });
620
+ },
621
+ PageDown() {
622
+ send({ type: "CHANNEL_SLIDER.PAGE_DOWN", channel });
623
+ },
624
+ Home() {
625
+ send({ type: "CHANNEL_SLIDER.HOME", channel });
626
+ },
627
+ End() {
628
+ send({ type: "CHANNEL_SLIDER.END", channel });
629
+ }
630
+ };
631
+ const exec = keyMap[getEventKey(event, state.context)];
632
+ if (exec) {
633
+ exec(event);
634
+ event.preventDefault();
635
+ }
636
+ }
637
+ });
638
+ },
639
+ getChannelInputProps(props) {
640
+ const { channel } = props;
641
+ const isTextField = channel === "hex" || channel === "css";
642
+ const range = getChannelInputRange(valueAsColor, channel);
643
+ return normalize.input({
644
+ ...parts.channelInput.attrs,
645
+ type: isTextField ? "text" : "number",
646
+ "data-channel": channel,
647
+ "aria-label": channel,
648
+ disabled: isDisabled,
649
+ "data-disabled": dataAttr(isDisabled),
650
+ readOnly: state.context.readOnly,
651
+ id: dom.getChannelInputId(state.context, channel),
652
+ defaultValue: getChannelInputValue(valueAsColor, channel),
653
+ min: range?.minValue,
654
+ max: range?.maxValue,
655
+ step: range?.step,
656
+ onFocus() {
657
+ send({ type: "CHANNEL_INPUT.FOCUS", channel });
658
+ },
659
+ onChange(event) {
660
+ if (isTextField)
661
+ return;
662
+ const value = event.currentTarget.value;
663
+ send({ type: "CHANNEL_INPUT.CHANGE", channel, value, isTextField });
664
+ },
665
+ onBlur(event) {
666
+ const value = event.currentTarget.value;
667
+ send({ type: "CHANNEL_INPUT.BLUR", channel, value, isTextField });
668
+ },
669
+ onKeyDown(event) {
670
+ if (!isTextField)
671
+ return;
672
+ if (event.key === "Enter") {
673
+ const value = event.currentTarget.value;
674
+ send({ type: "CHANNEL_INPUT.CHANGE", channel, value, isTextField });
675
+ }
676
+ },
677
+ style: {
678
+ appearance: "none",
679
+ WebkitAppearance: "none",
680
+ MozAppearance: "textfield"
681
+ }
682
+ });
683
+ },
684
+ eyeDropperTriggerProps: normalize.button({
685
+ ...parts.eyeDropTrigger.attrs,
686
+ onClick() {
687
+ send("EYEDROPPER.CLICK");
688
+ }
689
+ }),
690
+ getSwatchBackgroundProps(props) {
691
+ const { value } = props;
692
+ const alpha = normalizeColor(value).getChannelValue("alpha");
693
+ return normalize.element({
694
+ ...parts.swatchBg.attrs,
695
+ "data-alpha": alpha,
696
+ style: {
697
+ width: "100%",
698
+ height: "100%",
699
+ background: "#fff",
700
+ backgroundImage: [
701
+ "linear-gradient(-45deg,#0000 75.5%,#bcbcbc 75.5%)",
702
+ "linear-gradient(45deg,#0000 75.5%,#bcbcbc 75.5%)",
703
+ "linear-gradient(-45deg,#bcbcbc 25.5%,#0000 25.5%)",
704
+ "linear-gradient(45deg,#bcbcbc 25.5%,#0000 25.5%)"
705
+ ].join(","),
706
+ backgroundPosition: "-2px -2px,-2px 6px,6px -10px,-10px -2px",
707
+ backgroundSize: "16px 16px",
708
+ position: "absolute",
709
+ inset: "0px",
710
+ zIndex: -1
711
+ }
712
+ });
713
+ },
714
+ getSwatchProps(props) {
715
+ const { value, readOnly } = props;
716
+ const color = normalizeColor(value).toFormat(valueAsColor.getColorSpace());
717
+ return normalize.element({
718
+ ...parts.swatch.attrs,
719
+ onClick() {
720
+ if (readOnly)
721
+ return;
722
+ send({ type: "VALUE.SET", value: color });
723
+ },
724
+ style: {
725
+ position: "relative",
726
+ background: color.toString("css")
727
+ }
728
+ });
729
+ }
730
+ };
731
+ }
732
+
733
+ // src/color-picker.machine.ts
734
+ import { parseColor as parseColor2 } from "@zag-js/color-utils";
735
+ import { createMachine } from "@zag-js/core";
736
+ import { trackPointerMove } from "@zag-js/dom-event";
737
+ import { raf } from "@zag-js/dom-query";
738
+ import { clampValue, getPercentValue as getPercentValue2, snapValueToStep as snapValueToStep2 } from "@zag-js/numeric-range";
739
+ import { disableTextSelection } from "@zag-js/text-selection";
740
+ import { compact } from "@zag-js/utils";
741
+ function machine(userContext) {
742
+ const ctx = compact(userContext);
743
+ return createMachine(
744
+ {
745
+ id: "color-picker",
746
+ initial: "idle",
747
+ context: {
748
+ dir: "ltr",
749
+ activeId: null,
750
+ activeChannel: null,
751
+ activeOrientation: null,
752
+ value: "#D9D9D9",
753
+ ...ctx,
754
+ valueAsColor: parseColor2(ctx.value || "#D9D9D9")
755
+ },
756
+ computed: {
757
+ isRtl: (ctx2) => ctx2.dir === "rtl",
758
+ isInteractive: (ctx2) => !(ctx2.disabled || ctx2.readOnly)
759
+ },
760
+ on: {
761
+ "VALUE.SET": {
762
+ actions: ["setValue"]
763
+ }
764
+ },
765
+ created: ["setValueAsColor"],
766
+ watch: {
767
+ value: ["setValueAsColor", "syncChannelInputs", "invokeOnChange"]
768
+ },
769
+ states: {
770
+ idle: {
771
+ on: {
772
+ "EYEDROPPER.CLICK": {
773
+ actions: ["openEyeDropper"]
774
+ },
775
+ "AREA.POINTER_DOWN": {
776
+ target: "dragging",
777
+ actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
778
+ },
779
+ "CHANNEL_SLIDER.POINTER_DOWN": {
780
+ target: "dragging",
781
+ actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
782
+ },
783
+ "CHANNEL_INPUT.FOCUS": {
784
+ target: "focused",
785
+ actions: ["setActiveChannel"]
786
+ },
787
+ "CHANNEL_INPUT.CHANGE": {
788
+ actions: ["setChannelColorFromInput"]
789
+ }
790
+ }
791
+ },
792
+ focused: {
793
+ on: {
794
+ "AREA.POINTER_DOWN": {
795
+ target: "dragging",
796
+ actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
797
+ },
798
+ "CHANNEL_SLIDER.POINTER_DOWN": {
799
+ target: "dragging",
800
+ actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
801
+ },
802
+ "AREA.ARROW_LEFT": {
803
+ actions: ["decrementXChannel"]
804
+ },
805
+ "AREA.ARROW_RIGHT": {
806
+ actions: ["incrementXChannel"]
807
+ },
808
+ "AREA.ARROW_UP": {
809
+ actions: ["incrementYChannel"]
810
+ },
811
+ "AREA.ARROW_DOWN": {
812
+ actions: ["decrementYChannel"]
813
+ },
814
+ "AREA.PAGE_UP": {
815
+ actions: ["incrementXChannel"]
816
+ },
817
+ "AREA.PAGE_DOWN": {
818
+ actions: ["decrementXChannel"]
819
+ },
820
+ "CHANNEL_SLIDER.ARROW_LEFT": {
821
+ actions: ["decrementChannel"]
822
+ },
823
+ "CHANNEL_SLIDER.ARROW_RIGHT": {
824
+ actions: ["incrementChannel"]
825
+ },
826
+ "CHANNEL_SLIDER.ARROW_UP": {
827
+ actions: ["incrementChannel"]
828
+ },
829
+ "CHANNEL_SLIDER.ARROW_DOWN": {
830
+ actions: ["decrementChannel"]
831
+ },
832
+ "CHANNEL_SLIDER.PAGE_UP": {
833
+ actions: ["incrementChannel"]
834
+ },
835
+ "CHANNEL_SLIDER.PAGE_DOWN": {
836
+ actions: ["decrementChannel"]
837
+ },
838
+ "CHANNEL_SLIDER.HOME": {
839
+ actions: ["setChannelToMin"]
840
+ },
841
+ "CHANNEL_SLIDER.END": {
842
+ actions: ["setChannelToMax"]
843
+ },
844
+ "CHANNEL_INPUT.FOCUS": {
845
+ actions: ["setActiveChannel"]
846
+ },
847
+ "CHANNEL_INPUT.CHANGE": {
848
+ actions: ["setChannelColorFromInput"]
849
+ },
850
+ "CHANNEL_INPUT.BLUR": [
851
+ {
852
+ guard: "isTextField",
853
+ target: "idle",
854
+ actions: ["setChannelColorFromInput"]
855
+ },
856
+ { target: "idle" }
857
+ ],
858
+ "CHANNEL_SLIDER.BLUR": {
859
+ target: "idle"
860
+ },
861
+ "AREA.BLUR": {
862
+ target: "idle"
863
+ }
864
+ }
865
+ },
866
+ dragging: {
867
+ exit: ["clearActiveChannel"],
868
+ activities: ["trackPointerMove", "disableTextSelection"],
869
+ on: {
870
+ "AREA.POINTER_MOVE": {
871
+ actions: ["setAreaColorFromPoint"]
872
+ },
873
+ "AREA.POINTER_UP": {
874
+ target: "focused",
875
+ actions: ["invokeOnChangeEnd"]
876
+ },
877
+ "CHANNEL_SLIDER.POINTER_MOVE": {
878
+ actions: ["setChannelColorFromPoint"]
879
+ },
880
+ "CHANNEL_SLIDER.POINTER_UP": {
881
+ target: "focused",
882
+ actions: ["invokeOnChangeEnd"]
883
+ }
884
+ }
885
+ }
886
+ }
887
+ },
888
+ {
889
+ guards: {
890
+ isTextField: (_ctx, evt) => !!evt.isTextField
891
+ },
892
+ activities: {
893
+ trackPointerMove(ctx2, _evt, { send }) {
894
+ return trackPointerMove(dom.getDoc(ctx2), {
895
+ onPointerMove({ point }) {
896
+ const type = ctx2.activeId === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
897
+ send({ type, point });
898
+ },
899
+ onPointerUp() {
900
+ const type = ctx2.activeId === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP";
901
+ send({ type });
902
+ }
903
+ });
904
+ },
905
+ disableTextSelection(ctx2) {
906
+ return disableTextSelection({ doc: dom.getDoc(ctx2), target: dom.getContentEl(ctx2) });
907
+ }
908
+ },
909
+ actions: {
910
+ openEyeDropper(ctx2) {
911
+ const isSupported = "EyeDropper" in dom.getWin(ctx2);
912
+ if (!isSupported)
913
+ return;
914
+ const win = dom.getWin(ctx2);
915
+ const picker = new win.EyeDropper();
916
+ picker.open().then(({ sRGBHex }) => {
917
+ const format = ctx2.valueAsColor.getColorSpace();
918
+ const color = parseColor2(sRGBHex).toFormat(format);
919
+ setColor(ctx2, color);
920
+ ctx2.onChangeEnd?.({ value: ctx2.value, valueAsColor: color });
921
+ }).catch(() => void 0);
922
+ },
923
+ setActiveChannel(ctx2, evt) {
924
+ ctx2.activeId = evt.id;
925
+ if (evt.channel) {
926
+ ctx2.activeChannel = evt.channel;
927
+ }
928
+ if (evt.orientation) {
929
+ ctx2.activeOrientation = evt.orientation;
930
+ }
931
+ },
932
+ clearActiveChannel(ctx2) {
933
+ ctx2.activeChannel = null;
934
+ ctx2.activeId = null;
935
+ ctx2.activeOrientation = null;
936
+ },
937
+ setAreaColorFromPoint(ctx2, evt) {
938
+ const { xChannel, yChannel } = evt.channel || ctx2.activeChannel;
939
+ const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
940
+ const { getColorFromPoint } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
941
+ const color = getColorFromPoint(percent.x, percent.y);
942
+ if (!color)
943
+ return;
944
+ setColor(ctx2, color);
945
+ },
946
+ setChannelColorFromPoint(ctx2, evt) {
947
+ const channel = evt.channel || ctx2.activeId;
948
+ const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
949
+ const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(channel);
950
+ const orientation = ctx2.activeOrientation || "horizontal";
951
+ const point = orientation === "horizontal" ? percent.x : percent.y;
952
+ const channelValue = getPercentValue2(point, minValue, maxValue, step);
953
+ const value = snapValueToStep2(channelValue - step, minValue, maxValue, step);
954
+ const newColor = ctx2.valueAsColor.withChannelValue(channel, value);
955
+ setColor(ctx2, newColor);
956
+ },
957
+ setValue(ctx2, evt) {
958
+ setColor(ctx2, evt.value);
959
+ },
960
+ setValueAsColor(ctx2) {
961
+ try {
962
+ const color = parseColor2(ctx2.value);
963
+ if (color.isEqual(ctx2.valueAsColor))
964
+ return;
965
+ ctx2.valueAsColor = color;
966
+ } catch {
967
+ }
968
+ },
969
+ syncChannelInputs(ctx2) {
970
+ const inputs = dom.getChannelInputEls(ctx2);
971
+ inputs.forEach((input) => {
972
+ const channel = input.getAttribute("data-channel");
973
+ if (!channel)
974
+ return;
975
+ const value = getChannelInputValue(ctx2.valueAsColor, channel);
976
+ input.value = value.toString();
977
+ });
978
+ },
979
+ setChannelColorFromInput(ctx2, evt) {
980
+ const { channel, isTextField, value } = evt;
981
+ try {
982
+ const format = ctx2.valueAsColor.getColorSpace();
983
+ const newColor = isTextField ? parseColor2(value).toFormat(format) : ctx2.valueAsColor.withChannelValue(channel, value);
984
+ setColor(ctx2, newColor);
985
+ } catch {
986
+ const input = dom.getChannelInputEl(ctx2, channel);
987
+ if (!input)
988
+ return;
989
+ input.value = getChannelInputValue(ctx2.valueAsColor, channel);
990
+ }
991
+ },
992
+ incrementChannel(ctx2, evt) {
993
+ const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
994
+ const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
995
+ const value = snapValueToStep2(channelValue + evt.step, minValue, maxValue, step);
996
+ const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
997
+ setColor(ctx2, newColor);
998
+ },
999
+ decrementChannel(ctx2, evt) {
1000
+ const { minValue, maxValue, step } = ctx2.valueAsColor.getChannelRange(evt.channel);
1001
+ const channelValue = ctx2.valueAsColor.getChannelValue(evt.channel);
1002
+ const value = snapValueToStep2(channelValue - evt.step, minValue, maxValue, step);
1003
+ const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, clampValue(value, minValue, maxValue));
1004
+ setColor(ctx2, newColor);
1005
+ },
1006
+ incrementXChannel(ctx2, evt) {
1007
+ const { xChannel, yChannel } = evt.channel;
1008
+ const { incrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
1009
+ const newColor = ctx2.valueAsColor.withChannelValue(xChannel, incrementX(evt.step));
1010
+ setColor(ctx2, newColor);
1011
+ },
1012
+ decrementXChannel(ctx2, evt) {
1013
+ const { xChannel, yChannel } = evt.channel;
1014
+ const { decrementX } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
1015
+ const newColor = ctx2.valueAsColor.withChannelValue(xChannel, decrementX(evt.step));
1016
+ setColor(ctx2, newColor);
1017
+ },
1018
+ incrementYChannel(ctx2, evt) {
1019
+ const { xChannel, yChannel } = evt.channel;
1020
+ const { incrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
1021
+ const newColor = ctx2.valueAsColor.withChannelValue(yChannel, incrementY(evt.step));
1022
+ setColor(ctx2, newColor);
1023
+ },
1024
+ decrementYChannel(ctx2, evt) {
1025
+ const { xChannel, yChannel } = evt.channel;
1026
+ const { decrementY } = getChannelDetails(ctx2.valueAsColor, xChannel, yChannel);
1027
+ const newColor = ctx2.valueAsColor.withChannelValue(yChannel, decrementY(evt.step));
1028
+ setColor(ctx2, newColor);
1029
+ },
1030
+ setChannelToMax(ctx2, evt) {
1031
+ const { maxValue } = ctx2.valueAsColor.getChannelRange(evt.channel);
1032
+ const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, maxValue);
1033
+ setColor(ctx2, newColor);
1034
+ },
1035
+ setChannelToMin(ctx2, evt) {
1036
+ const { minValue } = ctx2.valueAsColor.getChannelRange(evt.channel);
1037
+ const newColor = ctx2.valueAsColor.withChannelValue(evt.channel, minValue);
1038
+ setColor(ctx2, newColor);
1039
+ },
1040
+ invokeOnChangeEnd(ctx2) {
1041
+ ctx2.onChangeEnd?.({ value: ctx2.value, valueAsColor: ctx2.valueAsColor });
1042
+ },
1043
+ invokeOnChange(ctx2) {
1044
+ ctx2.onChange?.({ value: ctx2.value, valueAsColor: ctx2.valueAsColor });
1045
+ },
1046
+ focusAreaThumb(ctx2) {
1047
+ raf(() => {
1048
+ dom.getAreaThumbEl(ctx2)?.focus({ preventScroll: true });
1049
+ });
1050
+ },
1051
+ focusChannelThumb(ctx2, evt) {
1052
+ raf(() => {
1053
+ dom.getChannelSliderThumbEl(ctx2, evt.channel)?.focus({ preventScroll: true });
1054
+ });
1055
+ }
1056
+ }
1057
+ }
1058
+ );
1059
+ }
1060
+ var setColor = (ctx, color) => {
1061
+ ctx.value = color.toString("css");
1062
+ ctx.valueAsColor = color;
1063
+ };
1064
+ export {
1065
+ anatomy,
1066
+ connect,
1067
+ machine
1068
+ };
1069
+ //# sourceMappingURL=index.mjs.map