@zag-js/color-picker 1.34.1 → 1.35.1

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 (49) hide show
  1. package/dist/color-picker.anatomy.d.mts +6 -0
  2. package/dist/color-picker.anatomy.d.ts +6 -0
  3. package/dist/color-picker.anatomy.js +59 -0
  4. package/dist/color-picker.anatomy.mjs +33 -0
  5. package/dist/color-picker.connect.d.mts +10 -0
  6. package/dist/color-picker.connect.d.ts +10 -0
  7. package/dist/color-picker.connect.js +681 -0
  8. package/dist/color-picker.connect.mjs +646 -0
  9. package/dist/color-picker.dom.d.mts +39 -0
  10. package/dist/color-picker.dom.d.ts +39 -0
  11. package/dist/color-picker.dom.js +136 -0
  12. package/dist/color-picker.dom.mjs +85 -0
  13. package/dist/color-picker.machine.d.mts +10 -0
  14. package/dist/color-picker.machine.d.ts +10 -0
  15. package/dist/color-picker.machine.js +637 -0
  16. package/dist/color-picker.machine.mjs +610 -0
  17. package/dist/color-picker.parse.d.mts +5 -0
  18. package/dist/color-picker.parse.d.ts +5 -0
  19. package/dist/color-picker.parse.js +33 -0
  20. package/dist/color-picker.parse.mjs +8 -0
  21. package/dist/color-picker.props.d.mts +21 -0
  22. package/dist/color-picker.props.d.ts +21 -0
  23. package/dist/color-picker.props.js +94 -0
  24. package/dist/color-picker.props.mjs +58 -0
  25. package/dist/color-picker.types.d.mts +303 -0
  26. package/dist/color-picker.types.d.ts +303 -0
  27. package/dist/color-picker.types.js +18 -0
  28. package/dist/color-picker.types.mjs +0 -0
  29. package/dist/index.d.mts +9 -324
  30. package/dist/index.d.ts +9 -324
  31. package/dist/index.js +37 -1517
  32. package/dist/index.mjs +11 -1504
  33. package/dist/utils/get-channel-display-color.d.mts +5 -0
  34. package/dist/utils/get-channel-display-color.d.ts +5 -0
  35. package/dist/utils/get-channel-display-color.js +48 -0
  36. package/dist/utils/get-channel-display-color.mjs +23 -0
  37. package/dist/utils/get-channel-input-value.d.mts +11 -0
  38. package/dist/utils/get-channel-input-value.d.ts +11 -0
  39. package/dist/utils/get-channel-input-value.js +88 -0
  40. package/dist/utils/get-channel-input-value.mjs +62 -0
  41. package/dist/utils/get-slider-background.d.mts +14 -0
  42. package/dist/utils/get-slider-background.d.ts +14 -0
  43. package/dist/utils/get-slider-background.js +65 -0
  44. package/dist/utils/get-slider-background.mjs +40 -0
  45. package/dist/utils/is-valid-hex.d.mts +4 -0
  46. package/dist/utils/is-valid-hex.d.ts +4 -0
  47. package/dist/utils/is-valid-hex.js +40 -0
  48. package/dist/utils/is-valid-hex.mjs +14 -0
  49. package/package.json +20 -10
package/dist/index.mjs CHANGED
@@ -1,1505 +1,12 @@
1
- import { createAnatomy } from '@zag-js/anatomy';
2
- import { parseColor, getColorAreaGradient, normalizeColor } from '@zag-js/color-utils';
3
- import { raf, getInitialFocus, dispatchInputValueEvent, disableTextSelection, trackPointerMove, trackFormControl, setElementValue, getRelativePoint, queryAll, dataAttr, visuallyHiddenStyle, getEventStep, getEventKey, isLeftClick, isModifierKey, getEventPoint, query } from '@zag-js/dom-query';
4
- import { getPlacement, getPlacementStyles } from '@zag-js/popper';
5
- import { createGuards, createMachine } from '@zag-js/core';
6
- import { trackDismissableElement } from '@zag-js/dismissable';
7
- import { tryCatch, createSplitProps } from '@zag-js/utils';
8
- import { createProps } from '@zag-js/types';
9
-
10
- // src/color-picker.anatomy.ts
11
- var anatomy = createAnatomy("color-picker", [
12
- "root",
13
- "label",
14
- "control",
15
- "trigger",
16
- "positioner",
17
- "content",
18
- "area",
19
- "areaThumb",
20
- "valueText",
21
- "areaBackground",
22
- "channelSlider",
23
- "channelSliderLabel",
24
- "channelSliderTrack",
25
- "channelSliderThumb",
26
- "channelSliderValueText",
27
- "channelInput",
28
- "transparencyGrid",
29
- "swatchGroup",
30
- "swatchTrigger",
31
- "swatchIndicator",
32
- "swatch",
33
- "eyeDropperTrigger",
34
- "formatTrigger",
35
- "formatSelect"
36
- ]);
37
- var parts = anatomy.build();
38
- var getRootId = (ctx) => ctx.ids?.root ?? `color-picker:${ctx.id}`;
39
- var getLabelId = (ctx) => ctx.ids?.label ?? `color-picker:${ctx.id}:label`;
40
- var getHiddenInputId = (ctx) => ctx.ids?.hiddenInput ?? `color-picker:${ctx.id}:hidden-input`;
41
- var getControlId = (ctx) => ctx.ids?.control ?? `color-picker:${ctx.id}:control`;
42
- var getTriggerId = (ctx) => ctx.ids?.trigger ?? `color-picker:${ctx.id}:trigger`;
43
- var getContentId = (ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`;
44
- var getPositionerId = (ctx) => ctx.ids?.positioner ?? `color-picker:${ctx.id}:positioner`;
45
- var getFormatSelectId = (ctx) => ctx.ids?.formatSelect ?? `color-picker:${ctx.id}:format-select`;
46
- var getAreaId = (ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`;
47
- var getAreaGradientId = (ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`;
48
- var getAreaThumbId = (ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`;
49
- var getChannelSliderTrackId = (ctx, channel) => ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`;
50
- var getChannelSliderThumbId = (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`;
51
- var getContentEl = (ctx) => ctx.getById(getContentId(ctx));
52
- var getAreaThumbEl = (ctx) => ctx.getById(getAreaThumbId(ctx));
53
- var getChannelSliderThumbEl = (ctx, channel) => ctx.getById(getChannelSliderThumbId(ctx, channel));
54
- var getFormatSelectEl = (ctx) => ctx.getById(getFormatSelectId(ctx));
55
- var getHiddenInputEl = (ctx) => ctx.getById(getHiddenInputId(ctx));
56
- var getAreaEl = (ctx) => ctx.getById(getAreaId(ctx));
57
- var getAreaValueFromPoint = (ctx, point, dir) => {
58
- const areaEl = getAreaEl(ctx);
59
- if (!areaEl) return;
60
- const { getPercentValue } = getRelativePoint(point, areaEl);
61
- return {
62
- x: getPercentValue({ dir, orientation: "horizontal" }),
63
- y: getPercentValue({ orientation: "vertical" })
64
- };
1
+ // src/index.ts
2
+ import { anatomy } from "./color-picker.anatomy.mjs";
3
+ import { connect } from "./color-picker.connect.mjs";
4
+ import { machine } from "./color-picker.machine.mjs";
5
+ import { parse } from "./color-picker.parse.mjs";
6
+ export * from "./color-picker.props.mjs";
7
+ export {
8
+ anatomy,
9
+ connect,
10
+ machine,
11
+ parse
65
12
  };
66
- var getControlEl = (ctx) => ctx.getById(getControlId(ctx));
67
- var getTriggerEl = (ctx) => ctx.getById(getTriggerId(ctx));
68
- var getPositionerEl = (ctx) => ctx.getById(getPositionerId(ctx));
69
- var getChannelSliderTrackEl = (ctx, channel) => ctx.getById(getChannelSliderTrackId(ctx, channel));
70
- var getChannelSliderValueFromPoint = (ctx, point, channel, dir) => {
71
- const trackEl = getChannelSliderTrackEl(ctx, channel);
72
- if (!trackEl) return;
73
- const { getPercentValue } = getRelativePoint(point, trackEl);
74
- return {
75
- x: getPercentValue({ dir, orientation: "horizontal" }),
76
- y: getPercentValue({ orientation: "vertical" })
77
- };
78
- };
79
- var getChannelInputEls = (ctx) => {
80
- return [
81
- ...queryAll(getContentEl(ctx), "input[data-channel]"),
82
- ...queryAll(getControlEl(ctx), "input[data-channel]")
83
- ];
84
- };
85
- function getChannelDisplayColor(color, channel) {
86
- switch (channel) {
87
- case "hue":
88
- return parseColor(`hsl(${color.getChannelValue("hue")}, 100%, 50%)`);
89
- case "lightness":
90
- case "brightness":
91
- case "saturation":
92
- case "red":
93
- case "green":
94
- case "blue":
95
- return color.withChannelValue("alpha", 1);
96
- case "alpha": {
97
- return color;
98
- }
99
- default:
100
- throw new Error("Unknown color channel: " + channel);
101
- }
102
- }
103
- function getChannelValue(color, channel) {
104
- if (channel == null) return "";
105
- if (channel === "hex") {
106
- return color.toString("hex");
107
- }
108
- if (channel === "css") {
109
- return color.toString("css");
110
- }
111
- if (channel in color) {
112
- return color.getChannelValue(channel).toString();
113
- }
114
- const isHSL = color.getFormat() === "hsla";
115
- switch (channel) {
116
- case "hue":
117
- return isHSL ? color.toFormat("hsla").getChannelValue("hue").toString() : color.toFormat("hsba").getChannelValue("hue").toString();
118
- case "saturation":
119
- return isHSL ? color.toFormat("hsla").getChannelValue("saturation").toString() : color.toFormat("hsba").getChannelValue("saturation").toString();
120
- case "lightness":
121
- return color.toFormat("hsla").getChannelValue("lightness").toString();
122
- case "brightness":
123
- return color.toFormat("hsba").getChannelValue("brightness").toString();
124
- case "red":
125
- case "green":
126
- case "blue":
127
- return color.toFormat("rgba").getChannelValue(channel).toString();
128
- default:
129
- return color.getChannelValue(channel).toString();
130
- }
131
- }
132
- function getChannelRange(color, channel) {
133
- switch (channel) {
134
- case "hex":
135
- const minColor = parseColor("#000000");
136
- const maxColor = parseColor("#FFFFFF");
137
- return {
138
- minValue: minColor.toHexInt(),
139
- maxValue: maxColor.toHexInt(),
140
- pageSize: 10,
141
- step: 1
142
- };
143
- case "css":
144
- return void 0;
145
- case "hue":
146
- case "saturation":
147
- case "lightness":
148
- return color.toFormat("hsla").getChannelRange(channel);
149
- case "brightness":
150
- return color.toFormat("hsba").getChannelRange(channel);
151
- case "red":
152
- case "green":
153
- case "blue":
154
- return color.toFormat("rgba").getChannelRange(channel);
155
- default:
156
- return color.getChannelRange(channel);
157
- }
158
- }
159
-
160
- // src/utils/get-slider-background.ts
161
- function getSliderBackgroundDirection(orientation, dir) {
162
- if (orientation === "vertical") {
163
- return "top";
164
- } else if (dir === "ltr") {
165
- return "right";
166
- } else {
167
- return "left";
168
- }
169
- }
170
- var getSliderBackground = (props2) => {
171
- const { channel, value, dir, orientation } = props2;
172
- const bgDirection = getSliderBackgroundDirection(orientation, dir);
173
- const { minValue, maxValue } = value.getChannelRange(channel);
174
- switch (channel) {
175
- case "hue":
176
- 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%)`;
177
- case "lightness": {
178
- let start = value.withChannelValue(channel, minValue).toString("css");
179
- let middle = value.withChannelValue(channel, (maxValue - minValue) / 2).toString("css");
180
- let end = value.withChannelValue(channel, maxValue).toString("css");
181
- return `linear-gradient(to ${bgDirection}, ${start}, ${middle}, ${end})`;
182
- }
183
- case "saturation":
184
- case "brightness":
185
- case "red":
186
- case "green":
187
- case "blue":
188
- case "alpha": {
189
- let start = value.withChannelValue(channel, minValue).toString("css");
190
- let end = value.withChannelValue(channel, maxValue).toString("css");
191
- return `linear-gradient(to ${bgDirection}, ${start}, ${end})`;
192
- }
193
- default:
194
- throw new Error("Unknown color channel: " + channel);
195
- }
196
- };
197
-
198
- // src/color-picker.connect.ts
199
- function connect(service, normalize) {
200
- const { context, send, prop, computed, state, scope } = service;
201
- const value = context.get("value");
202
- const format = context.get("format");
203
- const areaValue = computed("areaValue");
204
- const valueAsString = computed("valueAsString");
205
- const disabled = computed("disabled");
206
- const readOnly = !!prop("readOnly");
207
- const invalid = !!prop("invalid");
208
- const required = !!prop("required");
209
- const interactive = computed("interactive");
210
- const dragging = state.hasTag("dragging");
211
- const open = state.hasTag("open");
212
- const focused = state.hasTag("focused");
213
- const getAreaChannels = (props2) => {
214
- const channels = areaValue.getChannels();
215
- return {
216
- xChannel: props2.xChannel ?? channels[1],
217
- yChannel: props2.yChannel ?? channels[2]
218
- };
219
- };
220
- const currentPlacement = context.get("currentPlacement");
221
- const popperStyles = getPlacementStyles({
222
- ...prop("positioning"),
223
- placement: currentPlacement
224
- });
225
- function getSwatchTriggerState(props2) {
226
- const color = normalizeColor(props2.value).toFormat(context.get("format"));
227
- return {
228
- value: color,
229
- valueAsString: color.toString("hex"),
230
- checked: color.isEqual(value),
231
- disabled: props2.disabled || !interactive
232
- };
233
- }
234
- return {
235
- dragging,
236
- open,
237
- valueAsString,
238
- value,
239
- inline: !!prop("inline"),
240
- setOpen(nextOpen) {
241
- if (prop("inline")) return;
242
- const open2 = state.hasTag("open");
243
- if (open2 === nextOpen) return;
244
- send({ type: nextOpen ? "OPEN" : "CLOSE" });
245
- },
246
- setValue(value2) {
247
- send({ type: "VALUE.SET", value: normalizeColor(value2), src: "set-color" });
248
- },
249
- getChannelValue(channel) {
250
- return getChannelValue(value, channel);
251
- },
252
- getChannelValueText(channel, locale) {
253
- return value.formatChannelValue(channel, locale);
254
- },
255
- setChannelValue(channel, channelValue) {
256
- const color = value.withChannelValue(channel, channelValue);
257
- send({ type: "VALUE.SET", value: color, src: "set-channel" });
258
- },
259
- format: context.get("format"),
260
- setFormat(format2) {
261
- const formatValue = value.toFormat(format2);
262
- send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
263
- },
264
- alpha: value.getChannelValue("alpha"),
265
- setAlpha(alphaValue) {
266
- const color = value.withChannelValue("alpha", alphaValue);
267
- send({ type: "VALUE.SET", value: color, src: "set-alpha" });
268
- },
269
- getRootProps() {
270
- return normalize.element({
271
- ...parts.root.attrs,
272
- dir: prop("dir"),
273
- id: getRootId(scope),
274
- "data-disabled": dataAttr(disabled),
275
- "data-readonly": dataAttr(readOnly),
276
- "data-invalid": dataAttr(invalid),
277
- style: {
278
- "--value": value.toString("css")
279
- }
280
- });
281
- },
282
- getLabelProps() {
283
- return normalize.element({
284
- ...parts.label.attrs,
285
- dir: prop("dir"),
286
- id: getLabelId(scope),
287
- htmlFor: getHiddenInputId(scope),
288
- "data-disabled": dataAttr(disabled),
289
- "data-readonly": dataAttr(readOnly),
290
- "data-invalid": dataAttr(invalid),
291
- "data-required": dataAttr(required),
292
- "data-focus": dataAttr(focused),
293
- onClick(event) {
294
- event.preventDefault();
295
- const inputEl = query(getControlEl(scope), "[data-channel=hex]");
296
- inputEl?.focus({ preventScroll: true });
297
- }
298
- });
299
- },
300
- getControlProps() {
301
- return normalize.element({
302
- ...parts.control.attrs,
303
- id: getControlId(scope),
304
- dir: prop("dir"),
305
- "data-disabled": dataAttr(disabled),
306
- "data-readonly": dataAttr(readOnly),
307
- "data-invalid": dataAttr(invalid),
308
- "data-state": open ? "open" : "closed",
309
- "data-focus": dataAttr(focused)
310
- });
311
- },
312
- getTriggerProps() {
313
- return normalize.button({
314
- ...parts.trigger.attrs,
315
- id: getTriggerId(scope),
316
- dir: prop("dir"),
317
- disabled,
318
- "aria-label": `select color. current color is ${valueAsString}`,
319
- "aria-controls": getContentId(scope),
320
- "aria-labelledby": getLabelId(scope),
321
- "aria-haspopup": prop("inline") ? void 0 : "dialog",
322
- "data-disabled": dataAttr(disabled),
323
- "data-readonly": dataAttr(readOnly),
324
- "data-invalid": dataAttr(invalid),
325
- "data-placement": currentPlacement,
326
- "aria-expanded": open,
327
- "data-state": open ? "open" : "closed",
328
- "data-focus": dataAttr(focused),
329
- type: "button",
330
- onClick() {
331
- if (!interactive) return;
332
- send({ type: "TRIGGER.CLICK" });
333
- },
334
- onBlur() {
335
- if (!interactive) return;
336
- send({ type: "TRIGGER.BLUR" });
337
- },
338
- style: {
339
- position: "relative"
340
- }
341
- });
342
- },
343
- getPositionerProps() {
344
- return normalize.element({
345
- ...parts.positioner.attrs,
346
- id: getPositionerId(scope),
347
- dir: prop("dir"),
348
- style: popperStyles.floating
349
- });
350
- },
351
- getContentProps() {
352
- return normalize.element({
353
- ...parts.content.attrs,
354
- id: getContentId(scope),
355
- dir: prop("dir"),
356
- role: prop("inline") ? void 0 : "dialog",
357
- tabIndex: -1,
358
- "data-placement": currentPlacement,
359
- "data-state": open ? "open" : "closed",
360
- hidden: !open
361
- });
362
- },
363
- getValueTextProps() {
364
- return normalize.element({
365
- ...parts.valueText.attrs,
366
- dir: prop("dir"),
367
- "data-disabled": dataAttr(disabled),
368
- "data-focus": dataAttr(focused)
369
- });
370
- },
371
- getAreaProps(props2 = {}) {
372
- const { xChannel, yChannel } = getAreaChannels(props2);
373
- const { areaStyles } = getColorAreaGradient(areaValue, {
374
- xChannel,
375
- yChannel,
376
- dir: prop("dir")
377
- });
378
- return normalize.element({
379
- ...parts.area.attrs,
380
- id: getAreaId(scope),
381
- role: "group",
382
- "data-invalid": dataAttr(invalid),
383
- "data-disabled": dataAttr(disabled),
384
- "data-readonly": dataAttr(readOnly),
385
- onPointerDown(event) {
386
- if (!interactive) return;
387
- if (!isLeftClick(event)) return;
388
- if (isModifierKey(event)) return;
389
- const point = getEventPoint(event);
390
- const channel = { xChannel, yChannel };
391
- send({ type: "AREA.POINTER_DOWN", point, channel, id: "area" });
392
- event.preventDefault();
393
- },
394
- style: {
395
- position: "relative",
396
- touchAction: "none",
397
- forcedColorAdjust: "none",
398
- ...areaStyles
399
- }
400
- });
401
- },
402
- getAreaBackgroundProps(props2 = {}) {
403
- const { xChannel, yChannel } = getAreaChannels(props2);
404
- const { areaGradientStyles } = getColorAreaGradient(areaValue, {
405
- xChannel,
406
- yChannel,
407
- dir: prop("dir")
408
- });
409
- return normalize.element({
410
- ...parts.areaBackground.attrs,
411
- id: getAreaGradientId(scope),
412
- "data-invalid": dataAttr(invalid),
413
- "data-disabled": dataAttr(disabled),
414
- "data-readonly": dataAttr(readOnly),
415
- style: {
416
- position: "relative",
417
- touchAction: "none",
418
- forcedColorAdjust: "none",
419
- ...areaGradientStyles
420
- }
421
- });
422
- },
423
- getAreaThumbProps(props2 = {}) {
424
- const { xChannel, yChannel } = getAreaChannels(props2);
425
- const channel = { xChannel, yChannel };
426
- const xPercent = areaValue.getChannelValuePercent(xChannel);
427
- const yPercent = 1 - areaValue.getChannelValuePercent(yChannel);
428
- const isRtl = prop("dir") === "rtl";
429
- const finalXPercent = isRtl ? 1 - xPercent : xPercent;
430
- const xValue = areaValue.getChannelValue(xChannel);
431
- const yValue = areaValue.getChannelValue(yChannel);
432
- const color = areaValue.withChannelValue("alpha", 1).toString("css");
433
- return normalize.element({
434
- ...parts.areaThumb.attrs,
435
- id: getAreaThumbId(scope),
436
- dir: prop("dir"),
437
- tabIndex: disabled ? void 0 : 0,
438
- "data-disabled": dataAttr(disabled),
439
- "data-invalid": dataAttr(invalid),
440
- "data-readonly": dataAttr(readOnly),
441
- role: "slider",
442
- "aria-valuemin": 0,
443
- "aria-valuemax": 100,
444
- "aria-valuenow": xValue,
445
- "aria-label": `${xChannel} and ${yChannel}`,
446
- "aria-roledescription": "2d slider",
447
- "aria-valuetext": `${xChannel} ${xValue}, ${yChannel} ${yValue}`,
448
- style: {
449
- position: "absolute",
450
- left: `${finalXPercent * 100}%`,
451
- top: `${yPercent * 100}%`,
452
- transform: "translate(-50%, -50%)",
453
- touchAction: "none",
454
- forcedColorAdjust: "none",
455
- "--color": color,
456
- background: color
457
- },
458
- onFocus() {
459
- if (!interactive) return;
460
- send({ type: "AREA.FOCUS", id: "area", channel });
461
- },
462
- onKeyDown(event) {
463
- if (event.defaultPrevented) return;
464
- if (!interactive) return;
465
- const step = getEventStep(event);
466
- const keyMap = {
467
- ArrowUp() {
468
- send({ type: "AREA.ARROW_UP", channel, step });
469
- },
470
- ArrowDown() {
471
- send({ type: "AREA.ARROW_DOWN", channel, step });
472
- },
473
- ArrowLeft() {
474
- send({ type: "AREA.ARROW_LEFT", channel, step });
475
- },
476
- ArrowRight() {
477
- send({ type: "AREA.ARROW_RIGHT", channel, step });
478
- },
479
- PageUp() {
480
- send({ type: "AREA.PAGE_UP", channel, step });
481
- },
482
- PageDown() {
483
- send({ type: "AREA.PAGE_DOWN", channel, step });
484
- },
485
- Escape(event2) {
486
- event2.stopPropagation();
487
- }
488
- };
489
- const exec = keyMap[getEventKey(event, {
490
- dir: prop("dir")
491
- })];
492
- if (exec) {
493
- exec(event);
494
- event.preventDefault();
495
- }
496
- }
497
- });
498
- },
499
- getTransparencyGridProps(props2 = {}) {
500
- const { size = "12px" } = props2;
501
- return normalize.element({
502
- ...parts.transparencyGrid.attrs,
503
- style: {
504
- "--size": size,
505
- width: "100%",
506
- height: "100%",
507
- position: "absolute",
508
- backgroundColor: "#fff",
509
- backgroundImage: "conic-gradient(#eeeeee 0 25%, transparent 0 50%, #eeeeee 0 75%, transparent 0)",
510
- backgroundSize: "var(--size) var(--size)",
511
- inset: "0px",
512
- zIndex: "auto",
513
- pointerEvents: "none"
514
- }
515
- });
516
- },
517
- getChannelSliderProps(props2) {
518
- const { orientation = "horizontal", channel, format: format2 } = props2;
519
- return normalize.element({
520
- ...parts.channelSlider.attrs,
521
- "data-channel": channel,
522
- "data-orientation": orientation,
523
- role: "presentation",
524
- onPointerDown(event) {
525
- if (!interactive) return;
526
- if (!isLeftClick(event)) return;
527
- if (isModifierKey(event)) return;
528
- const point = getEventPoint(event);
529
- send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, format: format2, point, id: channel, orientation });
530
- event.preventDefault();
531
- },
532
- style: {
533
- position: "relative",
534
- touchAction: "none"
535
- }
536
- });
537
- },
538
- getChannelSliderTrackProps(props2) {
539
- const { orientation = "horizontal", channel, format: format2 } = props2;
540
- const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
541
- return normalize.element({
542
- ...parts.channelSliderTrack.attrs,
543
- id: getChannelSliderTrackId(scope, channel),
544
- role: "group",
545
- "data-channel": channel,
546
- "data-orientation": orientation,
547
- style: {
548
- position: "relative",
549
- forcedColorAdjust: "none",
550
- backgroundImage: getSliderBackground({
551
- orientation,
552
- channel,
553
- dir: prop("dir"),
554
- value: normalizedValue
555
- })
556
- }
557
- });
558
- },
559
- getChannelSliderLabelProps(props2) {
560
- const { channel } = props2;
561
- return normalize.element({
562
- ...parts.channelSliderLabel.attrs,
563
- "data-channel": channel,
564
- onClick(event) {
565
- if (!interactive) return;
566
- event.preventDefault();
567
- const thumbId = getChannelSliderThumbId(scope, channel);
568
- scope.getById(thumbId)?.focus({ preventScroll: true });
569
- },
570
- style: {
571
- userSelect: "none",
572
- WebkitUserSelect: "none"
573
- }
574
- });
575
- },
576
- getChannelSliderValueTextProps(props2) {
577
- return normalize.element({
578
- ...parts.channelSliderValueText.attrs,
579
- "data-channel": props2.channel
580
- });
581
- },
582
- getChannelSliderThumbProps(props2) {
583
- const { orientation = "horizontal", channel, format: format2 } = props2;
584
- const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
585
- const channelRange = normalizedValue.getChannelRange(channel);
586
- const channelValue = normalizedValue.getChannelValue(channel);
587
- const offset = (channelValue - channelRange.minValue) / (channelRange.maxValue - channelRange.minValue);
588
- const isRtl = prop("dir") === "rtl";
589
- const finalOffset = orientation === "horizontal" && isRtl ? 1 - offset : offset;
590
- const placementStyles = orientation === "horizontal" ? { left: `${finalOffset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
591
- return normalize.element({
592
- ...parts.channelSliderThumb.attrs,
593
- id: getChannelSliderThumbId(scope, channel),
594
- role: "slider",
595
- "aria-label": channel,
596
- tabIndex: disabled ? void 0 : 0,
597
- "data-channel": channel,
598
- "data-disabled": dataAttr(disabled),
599
- "data-orientation": orientation,
600
- "aria-disabled": dataAttr(disabled),
601
- "aria-orientation": orientation,
602
- "aria-valuemax": channelRange.maxValue,
603
- "aria-valuemin": channelRange.minValue,
604
- "aria-valuenow": channelValue,
605
- "aria-valuetext": `${channel} ${channelValue}`,
606
- style: {
607
- forcedColorAdjust: "none",
608
- position: "absolute",
609
- background: getChannelDisplayColor(areaValue, channel).toString("css"),
610
- ...placementStyles
611
- },
612
- onFocus() {
613
- if (!interactive) return;
614
- send({ type: "CHANNEL_SLIDER.FOCUS", channel });
615
- },
616
- onKeyDown(event) {
617
- if (event.defaultPrevented) return;
618
- if (!interactive) return;
619
- const step = getEventStep(event) * channelRange.step;
620
- const keyMap = {
621
- ArrowUp() {
622
- send({ type: "CHANNEL_SLIDER.ARROW_UP", channel, step });
623
- },
624
- ArrowDown() {
625
- send({ type: "CHANNEL_SLIDER.ARROW_DOWN", channel, step });
626
- },
627
- ArrowLeft() {
628
- send({ type: "CHANNEL_SLIDER.ARROW_LEFT", channel, step });
629
- },
630
- ArrowRight() {
631
- send({ type: "CHANNEL_SLIDER.ARROW_RIGHT", channel, step });
632
- },
633
- PageUp() {
634
- send({ type: "CHANNEL_SLIDER.PAGE_UP", channel });
635
- },
636
- PageDown() {
637
- send({ type: "CHANNEL_SLIDER.PAGE_DOWN", channel });
638
- },
639
- Home() {
640
- send({ type: "CHANNEL_SLIDER.HOME", channel });
641
- },
642
- End() {
643
- send({ type: "CHANNEL_SLIDER.END", channel });
644
- },
645
- Escape(event2) {
646
- event2.stopPropagation();
647
- }
648
- };
649
- const exec = keyMap[getEventKey(event, {
650
- dir: prop("dir")
651
- })];
652
- if (exec) {
653
- exec(event);
654
- event.preventDefault();
655
- }
656
- }
657
- });
658
- },
659
- getChannelInputProps(props2) {
660
- const { channel } = props2;
661
- const isTextField = channel === "hex" || channel === "css";
662
- const channelRange = getChannelRange(value, channel);
663
- return normalize.input({
664
- ...parts.channelInput.attrs,
665
- dir: prop("dir"),
666
- type: isTextField ? "text" : "number",
667
- "data-channel": channel,
668
- "aria-label": channel,
669
- spellCheck: false,
670
- autoComplete: "off",
671
- disabled,
672
- "data-disabled": dataAttr(disabled),
673
- "data-invalid": dataAttr(invalid),
674
- "data-readonly": dataAttr(readOnly),
675
- readOnly,
676
- defaultValue: getChannelValue(value, channel),
677
- min: channelRange?.minValue,
678
- max: channelRange?.maxValue,
679
- step: channelRange?.step,
680
- onBeforeInput(event) {
681
- if (isTextField || !interactive) return;
682
- const value2 = event.currentTarget.value;
683
- if (value2.match(/[^0-9.]/g)) {
684
- event.preventDefault();
685
- }
686
- },
687
- onFocus(event) {
688
- if (!interactive) return;
689
- send({ type: "CHANNEL_INPUT.FOCUS", channel });
690
- event.currentTarget.select();
691
- },
692
- onBlur(event) {
693
- if (!interactive) return;
694
- const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
695
- send({ type: "CHANNEL_INPUT.BLUR", channel, value: value2, isTextField });
696
- },
697
- onKeyDown(event) {
698
- if (event.defaultPrevented) return;
699
- if (!interactive) return;
700
- if (event.key === "Enter") {
701
- const value2 = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber;
702
- send({ type: "CHANNEL_INPUT.CHANGE", channel, value: value2, isTextField });
703
- event.preventDefault();
704
- }
705
- },
706
- style: {
707
- appearance: "none",
708
- WebkitAppearance: "none",
709
- MozAppearance: "textfield"
710
- }
711
- });
712
- },
713
- getHiddenInputProps() {
714
- return normalize.input({
715
- type: "text",
716
- disabled,
717
- name: prop("name"),
718
- tabIndex: -1,
719
- readOnly,
720
- required,
721
- id: getHiddenInputId(scope),
722
- style: visuallyHiddenStyle,
723
- defaultValue: valueAsString
724
- });
725
- },
726
- getEyeDropperTriggerProps() {
727
- return normalize.button({
728
- ...parts.eyeDropperTrigger.attrs,
729
- type: "button",
730
- dir: prop("dir"),
731
- disabled,
732
- "data-disabled": dataAttr(disabled),
733
- "data-invalid": dataAttr(invalid),
734
- "data-readonly": dataAttr(readOnly),
735
- "aria-label": "Pick a color from the screen",
736
- onClick() {
737
- if (!interactive) return;
738
- send({ type: "EYEDROPPER.CLICK" });
739
- }
740
- });
741
- },
742
- getSwatchGroupProps() {
743
- return normalize.element({
744
- ...parts.swatchGroup.attrs,
745
- role: "group"
746
- });
747
- },
748
- getSwatchTriggerState,
749
- getSwatchTriggerProps(props2) {
750
- const swatchState = getSwatchTriggerState(props2);
751
- return normalize.button({
752
- ...parts.swatchTrigger.attrs,
753
- disabled: swatchState.disabled,
754
- dir: prop("dir"),
755
- type: "button",
756
- "aria-label": `select ${swatchState.valueAsString} as the color`,
757
- "data-state": swatchState.checked ? "checked" : "unchecked",
758
- "data-value": swatchState.valueAsString,
759
- "data-disabled": dataAttr(swatchState.disabled),
760
- onClick() {
761
- if (swatchState.disabled) return;
762
- send({ type: "SWATCH_TRIGGER.CLICK", value: swatchState.value });
763
- },
764
- style: {
765
- "--color": swatchState.valueAsString,
766
- position: "relative"
767
- }
768
- });
769
- },
770
- getSwatchIndicatorProps(props2) {
771
- const swatchState = getSwatchTriggerState(props2);
772
- return normalize.element({
773
- ...parts.swatchIndicator.attrs,
774
- dir: prop("dir"),
775
- hidden: !swatchState.checked
776
- });
777
- },
778
- getSwatchProps(props2) {
779
- const { respectAlpha = true } = props2;
780
- const swatchState = getSwatchTriggerState(props2);
781
- const color = swatchState.value.toString(respectAlpha ? "css" : "hex");
782
- return normalize.element({
783
- ...parts.swatch.attrs,
784
- dir: prop("dir"),
785
- "data-state": swatchState.checked ? "checked" : "unchecked",
786
- "data-value": swatchState.valueAsString,
787
- style: {
788
- "--color": color,
789
- position: "relative",
790
- background: color
791
- }
792
- });
793
- },
794
- getFormatTriggerProps() {
795
- return normalize.button({
796
- ...parts.formatTrigger.attrs,
797
- dir: prop("dir"),
798
- type: "button",
799
- "aria-label": `change color format to ${getNextFormat(format)}`,
800
- onClick(event) {
801
- if (event.currentTarget.disabled) return;
802
- const nextFormat = getNextFormat(format);
803
- send({ type: "FORMAT.SET", format: nextFormat, src: "format-trigger" });
804
- }
805
- });
806
- },
807
- getFormatSelectProps() {
808
- return normalize.select({
809
- ...parts.formatSelect.attrs,
810
- "aria-label": "change color format",
811
- dir: prop("dir"),
812
- defaultValue: prop("format"),
813
- disabled,
814
- onChange(event) {
815
- const format2 = assertFormat(event.currentTarget.value);
816
- send({ type: "FORMAT.SET", format: format2, src: "format-select" });
817
- }
818
- });
819
- }
820
- };
821
- }
822
- var formats = ["hsba", "hsla", "rgba"];
823
- var formatRegex = new RegExp(`^(${formats.join("|")})$`);
824
- function getNextFormat(format) {
825
- const index = formats.indexOf(format);
826
- return formats[index + 1] ?? formats[0];
827
- }
828
- function assertFormat(format) {
829
- if (formatRegex.test(format)) return format;
830
- throw new Error(`Unsupported color format: ${format}`);
831
- }
832
- var parse = (colorString) => {
833
- return parseColor(colorString);
834
- };
835
-
836
- // src/utils/is-valid-hex.ts
837
- var HEX_REGEX = /^[0-9a-fA-F]{3,8}$/;
838
- function isValidHex(value) {
839
- return HEX_REGEX.test(value);
840
- }
841
- function prefixHex(value) {
842
- if (value.startsWith("#")) return value;
843
- if (isValidHex(value)) return `#${value}`;
844
- return value;
845
- }
846
-
847
- // src/color-picker.machine.ts
848
- var { and } = createGuards();
849
- var hashObject = (obj) => {
850
- let hash = "";
851
- for (const key in obj) hash += `${key}:${obj[key] ?? ""};`;
852
- return hash;
853
- };
854
- var DEFAULT_COLOR = parse("#000000");
855
- var machine = createMachine({
856
- props({ props: props2 }) {
857
- const color = props2.value ?? props2.defaultValue ?? DEFAULT_COLOR;
858
- return {
859
- dir: "ltr",
860
- defaultValue: DEFAULT_COLOR,
861
- defaultFormat: color.getFormat(),
862
- openAutoFocus: true,
863
- ...props2,
864
- positioning: {
865
- placement: "bottom",
866
- ...props2.positioning
867
- }
868
- };
869
- },
870
- initialState({ prop }) {
871
- const open = prop("open") || prop("defaultOpen") || prop("inline");
872
- return open ? "open" : "idle";
873
- },
874
- context({ prop, bindable, getContext }) {
875
- return {
876
- value: bindable(() => ({
877
- defaultValue: prop("defaultValue"),
878
- value: prop("value"),
879
- isEqual(a, b) {
880
- return b != null && a.isEqual(b);
881
- },
882
- hash(a) {
883
- return hashObject(a.toJSON());
884
- },
885
- onChange(value) {
886
- const ctx = getContext();
887
- const format = ctx.get("format");
888
- prop("onValueChange")?.({ value, valueAsString: value.toString(format) });
889
- }
890
- })),
891
- format: bindable(() => ({
892
- defaultValue: prop("defaultFormat"),
893
- value: prop("format"),
894
- onChange(format) {
895
- prop("onFormatChange")?.({ format });
896
- }
897
- })),
898
- activeId: bindable(() => ({ defaultValue: null })),
899
- activeChannel: bindable(() => ({ defaultValue: null })),
900
- activeOrientation: bindable(() => ({ defaultValue: null })),
901
- fieldsetDisabled: bindable(() => ({ defaultValue: false })),
902
- restoreFocus: bindable(() => ({ defaultValue: true })),
903
- currentPlacement: bindable(() => ({
904
- defaultValue: void 0
905
- }))
906
- };
907
- },
908
- computed: {
909
- rtl: ({ prop }) => prop("dir") === "rtl",
910
- disabled: ({ prop, context }) => !!prop("disabled") || context.get("fieldsetDisabled"),
911
- interactive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
912
- valueAsString: ({ context }) => context.get("value").toString(context.get("format")),
913
- areaValue: ({ context }) => {
914
- const format = context.get("format").startsWith("hsl") ? "hsla" : "hsba";
915
- return context.get("value").toFormat(format);
916
- }
917
- },
918
- effects: ["trackFormControl"],
919
- watch({ prop, context, action, track }) {
920
- track([() => context.hash("value")], () => {
921
- action(["syncInputElements", "dispatchChangeEvent"]);
922
- });
923
- track([() => context.get("format")], () => {
924
- action(["syncFormatSelectElement", "syncValueWithFormat"]);
925
- });
926
- track([() => prop("open")], () => {
927
- action(["toggleVisibility"]);
928
- });
929
- },
930
- on: {
931
- "VALUE.SET": {
932
- actions: ["setValue"]
933
- },
934
- "FORMAT.SET": {
935
- actions: ["setFormat"]
936
- },
937
- "CHANNEL_INPUT.CHANGE": {
938
- actions: ["setChannelColorFromInput"]
939
- },
940
- "EYEDROPPER.CLICK": {
941
- actions: ["openEyeDropper"]
942
- },
943
- "SWATCH_TRIGGER.CLICK": {
944
- actions: ["setValue"]
945
- }
946
- },
947
- states: {
948
- idle: {
949
- tags: ["closed"],
950
- on: {
951
- "CONTROLLED.OPEN": {
952
- target: "open",
953
- actions: ["setInitialFocus"]
954
- },
955
- OPEN: [
956
- {
957
- guard: "isOpenControlled",
958
- actions: ["invokeOnOpen"]
959
- },
960
- {
961
- target: "open",
962
- actions: ["invokeOnOpen", "setInitialFocus"]
963
- }
964
- ],
965
- "TRIGGER.CLICK": [
966
- {
967
- guard: "isOpenControlled",
968
- actions: ["invokeOnOpen"]
969
- },
970
- {
971
- target: "open",
972
- actions: ["invokeOnOpen", "setInitialFocus"]
973
- }
974
- ],
975
- "CHANNEL_INPUT.FOCUS": {
976
- target: "focused",
977
- actions: ["setActiveChannel"]
978
- }
979
- }
980
- },
981
- focused: {
982
- tags: ["closed", "focused"],
983
- on: {
984
- "CONTROLLED.OPEN": {
985
- target: "open",
986
- actions: ["setInitialFocus"]
987
- },
988
- OPEN: [
989
- {
990
- guard: "isOpenControlled",
991
- actions: ["invokeOnOpen"]
992
- },
993
- {
994
- target: "open",
995
- actions: ["invokeOnOpen", "setInitialFocus"]
996
- }
997
- ],
998
- "TRIGGER.CLICK": [
999
- {
1000
- guard: "isOpenControlled",
1001
- actions: ["invokeOnOpen"]
1002
- },
1003
- {
1004
- target: "open",
1005
- actions: ["invokeOnOpen", "setInitialFocus"]
1006
- }
1007
- ],
1008
- "CHANNEL_INPUT.FOCUS": {
1009
- actions: ["setActiveChannel"]
1010
- },
1011
- "CHANNEL_INPUT.BLUR": {
1012
- target: "idle",
1013
- actions: ["setChannelColorFromInput"]
1014
- },
1015
- "TRIGGER.BLUR": {
1016
- target: "idle"
1017
- }
1018
- }
1019
- },
1020
- open: {
1021
- tags: ["open"],
1022
- effects: ["trackPositioning", "trackDismissableElement"],
1023
- on: {
1024
- "CONTROLLED.CLOSE": [
1025
- {
1026
- guard: "shouldRestoreFocus",
1027
- target: "focused",
1028
- actions: ["setReturnFocus"]
1029
- },
1030
- {
1031
- target: "idle"
1032
- }
1033
- ],
1034
- "TRIGGER.CLICK": [
1035
- {
1036
- guard: "isOpenControlled",
1037
- actions: ["invokeOnClose"]
1038
- },
1039
- {
1040
- target: "idle",
1041
- actions: ["invokeOnClose"]
1042
- }
1043
- ],
1044
- "AREA.POINTER_DOWN": {
1045
- target: "open:dragging",
1046
- actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
1047
- },
1048
- "AREA.FOCUS": {
1049
- actions: ["setActiveChannel"]
1050
- },
1051
- "CHANNEL_SLIDER.POINTER_DOWN": {
1052
- target: "open:dragging",
1053
- actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
1054
- },
1055
- "CHANNEL_SLIDER.FOCUS": {
1056
- actions: ["setActiveChannel"]
1057
- },
1058
- "AREA.ARROW_LEFT": {
1059
- actions: ["decrementAreaXChannel"]
1060
- },
1061
- "AREA.ARROW_RIGHT": {
1062
- actions: ["incrementAreaXChannel"]
1063
- },
1064
- "AREA.ARROW_UP": {
1065
- actions: ["incrementAreaYChannel"]
1066
- },
1067
- "AREA.ARROW_DOWN": {
1068
- actions: ["decrementAreaYChannel"]
1069
- },
1070
- "AREA.PAGE_UP": {
1071
- actions: ["incrementAreaXChannel"]
1072
- },
1073
- "AREA.PAGE_DOWN": {
1074
- actions: ["decrementAreaXChannel"]
1075
- },
1076
- "CHANNEL_SLIDER.ARROW_LEFT": {
1077
- actions: ["decrementChannel"]
1078
- },
1079
- "CHANNEL_SLIDER.ARROW_RIGHT": {
1080
- actions: ["incrementChannel"]
1081
- },
1082
- "CHANNEL_SLIDER.ARROW_UP": {
1083
- actions: ["incrementChannel"]
1084
- },
1085
- "CHANNEL_SLIDER.ARROW_DOWN": {
1086
- actions: ["decrementChannel"]
1087
- },
1088
- "CHANNEL_SLIDER.PAGE_UP": {
1089
- actions: ["incrementChannel"]
1090
- },
1091
- "CHANNEL_SLIDER.PAGE_DOWN": {
1092
- actions: ["decrementChannel"]
1093
- },
1094
- "CHANNEL_SLIDER.HOME": {
1095
- actions: ["setChannelToMin"]
1096
- },
1097
- "CHANNEL_SLIDER.END": {
1098
- actions: ["setChannelToMax"]
1099
- },
1100
- "CHANNEL_INPUT.BLUR": {
1101
- actions: ["setChannelColorFromInput"]
1102
- },
1103
- INTERACT_OUTSIDE: [
1104
- {
1105
- guard: "isOpenControlled",
1106
- actions: ["invokeOnClose"]
1107
- },
1108
- {
1109
- guard: "shouldRestoreFocus",
1110
- target: "focused",
1111
- actions: ["invokeOnClose", "setReturnFocus"]
1112
- },
1113
- {
1114
- target: "idle",
1115
- actions: ["invokeOnClose"]
1116
- }
1117
- ],
1118
- CLOSE: [
1119
- {
1120
- guard: "isOpenControlled",
1121
- actions: ["invokeOnClose"]
1122
- },
1123
- {
1124
- target: "idle",
1125
- actions: ["invokeOnClose"]
1126
- }
1127
- ],
1128
- "SWATCH_TRIGGER.CLICK": [
1129
- {
1130
- guard: and("isOpenControlled", "closeOnSelect"),
1131
- actions: ["setValue", "invokeOnClose"]
1132
- },
1133
- {
1134
- guard: "closeOnSelect",
1135
- target: "focused",
1136
- actions: ["setValue", "invokeOnClose", "setReturnFocus"]
1137
- },
1138
- {
1139
- actions: ["setValue"]
1140
- }
1141
- ]
1142
- }
1143
- },
1144
- "open:dragging": {
1145
- tags: ["open"],
1146
- exit: ["clearActiveChannel"],
1147
- effects: ["trackPointerMove", "disableTextSelection", "trackPositioning", "trackDismissableElement"],
1148
- on: {
1149
- "CONTROLLED.CLOSE": [
1150
- {
1151
- guard: "shouldRestoreFocus",
1152
- target: "focused",
1153
- actions: ["setReturnFocus"]
1154
- },
1155
- {
1156
- target: "idle"
1157
- }
1158
- ],
1159
- "AREA.POINTER_MOVE": {
1160
- actions: ["setAreaColorFromPoint", "focusAreaThumb"]
1161
- },
1162
- "AREA.POINTER_UP": {
1163
- target: "open",
1164
- actions: ["invokeOnChangeEnd"]
1165
- },
1166
- "CHANNEL_SLIDER.POINTER_MOVE": {
1167
- actions: ["setChannelColorFromPoint", "focusChannelThumb"]
1168
- },
1169
- "CHANNEL_SLIDER.POINTER_UP": {
1170
- target: "open",
1171
- actions: ["invokeOnChangeEnd"]
1172
- },
1173
- INTERACT_OUTSIDE: [
1174
- {
1175
- guard: "isOpenControlled",
1176
- actions: ["invokeOnClose"]
1177
- },
1178
- {
1179
- guard: "shouldRestoreFocus",
1180
- target: "focused",
1181
- actions: ["invokeOnClose", "setReturnFocus"]
1182
- },
1183
- {
1184
- target: "idle",
1185
- actions: ["invokeOnClose"]
1186
- }
1187
- ],
1188
- CLOSE: [
1189
- {
1190
- guard: "isOpenControlled",
1191
- actions: ["invokeOnClose"]
1192
- },
1193
- {
1194
- target: "idle",
1195
- actions: ["invokeOnClose"]
1196
- }
1197
- ]
1198
- }
1199
- }
1200
- },
1201
- implementations: {
1202
- guards: {
1203
- closeOnSelect: ({ prop }) => !!prop("closeOnSelect"),
1204
- isOpenControlled: ({ prop }) => prop("open") != null || !!prop("inline"),
1205
- shouldRestoreFocus: ({ context }) => !!context.get("restoreFocus")
1206
- },
1207
- effects: {
1208
- trackPositioning({ context, prop, scope }) {
1209
- if (prop("inline")) return;
1210
- if (!context.get("currentPlacement")) {
1211
- context.set("currentPlacement", prop("positioning")?.placement);
1212
- }
1213
- const anchorEl = getTriggerEl(scope);
1214
- const getPositionerEl2 = () => getPositionerEl(scope);
1215
- return getPlacement(anchorEl, getPositionerEl2, {
1216
- ...prop("positioning"),
1217
- defer: true,
1218
- onComplete(data) {
1219
- context.set("currentPlacement", data.placement);
1220
- }
1221
- });
1222
- },
1223
- trackDismissableElement({ context, scope, prop, send }) {
1224
- if (prop("inline")) return;
1225
- const getContentEl2 = () => getContentEl(scope);
1226
- return trackDismissableElement(getContentEl2, {
1227
- type: "popover",
1228
- exclude: getTriggerEl(scope),
1229
- defer: true,
1230
- onInteractOutside(event) {
1231
- prop("onInteractOutside")?.(event);
1232
- if (event.defaultPrevented) return;
1233
- context.set("restoreFocus", !(event.detail.focusable || event.detail.contextmenu));
1234
- },
1235
- onPointerDownOutside: prop("onPointerDownOutside"),
1236
- onFocusOutside: prop("onFocusOutside"),
1237
- onDismiss() {
1238
- send({ type: "INTERACT_OUTSIDE" });
1239
- }
1240
- });
1241
- },
1242
- trackFormControl({ context, scope, send }) {
1243
- const inputEl = getHiddenInputEl(scope);
1244
- return trackFormControl(inputEl, {
1245
- onFieldsetDisabledChange(disabled) {
1246
- context.set("fieldsetDisabled", disabled);
1247
- },
1248
- onFormReset() {
1249
- send({ type: "VALUE.SET", value: context.initial("value"), src: "form.reset" });
1250
- }
1251
- });
1252
- },
1253
- trackPointerMove({ context, scope, event, send }) {
1254
- return trackPointerMove(scope.getDoc(), {
1255
- onPointerMove({ point }) {
1256
- const type = context.get("activeId") === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
1257
- send({ type, point, format: event.format });
1258
- },
1259
- onPointerUp() {
1260
- const type = context.get("activeId") === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP";
1261
- send({ type });
1262
- }
1263
- });
1264
- },
1265
- disableTextSelection({ scope }) {
1266
- return disableTextSelection({
1267
- doc: scope.getDoc(),
1268
- target: getContentEl(scope)
1269
- });
1270
- }
1271
- },
1272
- actions: {
1273
- openEyeDropper({ scope, context }) {
1274
- const win = scope.getWin();
1275
- const isSupported = "EyeDropper" in win;
1276
- if (!isSupported) return;
1277
- const picker = new win.EyeDropper();
1278
- picker.open().then(({ sRGBHex }) => {
1279
- const format = context.get("value").getFormat();
1280
- const color = parseColor(sRGBHex).toFormat(format);
1281
- context.set("value", color);
1282
- }).catch(() => void 0);
1283
- },
1284
- setActiveChannel({ context, event }) {
1285
- context.set("activeId", event.id);
1286
- if (event.channel) context.set("activeChannel", event.channel);
1287
- if (event.orientation) context.set("activeOrientation", event.orientation);
1288
- },
1289
- clearActiveChannel({ context }) {
1290
- context.set("activeChannel", null);
1291
- context.set("activeId", null);
1292
- context.set("activeOrientation", null);
1293
- },
1294
- setAreaColorFromPoint({ context, event, computed, scope, prop }) {
1295
- const v = event.format ? context.get("value").toFormat(event.format) : computed("areaValue");
1296
- const { xChannel, yChannel } = event.channel || context.get("activeChannel");
1297
- const percent = getAreaValueFromPoint(scope, event.point, prop("dir"));
1298
- if (!percent) return;
1299
- const xValue = v.getChannelPercentValue(xChannel, percent.x);
1300
- const yValue = v.getChannelPercentValue(yChannel, 1 - percent.y);
1301
- const color = v.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
1302
- context.set("value", color);
1303
- },
1304
- setChannelColorFromPoint({ context, event, computed, scope, prop }) {
1305
- const channel = event.channel || context.get("activeId");
1306
- const normalizedValue = event.format ? context.get("value").toFormat(event.format) : computed("areaValue");
1307
- const percent = getChannelSliderValueFromPoint(scope, event.point, channel, prop("dir"));
1308
- if (!percent) return;
1309
- const orientation = context.get("activeOrientation") || "horizontal";
1310
- const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
1311
- const value = normalizedValue.getChannelPercentValue(channel, channelPercent);
1312
- const color = normalizedValue.withChannelValue(channel, value);
1313
- context.set("value", color);
1314
- },
1315
- setValue({ context, event }) {
1316
- context.set("value", event.value);
1317
- },
1318
- setFormat({ context, event }) {
1319
- context.set("format", event.format);
1320
- },
1321
- dispatchChangeEvent({ scope, computed }) {
1322
- dispatchInputValueEvent(getHiddenInputEl(scope), { value: computed("valueAsString") });
1323
- },
1324
- syncInputElements({ context, scope }) {
1325
- syncChannelInputs(scope, context.get("value"));
1326
- },
1327
- invokeOnChangeEnd({ context, prop, computed }) {
1328
- prop("onValueChangeEnd")?.({
1329
- value: context.get("value"),
1330
- valueAsString: computed("valueAsString")
1331
- });
1332
- },
1333
- setChannelColorFromInput({ context, event, scope, prop }) {
1334
- const { channel, isTextField, value } = event;
1335
- const currentAlpha = context.get("value").getChannelValue("alpha");
1336
- let color;
1337
- if (channel === "alpha") {
1338
- let valueAsNumber = parseFloat(value);
1339
- valueAsNumber = Number.isNaN(valueAsNumber) ? currentAlpha : valueAsNumber;
1340
- color = context.get("value").withChannelValue("alpha", valueAsNumber);
1341
- } else if (isTextField) {
1342
- color = tryCatch(
1343
- () => {
1344
- const parseValue = channel === "hex" ? prefixHex(value) : value;
1345
- return parse(parseValue).withChannelValue("alpha", currentAlpha);
1346
- },
1347
- () => context.get("value")
1348
- );
1349
- } else {
1350
- const current = context.get("value").toFormat(context.get("format"));
1351
- const valueAsNumber = Number.isNaN(value) ? current.getChannelValue(channel) : value;
1352
- color = current.withChannelValue(channel, valueAsNumber);
1353
- }
1354
- syncChannelInputs(scope, context.get("value"), color);
1355
- context.set("value", color);
1356
- prop("onValueChangeEnd")?.({
1357
- value: color,
1358
- valueAsString: color.toString(context.get("format"))
1359
- });
1360
- },
1361
- incrementChannel({ context, event }) {
1362
- const color = context.get("value").incrementChannel(event.channel, event.step);
1363
- context.set("value", color);
1364
- },
1365
- decrementChannel({ context, event }) {
1366
- const color = context.get("value").decrementChannel(event.channel, event.step);
1367
- context.set("value", color);
1368
- },
1369
- incrementAreaXChannel({ context, event, computed }) {
1370
- const { xChannel } = event.channel;
1371
- const color = computed("areaValue").incrementChannel(xChannel, event.step);
1372
- context.set("value", color);
1373
- },
1374
- decrementAreaXChannel({ context, event, computed }) {
1375
- const { xChannel } = event.channel;
1376
- const color = computed("areaValue").decrementChannel(xChannel, event.step);
1377
- context.set("value", color);
1378
- },
1379
- incrementAreaYChannel({ context, event, computed }) {
1380
- const { yChannel } = event.channel;
1381
- const color = computed("areaValue").incrementChannel(yChannel, event.step);
1382
- context.set("value", color);
1383
- },
1384
- decrementAreaYChannel({ context, event, computed }) {
1385
- const { yChannel } = event.channel;
1386
- const color = computed("areaValue").decrementChannel(yChannel, event.step);
1387
- context.set("value", color);
1388
- },
1389
- setChannelToMax({ context, event }) {
1390
- const value = context.get("value");
1391
- const range = value.getChannelRange(event.channel);
1392
- const color = value.withChannelValue(event.channel, range.maxValue);
1393
- context.set("value", color);
1394
- },
1395
- setChannelToMin({ context, event }) {
1396
- const value = context.get("value");
1397
- const range = value.getChannelRange(event.channel);
1398
- const color = value.withChannelValue(event.channel, range.minValue);
1399
- context.set("value", color);
1400
- },
1401
- focusAreaThumb({ scope }) {
1402
- raf(() => {
1403
- getAreaThumbEl(scope)?.focus({ preventScroll: true });
1404
- });
1405
- },
1406
- focusChannelThumb({ event, scope }) {
1407
- raf(() => {
1408
- getChannelSliderThumbEl(scope, event.channel)?.focus({ preventScroll: true });
1409
- });
1410
- },
1411
- setInitialFocus({ prop, scope }) {
1412
- if (!prop("openAutoFocus")) return;
1413
- raf(() => {
1414
- const element = getInitialFocus({
1415
- root: getContentEl(scope),
1416
- getInitialEl: prop("initialFocusEl")
1417
- });
1418
- element?.focus({ preventScroll: true });
1419
- });
1420
- },
1421
- setReturnFocus({ scope }) {
1422
- raf(() => {
1423
- getTriggerEl(scope)?.focus({ preventScroll: true });
1424
- });
1425
- },
1426
- syncFormatSelectElement({ context, scope }) {
1427
- syncFormatSelect(scope, context.get("format"));
1428
- },
1429
- syncValueWithFormat({ context }) {
1430
- const value = context.get("value");
1431
- const newValue = value.toFormat(context.get("format"));
1432
- if (newValue.isEqual(value)) return;
1433
- context.set("value", newValue);
1434
- },
1435
- invokeOnOpen({ prop, context }) {
1436
- if (prop("inline")) return;
1437
- prop("onOpenChange")?.({ open: true, value: context.get("value") });
1438
- },
1439
- invokeOnClose({ prop, context }) {
1440
- if (prop("inline")) return;
1441
- prop("onOpenChange")?.({ open: false, value: context.get("value") });
1442
- },
1443
- toggleVisibility({ prop, event, send }) {
1444
- send({ type: prop("open") ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: event });
1445
- }
1446
- }
1447
- }
1448
- });
1449
- function syncChannelInputs(scope, currentValue, nextValue) {
1450
- const channelInputEls = getChannelInputEls(scope);
1451
- raf(() => {
1452
- channelInputEls.forEach((inputEl) => {
1453
- const channel = inputEl.dataset.channel;
1454
- setElementValue(inputEl, getChannelValue(nextValue || currentValue, channel));
1455
- });
1456
- });
1457
- }
1458
- function syncFormatSelect(scope, format) {
1459
- const selectEl = getFormatSelectEl(scope);
1460
- if (!selectEl) return;
1461
- raf(() => setElementValue(selectEl, format));
1462
- }
1463
- var props = createProps()([
1464
- "closeOnSelect",
1465
- "dir",
1466
- "disabled",
1467
- "format",
1468
- "defaultFormat",
1469
- "getRootNode",
1470
- "id",
1471
- "ids",
1472
- "initialFocusEl",
1473
- "inline",
1474
- "name",
1475
- "positioning",
1476
- "onFocusOutside",
1477
- "onFormatChange",
1478
- "onInteractOutside",
1479
- "onOpenChange",
1480
- "onPointerDownOutside",
1481
- "onValueChange",
1482
- "onValueChangeEnd",
1483
- "defaultOpen",
1484
- "open",
1485
- "positioning",
1486
- "required",
1487
- "readOnly",
1488
- "value",
1489
- "defaultValue",
1490
- "invalid",
1491
- "openAutoFocus"
1492
- ]);
1493
- var splitProps = createSplitProps(props);
1494
- var areaProps = createProps()(["xChannel", "yChannel"]);
1495
- var splitAreaProps = createSplitProps(areaProps);
1496
- var channelProps = createProps()(["channel", "orientation"]);
1497
- var splitChannelProps = createSplitProps(channelProps);
1498
- var swatchTriggerProps = createProps()(["value", "disabled"]);
1499
- var splitSwatchTriggerProps = createSplitProps(swatchTriggerProps);
1500
- var swatchProps = createProps()(["value", "respectAlpha"]);
1501
- var splitSwatchProps = createSplitProps(swatchProps);
1502
- var transparencyGridProps = createProps()(["size"]);
1503
- var splitTransparencyGridProps = createSplitProps(transparencyGridProps);
1504
-
1505
- export { anatomy, areaProps, channelProps, connect, machine, parse, props, splitAreaProps, splitChannelProps, splitProps, splitSwatchProps, splitSwatchTriggerProps, splitTransparencyGridProps, swatchProps, swatchTriggerProps, transparencyGridProps };