@zag-js/color-picker 0.82.2 → 1.0.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.
package/dist/index.mjs CHANGED
@@ -1,10 +1,11 @@
1
1
  import { createAnatomy } from '@zag-js/anatomy';
2
- import { normalizeColor, getColorAreaGradient, parseColor } from '@zag-js/color-utils';
3
- import { createScope, queryAll, getRelativePoint, dataAttr, query, isLeftClick, isModifierKey, getEventPoint, getEventStep, getEventKey, visuallyHiddenStyle, trackFormControl, trackPointerMove, disableTextSelection, raf, getInitialFocus, dispatchInputValueEvent } from '@zag-js/dom-query';
4
- import { getPlacementStyles, getPlacement } from '@zag-js/popper';
5
- import { createMachine, guards } from '@zag-js/core';
2
+ import { parseColor, normalizeColor, getColorAreaGradient } from '@zag-js/color-utils';
3
+ import { dispatchInputValueEvent, trackFormControl, trackPointerMove, disableTextSelection, raf, getInitialFocus, setElementValue, getRelativePoint, queryAll, dataAttr, query, isLeftClick, isModifierKey, getEventPoint, getEventStep, getEventKey, visuallyHiddenStyle } from '@zag-js/dom-query';
4
+ import { getPlacement, getPlacementStyles } from '@zag-js/popper';
5
+ import { createGuards, createMachine } from '@zag-js/core';
6
6
  import { trackDismissableElement } from '@zag-js/dismissable';
7
- import { compact, tryCatch } from '@zag-js/utils';
7
+ import { tryCatch, createSplitProps } from '@zag-js/utils';
8
+ import { createProps } from '@zag-js/types';
8
9
 
9
10
  // src/color-picker.anatomy.ts
10
11
  var anatomy = createAnatomy("color-picker", [
@@ -34,58 +35,47 @@ var anatomy = createAnatomy("color-picker", [
34
35
  "formatSelect"
35
36
  ]);
36
37
  var parts = anatomy.build();
37
- var dom = createScope({
38
- getRootId: (ctx) => ctx.ids?.root ?? `color-picker:${ctx.id}`,
39
- getLabelId: (ctx) => ctx.ids?.label ?? `color-picker:${ctx.id}:label`,
40
- getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `color-picker:${ctx.id}:hidden-input`,
41
- getControlId: (ctx) => ctx.ids?.control ?? `color-picker:${ctx.id}:control`,
42
- getTriggerId: (ctx) => ctx.ids?.trigger ?? `color-picker:${ctx.id}:trigger`,
43
- getContentId: (ctx) => ctx.ids?.content ?? `color-picker:${ctx.id}:content`,
44
- getPositionerId: (ctx) => ctx.ids?.positioner ?? `color-picker:${ctx.id}:positioner`,
45
- getFormatSelectId: (ctx) => ctx.ids?.formatSelect ?? `color-picker:${ctx.id}:format-select`,
46
- getAreaId: (ctx) => ctx.ids?.area ?? `color-picker:${ctx.id}:area`,
47
- getAreaGradientId: (ctx) => ctx.ids?.areaGradient ?? `color-picker:${ctx.id}:area-gradient`,
48
- getAreaThumbId: (ctx) => ctx.ids?.areaThumb ?? `color-picker:${ctx.id}:area-thumb`,
49
- getChannelSliderTrackId: (ctx, channel) => ctx.ids?.channelSliderTrack?.(channel) ?? `color-picker:${ctx.id}:slider-track:${channel}`,
50
- getChannelSliderThumbId: (ctx, channel) => ctx.ids?.channelSliderThumb?.(channel) ?? `color-picker:${ctx.id}:slider-thumb:${channel}`,
51
- getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
52
- getAreaThumbEl: (ctx) => dom.getById(ctx, dom.getAreaThumbId(ctx)),
53
- getChannelSliderThumbEl: (ctx, channel) => dom.getById(ctx, dom.getChannelSliderThumbId(ctx, channel)),
54
- getChannelInputEl: (ctx, channel) => {
55
- const selector = `input[data-channel="${channel}"]`;
56
- return [
57
- ...queryAll(dom.getContentEl(ctx), selector),
58
- ...queryAll(dom.getControlEl(ctx), selector)
59
- ];
60
- },
61
- getFormatSelectEl: (ctx) => dom.getById(ctx, dom.getFormatSelectId(ctx)),
62
- getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
63
- getAreaEl: (ctx) => dom.getById(ctx, dom.getAreaId(ctx)),
64
- getAreaValueFromPoint(ctx, point) {
65
- const areaEl = dom.getAreaEl(ctx);
66
- if (!areaEl) return;
67
- const { percent } = getRelativePoint(point, areaEl);
68
- return percent;
69
- },
70
- getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
71
- getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
72
- getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
73
- getChannelSliderTrackEl: (ctx, channel) => {
74
- return dom.getById(ctx, dom.getChannelSliderTrackId(ctx, channel));
75
- },
76
- getChannelSliderValueFromPoint(ctx, point, channel) {
77
- const trackEl = dom.getChannelSliderTrackEl(ctx, channel);
78
- if (!trackEl) return;
79
- const { percent } = getRelativePoint(point, trackEl);
80
- return percent;
81
- },
82
- getChannelInputEls: (ctx) => {
83
- return [
84
- ...queryAll(dom.getContentEl(ctx), "input[data-channel]"),
85
- ...queryAll(dom.getControlEl(ctx), "input[data-channel]")
86
- ];
87
- }
88
- });
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) => {
58
+ const areaEl = getAreaEl(ctx);
59
+ if (!areaEl) return;
60
+ const { percent } = getRelativePoint(point, areaEl);
61
+ return percent;
62
+ };
63
+ var getControlEl = (ctx) => ctx.getById(getControlId(ctx));
64
+ var getTriggerEl = (ctx) => ctx.getById(getTriggerId(ctx));
65
+ var getPositionerEl = (ctx) => ctx.getById(getPositionerId(ctx));
66
+ var getChannelSliderTrackEl = (ctx, channel) => ctx.getById(getChannelSliderTrackId(ctx, channel));
67
+ var getChannelSliderValueFromPoint = (ctx, point, channel) => {
68
+ const trackEl = getChannelSliderTrackEl(ctx, channel);
69
+ if (!trackEl) return;
70
+ const { percent } = getRelativePoint(point, trackEl);
71
+ return percent;
72
+ };
73
+ var getChannelInputEls = (ctx) => {
74
+ return [
75
+ ...queryAll(getContentEl(ctx), "input[data-channel]"),
76
+ ...queryAll(getControlEl(ctx), "input[data-channel]")
77
+ ];
78
+ };
89
79
  function getChannelDisplayColor(color, channel) {
90
80
  switch (channel) {
91
81
  case "hue":
@@ -171,8 +161,8 @@ function getSliderBackgroundDirection(orientation, dir) {
171
161
  return "left";
172
162
  }
173
163
  }
174
- var getSliderBackground = (props) => {
175
- const { channel, value, dir, orientation } = props;
164
+ var getSliderBackground = (props2) => {
165
+ const { channel, value, dir, orientation } = props2;
176
166
  const bgDirection = getSliderBackgroundDirection(orientation, dir);
177
167
  const { minValue, maxValue } = value.getChannelRange(channel);
178
168
  switch (channel) {
@@ -200,34 +190,36 @@ var getSliderBackground = (props) => {
200
190
  };
201
191
 
202
192
  // src/color-picker.connect.ts
203
- function connect(state, send, normalize) {
204
- const value = state.context.value;
205
- const areaValue = state.context.areaValue;
206
- const valueAsString = state.context.valueAsString;
207
- const disabled = state.context.isDisabled;
208
- const interactive = state.context.isInteractive;
193
+ function connect(service, normalize) {
194
+ const { context, send, prop, computed, state, scope } = service;
195
+ const value = context.get("value");
196
+ const format = context.get("format");
197
+ const areaValue = computed("areaValue");
198
+ const valueAsString = computed("valueAsString");
199
+ const disabled = computed("disabled");
200
+ const interactive = computed("interactive");
209
201
  const dragging = state.hasTag("dragging");
210
202
  const open = state.hasTag("open");
211
203
  const focused = state.hasTag("focused");
212
- const getAreaChannels = (props) => {
204
+ const getAreaChannels = (props2) => {
213
205
  const channels = areaValue.getChannels();
214
206
  return {
215
- xChannel: props.xChannel ?? channels[1],
216
- yChannel: props.yChannel ?? channels[2]
207
+ xChannel: props2.xChannel ?? channels[1],
208
+ yChannel: props2.yChannel ?? channels[2]
217
209
  };
218
210
  };
219
- const currentPlacement = state.context.currentPlacement;
211
+ const currentPlacement = context.get("currentPlacement");
220
212
  const popperStyles = getPlacementStyles({
221
- ...state.context.positioning,
213
+ ...prop("positioning"),
222
214
  placement: currentPlacement
223
215
  });
224
- function getSwatchTriggerState(props) {
225
- const color = normalizeColor(props.value).toFormat(state.context.format);
216
+ function getSwatchTriggerState(props2) {
217
+ const color = normalizeColor(props2.value).toFormat(context.get("format"));
226
218
  return {
227
219
  value: color,
228
220
  valueAsString: color.toString("hex"),
229
221
  checked: color.isEqual(value),
230
- disabled: props.disabled || !interactive
222
+ disabled: props2.disabled || !interactive
231
223
  };
232
224
  }
233
225
  return {
@@ -252,9 +244,9 @@ function connect(state, send, normalize) {
252
244
  const color = value.withChannelValue(channel, channelValue);
253
245
  send({ type: "VALUE.SET", value: color, src: "set-channel" });
254
246
  },
255
- format: state.context.format,
256
- setFormat(format) {
257
- const formatValue = value.toFormat(format);
247
+ format: context.get("format"),
248
+ setFormat(format2) {
249
+ const formatValue = value.toFormat(format2);
258
250
  send({ type: "VALUE.SET", value: formatValue, src: "set-format" });
259
251
  },
260
252
  alpha: value.getChannelValue("alpha"),
@@ -265,11 +257,11 @@ function connect(state, send, normalize) {
265
257
  getRootProps() {
266
258
  return normalize.element({
267
259
  ...parts.root.attrs,
268
- dir: state.context.dir,
269
- id: dom.getRootId(state.context),
260
+ dir: prop("dir"),
261
+ id: getRootId(scope),
270
262
  "data-disabled": dataAttr(disabled),
271
- "data-readonly": dataAttr(state.context.readOnly),
272
- "data-invalid": dataAttr(state.context.invalid),
263
+ "data-readonly": dataAttr(prop("readOnly")),
264
+ "data-invalid": dataAttr(prop("invalid")),
273
265
  style: {
274
266
  "--value": value.toString("css")
275
267
  }
@@ -278,16 +270,16 @@ function connect(state, send, normalize) {
278
270
  getLabelProps() {
279
271
  return normalize.element({
280
272
  ...parts.label.attrs,
281
- dir: state.context.dir,
282
- id: dom.getLabelId(state.context),
283
- htmlFor: dom.getHiddenInputId(state.context),
273
+ dir: prop("dir"),
274
+ id: getLabelId(scope),
275
+ htmlFor: getHiddenInputId(scope),
284
276
  "data-disabled": dataAttr(disabled),
285
- "data-readonly": dataAttr(state.context.readOnly),
286
- "data-invalid": dataAttr(state.context.invalid),
277
+ "data-readonly": dataAttr(prop("readOnly")),
278
+ "data-invalid": dataAttr(prop("invalid")),
287
279
  "data-focus": dataAttr(focused),
288
280
  onClick(event) {
289
281
  event.preventDefault();
290
- const inputEl = query(dom.getControlEl(state.context), "[data-channel=hex]");
282
+ const inputEl = query(getControlEl(scope), "[data-channel=hex]");
291
283
  inputEl?.focus({ preventScroll: true });
292
284
  }
293
285
  });
@@ -295,11 +287,11 @@ function connect(state, send, normalize) {
295
287
  getControlProps() {
296
288
  return normalize.element({
297
289
  ...parts.control.attrs,
298
- id: dom.getControlId(state.context),
299
- dir: state.context.dir,
290
+ id: getControlId(scope),
291
+ dir: prop("dir"),
300
292
  "data-disabled": dataAttr(disabled),
301
- "data-readonly": dataAttr(state.context.readOnly),
302
- "data-invalid": dataAttr(state.context.invalid),
293
+ "data-readonly": dataAttr(prop("readOnly")),
294
+ "data-invalid": dataAttr(prop("invalid")),
303
295
  "data-state": open ? "open" : "closed",
304
296
  "data-focus": dataAttr(focused)
305
297
  });
@@ -307,15 +299,15 @@ function connect(state, send, normalize) {
307
299
  getTriggerProps() {
308
300
  return normalize.button({
309
301
  ...parts.trigger.attrs,
310
- id: dom.getTriggerId(state.context),
311
- dir: state.context.dir,
302
+ id: getTriggerId(scope),
303
+ dir: prop("dir"),
312
304
  disabled,
313
305
  "aria-label": `select color. current color is ${valueAsString}`,
314
- "aria-controls": dom.getContentId(state.context),
315
- "aria-labelledby": dom.getLabelId(state.context),
306
+ "aria-controls": getContentId(scope),
307
+ "aria-labelledby": getLabelId(scope),
316
308
  "data-disabled": dataAttr(disabled),
317
- "data-readonly": dataAttr(state.context.readOnly),
318
- "data-invalid": dataAttr(state.context.invalid),
309
+ "data-readonly": dataAttr(prop("readOnly")),
310
+ "data-invalid": dataAttr(prop("invalid")),
319
311
  "data-placement": currentPlacement,
320
312
  "aria-expanded": dataAttr(open),
321
313
  "data-state": open ? "open" : "closed",
@@ -337,16 +329,16 @@ function connect(state, send, normalize) {
337
329
  getPositionerProps() {
338
330
  return normalize.element({
339
331
  ...parts.positioner.attrs,
340
- id: dom.getPositionerId(state.context),
341
- dir: state.context.dir,
332
+ id: getPositionerId(scope),
333
+ dir: prop("dir"),
342
334
  style: popperStyles.floating
343
335
  });
344
336
  },
345
337
  getContentProps() {
346
338
  return normalize.element({
347
339
  ...parts.content.attrs,
348
- id: dom.getContentId(state.context),
349
- dir: state.context.dir,
340
+ id: getContentId(scope),
341
+ dir: prop("dir"),
350
342
  "data-placement": currentPlacement,
351
343
  "data-state": open ? "open" : "closed",
352
344
  hidden: !open
@@ -355,25 +347,25 @@ function connect(state, send, normalize) {
355
347
  getValueTextProps() {
356
348
  return normalize.element({
357
349
  ...parts.valueText.attrs,
358
- dir: state.context.dir,
350
+ dir: prop("dir"),
359
351
  "data-disabled": dataAttr(disabled),
360
352
  "data-focus": dataAttr(focused)
361
353
  });
362
354
  },
363
- getAreaProps(props = {}) {
364
- const { xChannel, yChannel } = getAreaChannels(props);
355
+ getAreaProps(props2 = {}) {
356
+ const { xChannel, yChannel } = getAreaChannels(props2);
365
357
  const { areaStyles } = getColorAreaGradient(areaValue, {
366
358
  xChannel,
367
359
  yChannel,
368
- dir: state.context.dir
360
+ dir: prop("dir")
369
361
  });
370
362
  return normalize.element({
371
363
  ...parts.area.attrs,
372
- id: dom.getAreaId(state.context),
364
+ id: getAreaId(scope),
373
365
  role: "group",
374
- "data-invalid": dataAttr(state.context.invalid),
366
+ "data-invalid": dataAttr(prop("invalid")),
375
367
  "data-disabled": dataAttr(disabled),
376
- "data-readonly": dataAttr(state.context.readOnly),
368
+ "data-readonly": dataAttr(prop("readOnly")),
377
369
  onPointerDown(event) {
378
370
  if (!interactive) return;
379
371
  if (!isLeftClick(event)) return;
@@ -391,19 +383,19 @@ function connect(state, send, normalize) {
391
383
  }
392
384
  });
393
385
  },
394
- getAreaBackgroundProps(props = {}) {
395
- const { xChannel, yChannel } = getAreaChannels(props);
386
+ getAreaBackgroundProps(props2 = {}) {
387
+ const { xChannel, yChannel } = getAreaChannels(props2);
396
388
  const { areaGradientStyles } = getColorAreaGradient(areaValue, {
397
389
  xChannel,
398
390
  yChannel,
399
- dir: state.context.dir
391
+ dir: prop("dir")
400
392
  });
401
393
  return normalize.element({
402
394
  ...parts.areaBackground.attrs,
403
- id: dom.getAreaGradientId(state.context),
404
- "data-invalid": dataAttr(state.context.invalid),
395
+ id: getAreaGradientId(scope),
396
+ "data-invalid": dataAttr(prop("invalid")),
405
397
  "data-disabled": dataAttr(disabled),
406
- "data-readonly": dataAttr(state.context.readOnly),
398
+ "data-readonly": dataAttr(prop("readOnly")),
407
399
  style: {
408
400
  position: "relative",
409
401
  touchAction: "none",
@@ -412,8 +404,8 @@ function connect(state, send, normalize) {
412
404
  }
413
405
  });
414
406
  },
415
- getAreaThumbProps(props = {}) {
416
- const { xChannel, yChannel } = getAreaChannels(props);
407
+ getAreaThumbProps(props2 = {}) {
408
+ const { xChannel, yChannel } = getAreaChannels(props2);
417
409
  const channel = { xChannel, yChannel };
418
410
  const xPercent = areaValue.getChannelValuePercent(xChannel);
419
411
  const yPercent = 1 - areaValue.getChannelValuePercent(yChannel);
@@ -422,12 +414,12 @@ function connect(state, send, normalize) {
422
414
  const color = areaValue.withChannelValue("alpha", 1).toString("css");
423
415
  return normalize.element({
424
416
  ...parts.areaThumb.attrs,
425
- id: dom.getAreaThumbId(state.context),
426
- dir: state.context.dir,
417
+ id: getAreaThumbId(scope),
418
+ dir: prop("dir"),
427
419
  tabIndex: disabled ? void 0 : 0,
428
420
  "data-disabled": dataAttr(disabled),
429
- "data-invalid": dataAttr(state.context.invalid),
430
- "data-readonly": dataAttr(state.context.readOnly),
421
+ "data-invalid": dataAttr(prop("invalid")),
422
+ "data-readonly": dataAttr(prop("readOnly")),
431
423
  role: "slider",
432
424
  "aria-valuemin": 0,
433
425
  "aria-valuemax": 100,
@@ -476,7 +468,9 @@ function connect(state, send, normalize) {
476
468
  event2.stopPropagation();
477
469
  }
478
470
  };
479
- const exec = keyMap[getEventKey(event, state.context)];
471
+ const exec = keyMap[getEventKey(event, {
472
+ dir: prop("dir")
473
+ })];
480
474
  if (exec) {
481
475
  exec(event);
482
476
  event.preventDefault();
@@ -484,8 +478,8 @@ function connect(state, send, normalize) {
484
478
  }
485
479
  });
486
480
  },
487
- getTransparencyGridProps(props = {}) {
488
- const { size = "12px" } = props;
481
+ getTransparencyGridProps(props2 = {}) {
482
+ const { size = "12px" } = props2;
489
483
  return normalize.element({
490
484
  ...parts.transparencyGrid.attrs,
491
485
  style: {
@@ -502,8 +496,8 @@ function connect(state, send, normalize) {
502
496
  }
503
497
  });
504
498
  },
505
- getChannelSliderProps(props) {
506
- const { orientation = "horizontal", channel, format } = props;
499
+ getChannelSliderProps(props2) {
500
+ const { orientation = "horizontal", channel, format: format2 } = props2;
507
501
  return normalize.element({
508
502
  ...parts.channelSlider.attrs,
509
503
  "data-channel": channel,
@@ -514,7 +508,7 @@ function connect(state, send, normalize) {
514
508
  if (!isLeftClick(event)) return;
515
509
  if (isModifierKey(event)) return;
516
510
  const point = getEventPoint(event);
517
- send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, format, point, id: channel, orientation });
511
+ send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, format: format2, point, id: channel, orientation });
518
512
  event.preventDefault();
519
513
  },
520
514
  style: {
@@ -523,12 +517,12 @@ function connect(state, send, normalize) {
523
517
  }
524
518
  });
525
519
  },
526
- getChannelSliderTrackProps(props) {
527
- const { orientation = "horizontal", channel, format } = props;
528
- const normalizedValue = format ? value.toFormat(format) : areaValue;
520
+ getChannelSliderTrackProps(props2) {
521
+ const { orientation = "horizontal", channel, format: format2 } = props2;
522
+ const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
529
523
  return normalize.element({
530
524
  ...parts.channelSliderTrack.attrs,
531
- id: dom.getChannelSliderTrackId(state.context, channel),
525
+ id: getChannelSliderTrackId(scope, channel),
532
526
  role: "group",
533
527
  "data-channel": channel,
534
528
  "data-orientation": orientation,
@@ -538,22 +532,22 @@ function connect(state, send, normalize) {
538
532
  backgroundImage: getSliderBackground({
539
533
  orientation,
540
534
  channel,
541
- dir: state.context.dir,
535
+ dir: prop("dir"),
542
536
  value: normalizedValue
543
537
  })
544
538
  }
545
539
  });
546
540
  },
547
- getChannelSliderLabelProps(props) {
548
- const { channel } = props;
541
+ getChannelSliderLabelProps(props2) {
542
+ const { channel } = props2;
549
543
  return normalize.element({
550
544
  ...parts.channelSliderLabel.attrs,
551
545
  "data-channel": channel,
552
546
  onClick(event) {
553
547
  if (!interactive) return;
554
548
  event.preventDefault();
555
- const thumbId = dom.getChannelSliderThumbId(state.context, channel);
556
- dom.getById(state.context, thumbId)?.focus({ preventScroll: true });
549
+ const thumbId = getChannelSliderThumbId(scope, channel);
550
+ scope.getById(thumbId)?.focus({ preventScroll: true });
557
551
  },
558
552
  style: {
559
553
  userSelect: "none",
@@ -561,22 +555,22 @@ function connect(state, send, normalize) {
561
555
  }
562
556
  });
563
557
  },
564
- getChannelSliderValueTextProps(props) {
558
+ getChannelSliderValueTextProps(props2) {
565
559
  return normalize.element({
566
560
  ...parts.channelSliderValueText.attrs,
567
- "data-channel": props.channel
561
+ "data-channel": props2.channel
568
562
  });
569
563
  },
570
- getChannelSliderThumbProps(props) {
571
- const { orientation = "horizontal", channel, format } = props;
572
- const normalizedValue = format ? value.toFormat(format) : areaValue;
564
+ getChannelSliderThumbProps(props2) {
565
+ const { orientation = "horizontal", channel, format: format2 } = props2;
566
+ const normalizedValue = format2 ? value.toFormat(format2) : areaValue;
573
567
  const channelRange = normalizedValue.getChannelRange(channel);
574
568
  const channelValue = normalizedValue.getChannelValue(channel);
575
569
  const offset = (channelValue - channelRange.minValue) / (channelRange.maxValue - channelRange.minValue);
576
570
  const placementStyles = orientation === "horizontal" ? { left: `${offset * 100}%`, top: "50%" } : { top: `${offset * 100}%`, left: "50%" };
577
571
  return normalize.element({
578
572
  ...parts.channelSliderThumb.attrs,
579
- id: dom.getChannelSliderThumbId(state.context, channel),
573
+ id: getChannelSliderThumbId(scope, channel),
580
574
  role: "slider",
581
575
  "aria-label": channel,
582
576
  tabIndex: disabled ? void 0 : 0,
@@ -632,7 +626,9 @@ function connect(state, send, normalize) {
632
626
  event2.stopPropagation();
633
627
  }
634
628
  };
635
- const exec = keyMap[getEventKey(event, state.context)];
629
+ const exec = keyMap[getEventKey(event, {
630
+ dir: prop("dir")
631
+ })];
636
632
  if (exec) {
637
633
  exec(event);
638
634
  event.preventDefault();
@@ -640,13 +636,13 @@ function connect(state, send, normalize) {
640
636
  }
641
637
  });
642
638
  },
643
- getChannelInputProps(props) {
644
- const { channel } = props;
639
+ getChannelInputProps(props2) {
640
+ const { channel } = props2;
645
641
  const isTextField = channel === "hex" || channel === "css";
646
642
  const channelRange = getChannelRange(value, channel);
647
643
  return normalize.input({
648
644
  ...parts.channelInput.attrs,
649
- dir: state.context.dir,
645
+ dir: prop("dir"),
650
646
  type: isTextField ? "text" : "number",
651
647
  "data-channel": channel,
652
648
  "aria-label": channel,
@@ -654,9 +650,9 @@ function connect(state, send, normalize) {
654
650
  autoComplete: "off",
655
651
  disabled,
656
652
  "data-disabled": dataAttr(disabled),
657
- "data-invalid": dataAttr(state.context.invalid),
658
- "data-readonly": dataAttr(state.context.readOnly),
659
- readOnly: state.context.readOnly,
653
+ "data-invalid": dataAttr(prop("invalid")),
654
+ "data-readonly": dataAttr(prop("readOnly")),
655
+ readOnly: prop("readOnly"),
660
656
  defaultValue: getChannelValue(value, channel),
661
657
  min: channelRange?.minValue,
662
658
  max: channelRange?.maxValue,
@@ -698,11 +694,11 @@ function connect(state, send, normalize) {
698
694
  return normalize.input({
699
695
  type: "text",
700
696
  disabled,
701
- name: state.context.name,
697
+ name: prop("name"),
702
698
  tabIndex: -1,
703
- readOnly: state.context.readOnly,
704
- required: state.context.required,
705
- id: dom.getHiddenInputId(state.context),
699
+ readOnly: prop("readOnly"),
700
+ required: prop("required"),
701
+ id: getHiddenInputId(scope),
706
702
  style: visuallyHiddenStyle,
707
703
  defaultValue: valueAsString
708
704
  });
@@ -711,15 +707,15 @@ function connect(state, send, normalize) {
711
707
  return normalize.button({
712
708
  ...parts.eyeDropperTrigger.attrs,
713
709
  type: "button",
714
- dir: state.context.dir,
710
+ dir: prop("dir"),
715
711
  disabled,
716
712
  "data-disabled": dataAttr(disabled),
717
- "data-invalid": dataAttr(state.context.invalid),
718
- "data-readonly": dataAttr(state.context.readOnly),
713
+ "data-invalid": dataAttr(prop("invalid")),
714
+ "data-readonly": dataAttr(prop("readOnly")),
719
715
  "aria-label": "Pick a color from the screen",
720
716
  onClick() {
721
717
  if (!interactive) return;
722
- send("EYEDROPPER.CLICK");
718
+ send({ type: "EYEDROPPER.CLICK" });
723
719
  }
724
720
  });
725
721
  },
@@ -730,12 +726,12 @@ function connect(state, send, normalize) {
730
726
  });
731
727
  },
732
728
  getSwatchTriggerState,
733
- getSwatchTriggerProps(props) {
734
- const swatchState = getSwatchTriggerState(props);
729
+ getSwatchTriggerProps(props2) {
730
+ const swatchState = getSwatchTriggerState(props2);
735
731
  return normalize.button({
736
732
  ...parts.swatchTrigger.attrs,
737
733
  disabled: swatchState.disabled,
738
- dir: state.context.dir,
734
+ dir: prop("dir"),
739
735
  type: "button",
740
736
  "aria-label": `select ${swatchState.valueAsString} as the color`,
741
737
  "data-state": swatchState.checked ? "checked" : "unchecked",
@@ -751,21 +747,21 @@ function connect(state, send, normalize) {
751
747
  }
752
748
  });
753
749
  },
754
- getSwatchIndicatorProps(props) {
755
- const swatchState = getSwatchTriggerState(props);
750
+ getSwatchIndicatorProps(props2) {
751
+ const swatchState = getSwatchTriggerState(props2);
756
752
  return normalize.element({
757
753
  ...parts.swatchIndicator.attrs,
758
- dir: state.context.dir,
754
+ dir: prop("dir"),
759
755
  hidden: !swatchState.checked
760
756
  });
761
757
  },
762
- getSwatchProps(props) {
763
- const { respectAlpha = true } = props;
764
- const swatchState = getSwatchTriggerState(props);
758
+ getSwatchProps(props2) {
759
+ const { respectAlpha = true } = props2;
760
+ const swatchState = getSwatchTriggerState(props2);
765
761
  const color = swatchState.value.toString(respectAlpha ? "css" : "hex");
766
762
  return normalize.element({
767
763
  ...parts.swatch.attrs,
768
- dir: state.context.dir,
764
+ dir: prop("dir"),
769
765
  "data-state": swatchState.checked ? "checked" : "unchecked",
770
766
  "data-value": swatchState.valueAsString,
771
767
  style: {
@@ -778,12 +774,12 @@ function connect(state, send, normalize) {
778
774
  getFormatTriggerProps() {
779
775
  return normalize.button({
780
776
  ...parts.formatTrigger.attrs,
781
- dir: state.context.dir,
777
+ dir: prop("dir"),
782
778
  type: "button",
783
- "aria-label": `change color format to ${getNextFormat(state.context.format)}`,
779
+ "aria-label": `change color format to ${getNextFormat(format)}`,
784
780
  onClick(event) {
785
781
  if (event.currentTarget.disabled) return;
786
- const nextFormat = getNextFormat(state.context.format);
782
+ const nextFormat = getNextFormat(format);
787
783
  send({ type: "FORMAT.SET", format: nextFormat, src: "format-trigger" });
788
784
  }
789
785
  });
@@ -792,12 +788,12 @@ function connect(state, send, normalize) {
792
788
  return normalize.select({
793
789
  ...parts.formatSelect.attrs,
794
790
  "aria-label": "change color format",
795
- dir: state.context.dir,
796
- defaultValue: state.context.format,
791
+ dir: prop("dir"),
792
+ defaultValue: prop("format"),
797
793
  disabled,
798
794
  onChange(event) {
799
- const format = assertFormat(event.currentTarget.value);
800
- send({ type: "FORMAT.SET", format, src: "format-select" });
795
+ const format2 = assertFormat(event.currentTarget.value);
796
+ send({ type: "FORMAT.SET", format: format2, src: "format-select" });
801
797
  }
802
798
  });
803
799
  }
@@ -818,591 +814,633 @@ var parse = (colorString) => {
818
814
  };
819
815
 
820
816
  // src/color-picker.machine.ts
821
- var { and } = guards;
822
- function machine(userContext) {
823
- const ctx = compact(userContext);
824
- return createMachine(
825
- {
826
- id: "color-picker",
827
- initial: ctx.open ? "open" : "idle",
828
- context: {
829
- dir: "ltr",
830
- value: parse("#000000"),
831
- format: "rgba",
832
- disabled: false,
833
- closeOnSelect: false,
834
- openAutoFocus: true,
835
- ...ctx,
836
- activeId: null,
837
- activeChannel: null,
838
- activeOrientation: null,
839
- fieldsetDisabled: false,
840
- restoreFocus: true,
841
- positioning: {
842
- ...ctx.positioning,
843
- placement: "bottom"
844
- }
845
- },
846
- computed: {
847
- isRtl: (ctx2) => ctx2.dir === "rtl",
848
- isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
849
- isInteractive: (ctx2) => !(ctx2.isDisabled || ctx2.readOnly),
850
- valueAsString: (ctx2) => ctx2.value.toString(ctx2.format),
851
- areaValue: (ctx2) => {
852
- const format = ctx2.format.startsWith("hsl") ? "hsla" : "hsba";
853
- return ctx2.value.toFormat(format);
854
- }
855
- },
856
- activities: ["trackFormControl"],
857
- watch: {
858
- value: ["syncInputElements"],
859
- format: ["syncFormatSelectElement"],
860
- open: ["toggleVisibility"]
861
- },
862
- on: {
863
- "VALUE.SET": {
864
- actions: ["setValue"]
865
- },
866
- "FORMAT.SET": {
867
- actions: ["setFormat"]
868
- },
869
- "CHANNEL_INPUT.CHANGE": {
870
- actions: ["setChannelColorFromInput"]
817
+ var { and } = createGuards();
818
+ var machine = createMachine({
819
+ props({ props: props2 }) {
820
+ return {
821
+ dir: "ltr",
822
+ defaultValue: parse("#000000"),
823
+ defaultFormat: "rgba",
824
+ openAutoFocus: true,
825
+ ...props2,
826
+ positioning: {
827
+ placement: "bottom",
828
+ ...props2.positioning
829
+ }
830
+ };
831
+ },
832
+ initialState({ prop }) {
833
+ const open = prop("open") || prop("defaultOpen");
834
+ return open ? "open" : "idle";
835
+ },
836
+ context({ prop, bindable, getContext, scope }) {
837
+ return {
838
+ value: bindable(() => ({
839
+ defaultValue: prop("defaultValue"),
840
+ value: prop("value"),
841
+ isEqual(a, b) {
842
+ return a.toString("css") === b?.toString("css");
871
843
  },
872
- "EYEDROPPER.CLICK": {
873
- actions: ["openEyeDropper"]
844
+ hash(a) {
845
+ return a.toString("css");
874
846
  },
875
- "SWATCH_TRIGGER.CLICK": {
876
- actions: ["setValue"]
847
+ onChange(value) {
848
+ const ctx = getContext();
849
+ const valueAsString = value.toString(ctx.get("format"));
850
+ prop("onValueChange")?.({ value, valueAsString });
851
+ dispatchInputValueEvent(getHiddenInputEl(scope), { value: valueAsString });
877
852
  }
878
- },
879
- states: {
880
- idle: {
881
- tags: ["closed"],
882
- on: {
883
- "CONTROLLED.OPEN": {
884
- target: "open",
885
- actions: ["setInitialFocus"]
886
- },
887
- OPEN: [
888
- {
889
- guard: "isOpenControlled",
890
- actions: ["invokeOnOpen"]
891
- },
892
- {
893
- target: "open",
894
- actions: ["invokeOnOpen", "setInitialFocus"]
895
- }
896
- ],
897
- "TRIGGER.CLICK": [
898
- {
899
- guard: "isOpenControlled",
900
- actions: ["invokeOnOpen"]
901
- },
902
- {
903
- target: "open",
904
- actions: ["invokeOnOpen", "setInitialFocus"]
905
- }
906
- ],
907
- "CHANNEL_INPUT.FOCUS": {
908
- target: "focused",
909
- actions: ["setActiveChannel"]
910
- }
911
- }
912
- },
913
- focused: {
914
- tags: ["closed", "focused"],
915
- on: {
916
- "CONTROLLED.OPEN": {
917
- target: "open",
918
- actions: ["setInitialFocus"]
919
- },
920
- OPEN: [
921
- {
922
- guard: "isOpenControlled",
923
- actions: ["invokeOnOpen"]
924
- },
925
- {
926
- target: "open",
927
- actions: ["invokeOnOpen", "setInitialFocus"]
928
- }
929
- ],
930
- "TRIGGER.CLICK": [
931
- {
932
- guard: "isOpenControlled",
933
- actions: ["invokeOnOpen"]
934
- },
935
- {
936
- target: "open",
937
- actions: ["invokeOnOpen", "setInitialFocus"]
938
- }
939
- ],
940
- "CHANNEL_INPUT.FOCUS": {
941
- actions: ["setActiveChannel"]
942
- },
943
- "CHANNEL_INPUT.BLUR": {
944
- target: "idle",
945
- actions: ["setChannelColorFromInput"]
946
- },
947
- "TRIGGER.BLUR": {
948
- target: "idle"
949
- }
950
- }
853
+ })),
854
+ format: bindable(() => ({
855
+ defaultValue: prop("defaultFormat"),
856
+ value: prop("format"),
857
+ onChange(format) {
858
+ prop("onFormatChange")?.({ format });
859
+ }
860
+ })),
861
+ activeId: bindable(() => ({ defaultValue: null })),
862
+ activeChannel: bindable(() => ({ defaultValue: null })),
863
+ activeOrientation: bindable(() => ({ defaultValue: null })),
864
+ fieldsetDisabled: bindable(() => ({ defaultValue: false })),
865
+ restoreFocus: bindable(() => ({ defaultValue: true })),
866
+ currentPlacement: bindable(() => ({
867
+ defaultValue: void 0
868
+ }))
869
+ };
870
+ },
871
+ computed: {
872
+ rtl: ({ prop }) => prop("dir") === "rtl",
873
+ disabled: ({ prop, context }) => !!prop("disabled") || context.get("fieldsetDisabled"),
874
+ interactive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
875
+ valueAsString: ({ context }) => context.get("value").toString(context.get("format")),
876
+ areaValue: ({ context }) => {
877
+ const format = context.get("format").startsWith("hsl") ? "hsla" : "hsba";
878
+ return context.get("value").toFormat(format);
879
+ }
880
+ },
881
+ effects: ["trackFormControl"],
882
+ watch({ prop, context, action, track }) {
883
+ track([() => context.hash("value")], () => {
884
+ action(["syncInputElements"]);
885
+ });
886
+ track([() => context.get("format")], () => {
887
+ action(["syncFormatSelectElement"]);
888
+ });
889
+ track([() => prop("open")], () => {
890
+ action(["toggleVisibility"]);
891
+ });
892
+ },
893
+ on: {
894
+ "VALUE.SET": {
895
+ actions: ["setValue"]
896
+ },
897
+ "FORMAT.SET": {
898
+ actions: ["setFormat"]
899
+ },
900
+ "CHANNEL_INPUT.CHANGE": {
901
+ actions: ["setChannelColorFromInput"]
902
+ },
903
+ "EYEDROPPER.CLICK": {
904
+ actions: ["openEyeDropper"]
905
+ },
906
+ "SWATCH_TRIGGER.CLICK": {
907
+ actions: ["setValue"]
908
+ }
909
+ },
910
+ states: {
911
+ idle: {
912
+ tags: ["closed"],
913
+ on: {
914
+ "CONTROLLED.OPEN": {
915
+ target: "open",
916
+ actions: ["setInitialFocus"]
951
917
  },
952
- open: {
953
- tags: ["open"],
954
- activities: ["trackPositioning", "trackDismissableElement"],
955
- on: {
956
- "CONTROLLED.CLOSE": [
957
- {
958
- guard: "shouldRestoreFocus",
959
- target: "focused",
960
- actions: ["setReturnFocus"]
961
- },
962
- {
963
- target: "idle"
964
- }
965
- ],
966
- "TRIGGER.CLICK": [
967
- {
968
- guard: "isOpenControlled",
969
- actions: ["invokeOnClose"]
970
- },
971
- {
972
- target: "idle",
973
- actions: ["invokeOnClose"]
974
- }
975
- ],
976
- "AREA.POINTER_DOWN": {
977
- target: "open:dragging",
978
- actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
979
- },
980
- "AREA.FOCUS": {
981
- actions: ["setActiveChannel"]
982
- },
983
- "CHANNEL_SLIDER.POINTER_DOWN": {
984
- target: "open:dragging",
985
- actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
986
- },
987
- "CHANNEL_SLIDER.FOCUS": {
988
- actions: ["setActiveChannel"]
989
- },
990
- "AREA.ARROW_LEFT": {
991
- actions: ["decrementAreaXChannel"]
992
- },
993
- "AREA.ARROW_RIGHT": {
994
- actions: ["incrementAreaXChannel"]
995
- },
996
- "AREA.ARROW_UP": {
997
- actions: ["incrementAreaYChannel"]
998
- },
999
- "AREA.ARROW_DOWN": {
1000
- actions: ["decrementAreaYChannel"]
1001
- },
1002
- "AREA.PAGE_UP": {
1003
- actions: ["incrementAreaXChannel"]
1004
- },
1005
- "AREA.PAGE_DOWN": {
1006
- actions: ["decrementAreaXChannel"]
1007
- },
1008
- "CHANNEL_SLIDER.ARROW_LEFT": {
1009
- actions: ["decrementChannel"]
1010
- },
1011
- "CHANNEL_SLIDER.ARROW_RIGHT": {
1012
- actions: ["incrementChannel"]
1013
- },
1014
- "CHANNEL_SLIDER.ARROW_UP": {
1015
- actions: ["incrementChannel"]
1016
- },
1017
- "CHANNEL_SLIDER.ARROW_DOWN": {
1018
- actions: ["decrementChannel"]
1019
- },
1020
- "CHANNEL_SLIDER.PAGE_UP": {
1021
- actions: ["incrementChannel"]
1022
- },
1023
- "CHANNEL_SLIDER.PAGE_DOWN": {
1024
- actions: ["decrementChannel"]
1025
- },
1026
- "CHANNEL_SLIDER.HOME": {
1027
- actions: ["setChannelToMin"]
1028
- },
1029
- "CHANNEL_SLIDER.END": {
1030
- actions: ["setChannelToMax"]
1031
- },
1032
- "CHANNEL_INPUT.BLUR": {
1033
- actions: ["setChannelColorFromInput"]
1034
- },
1035
- INTERACT_OUTSIDE: [
1036
- {
1037
- guard: "isOpenControlled",
1038
- actions: ["invokeOnClose"]
1039
- },
1040
- {
1041
- guard: "shouldRestoreFocus",
1042
- target: "focused",
1043
- actions: ["invokeOnClose", "setReturnFocus"]
1044
- },
1045
- {
1046
- target: "idle",
1047
- actions: ["invokeOnClose"]
1048
- }
1049
- ],
1050
- CLOSE: [
1051
- {
1052
- guard: "isOpenControlled",
1053
- actions: ["invokeOnClose"]
1054
- },
1055
- {
1056
- target: "idle",
1057
- actions: ["invokeOnClose"]
1058
- }
1059
- ],
1060
- "SWATCH_TRIGGER.CLICK": [
1061
- {
1062
- guard: and("isOpenControlled", "closeOnSelect"),
1063
- actions: ["setValue", "invokeOnClose"]
1064
- },
1065
- {
1066
- guard: "closeOnSelect",
1067
- target: "focused",
1068
- actions: ["setValue", "invokeOnClose", "setReturnFocus"]
1069
- },
1070
- {
1071
- actions: ["setValue"]
1072
- }
1073
- ]
918
+ OPEN: [
919
+ {
920
+ guard: "isOpenControlled",
921
+ actions: ["invokeOnOpen"]
922
+ },
923
+ {
924
+ target: "open",
925
+ actions: ["invokeOnOpen", "setInitialFocus"]
1074
926
  }
1075
- },
1076
- "open:dragging": {
1077
- tags: ["open"],
1078
- exit: ["clearActiveChannel"],
1079
- activities: ["trackPointerMove", "disableTextSelection", "trackPositioning", "trackDismissableElement"],
1080
- on: {
1081
- "CONTROLLED.CLOSE": [
1082
- {
1083
- guard: "shouldRestoreFocus",
1084
- target: "focused",
1085
- actions: ["setReturnFocus"]
1086
- },
1087
- {
1088
- target: "idle"
1089
- }
1090
- ],
1091
- "AREA.POINTER_MOVE": {
1092
- actions: ["setAreaColorFromPoint", "focusAreaThumb"]
1093
- },
1094
- "AREA.POINTER_UP": {
1095
- target: "open",
1096
- actions: ["invokeOnChangeEnd"]
1097
- },
1098
- "CHANNEL_SLIDER.POINTER_MOVE": {
1099
- actions: ["setChannelColorFromPoint", "focusChannelThumb"]
1100
- },
1101
- "CHANNEL_SLIDER.POINTER_UP": {
1102
- target: "open",
1103
- actions: ["invokeOnChangeEnd"]
1104
- },
1105
- INTERACT_OUTSIDE: [
1106
- {
1107
- guard: "isOpenControlled",
1108
- actions: ["invokeOnClose"]
1109
- },
1110
- {
1111
- guard: "shouldRestoreFocus",
1112
- target: "focused",
1113
- actions: ["invokeOnClose", "setReturnFocus"]
1114
- },
1115
- {
1116
- target: "idle",
1117
- actions: ["invokeOnClose"]
1118
- }
1119
- ],
1120
- CLOSE: [
1121
- {
1122
- guard: "isOpenControlled",
1123
- actions: ["invokeOnClose"]
1124
- },
1125
- {
1126
- target: "idle",
1127
- actions: ["invokeOnClose"]
1128
- }
1129
- ]
927
+ ],
928
+ "TRIGGER.CLICK": [
929
+ {
930
+ guard: "isOpenControlled",
931
+ actions: ["invokeOnOpen"]
932
+ },
933
+ {
934
+ target: "open",
935
+ actions: ["invokeOnOpen", "setInitialFocus"]
1130
936
  }
937
+ ],
938
+ "CHANNEL_INPUT.FOCUS": {
939
+ target: "focused",
940
+ actions: ["setActiveChannel"]
1131
941
  }
1132
942
  }
1133
943
  },
1134
- {
1135
- guards: {
1136
- closeOnSelect: (ctx2) => !!ctx2.closeOnSelect,
1137
- isOpenControlled: (ctx2) => !!ctx2["open.controlled"],
1138
- shouldRestoreFocus: (ctx2) => !!ctx2.restoreFocus
1139
- },
1140
- activities: {
1141
- trackPositioning(ctx2) {
1142
- ctx2.currentPlacement || (ctx2.currentPlacement = ctx2.positioning.placement);
1143
- const anchorEl = dom.getTriggerEl(ctx2);
1144
- const getPositionerEl = () => dom.getPositionerEl(ctx2);
1145
- return getPlacement(anchorEl, getPositionerEl, {
1146
- ...ctx2.positioning,
1147
- defer: true,
1148
- onComplete(data) {
1149
- ctx2.currentPlacement = data.placement;
1150
- }
1151
- });
1152
- },
1153
- trackDismissableElement(ctx2, _evt, { send }) {
1154
- const getContentEl = () => dom.getContentEl(ctx2);
1155
- return trackDismissableElement(getContentEl, {
1156
- exclude: dom.getTriggerEl(ctx2),
1157
- defer: true,
1158
- onInteractOutside(event) {
1159
- ctx2.onInteractOutside?.(event);
1160
- if (event.defaultPrevented) return;
1161
- ctx2.restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
1162
- },
1163
- onPointerDownOutside: ctx2.onPointerDownOutside,
1164
- onFocusOutside: ctx2.onFocusOutside,
1165
- onDismiss() {
1166
- send({ type: "INTERACT_OUTSIDE" });
1167
- }
1168
- });
944
+ focused: {
945
+ tags: ["closed", "focused"],
946
+ on: {
947
+ "CONTROLLED.OPEN": {
948
+ target: "open",
949
+ actions: ["setInitialFocus"]
1169
950
  },
1170
- trackFormControl(ctx2, _evt, { send, initialContext }) {
1171
- const inputEl = dom.getHiddenInputEl(ctx2);
1172
- return trackFormControl(inputEl, {
1173
- onFieldsetDisabledChange(disabled) {
1174
- ctx2.fieldsetDisabled = disabled;
1175
- },
1176
- onFormReset() {
1177
- send({ type: "VALUE.SET", value: initialContext.value, src: "form.reset" });
1178
- }
1179
- });
951
+ OPEN: [
952
+ {
953
+ guard: "isOpenControlled",
954
+ actions: ["invokeOnOpen"]
955
+ },
956
+ {
957
+ target: "open",
958
+ actions: ["invokeOnOpen", "setInitialFocus"]
959
+ }
960
+ ],
961
+ "TRIGGER.CLICK": [
962
+ {
963
+ guard: "isOpenControlled",
964
+ actions: ["invokeOnOpen"]
965
+ },
966
+ {
967
+ target: "open",
968
+ actions: ["invokeOnOpen", "setInitialFocus"]
969
+ }
970
+ ],
971
+ "CHANNEL_INPUT.FOCUS": {
972
+ actions: ["setActiveChannel"]
1180
973
  },
1181
- trackPointerMove(ctx2, evt, { send }) {
1182
- return trackPointerMove(dom.getDoc(ctx2), {
1183
- onPointerMove({ point }) {
1184
- const type = ctx2.activeId === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
1185
- send({ type, point, format: evt.format });
1186
- },
1187
- onPointerUp() {
1188
- const type = ctx2.activeId === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP";
1189
- send({ type });
1190
- }
1191
- });
974
+ "CHANNEL_INPUT.BLUR": {
975
+ target: "idle",
976
+ actions: ["setChannelColorFromInput"]
1192
977
  },
1193
- disableTextSelection(ctx2) {
1194
- return disableTextSelection({ doc: dom.getDoc(ctx2), target: dom.getContentEl(ctx2) });
978
+ "TRIGGER.BLUR": {
979
+ target: "idle"
1195
980
  }
1196
- },
1197
- actions: {
1198
- openEyeDropper(ctx2) {
1199
- const isSupported = "EyeDropper" in dom.getWin(ctx2);
1200
- if (!isSupported) return;
1201
- const win = dom.getWin(ctx2);
1202
- const picker = new win.EyeDropper();
1203
- picker.open().then(({ sRGBHex }) => {
1204
- const format = ctx2.value.getFormat();
1205
- const color = parseColor(sRGBHex).toFormat(format);
1206
- set.value(ctx2, color);
1207
- ctx2.onValueChangeEnd?.({ value: ctx2.value, valueAsString: ctx2.valueAsString });
1208
- }).catch(() => void 0);
1209
- },
1210
- setActiveChannel(ctx2, evt) {
1211
- ctx2.activeId = evt.id;
1212
- if (evt.channel) ctx2.activeChannel = evt.channel;
1213
- if (evt.orientation) ctx2.activeOrientation = evt.orientation;
1214
- },
1215
- clearActiveChannel(ctx2) {
1216
- ctx2.activeChannel = null;
1217
- ctx2.activeId = null;
1218
- ctx2.activeOrientation = null;
981
+ }
982
+ },
983
+ open: {
984
+ tags: ["open"],
985
+ effects: ["trackPositioning", "trackDismissableElement"],
986
+ on: {
987
+ "CONTROLLED.CLOSE": [
988
+ {
989
+ guard: "shouldRestoreFocus",
990
+ target: "focused",
991
+ actions: ["setReturnFocus"]
992
+ },
993
+ {
994
+ target: "idle"
995
+ }
996
+ ],
997
+ "TRIGGER.CLICK": [
998
+ {
999
+ guard: "isOpenControlled",
1000
+ actions: ["invokeOnClose"]
1001
+ },
1002
+ {
1003
+ target: "idle",
1004
+ actions: ["invokeOnClose"]
1005
+ }
1006
+ ],
1007
+ "AREA.POINTER_DOWN": {
1008
+ target: "open:dragging",
1009
+ actions: ["setActiveChannel", "setAreaColorFromPoint", "focusAreaThumb"]
1219
1010
  },
1220
- setAreaColorFromPoint(ctx2, evt) {
1221
- const normalizedValue = evt.format ? ctx2.value.toFormat(evt.format) : ctx2.areaValue;
1222
- const { xChannel, yChannel } = evt.channel || ctx2.activeChannel;
1223
- const percent = dom.getAreaValueFromPoint(ctx2, evt.point);
1224
- if (!percent) return;
1225
- const xValue = normalizedValue.getChannelPercentValue(xChannel, percent.x);
1226
- const yValue = normalizedValue.getChannelPercentValue(yChannel, 1 - percent.y);
1227
- const color = normalizedValue.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
1228
- set.value(ctx2, color);
1011
+ "AREA.FOCUS": {
1012
+ actions: ["setActiveChannel"]
1229
1013
  },
1230
- setChannelColorFromPoint(ctx2, evt) {
1231
- const channel = evt.channel || ctx2.activeId;
1232
- const normalizedValue = evt.format ? ctx2.value.toFormat(evt.format) : ctx2.areaValue;
1233
- const percent = dom.getChannelSliderValueFromPoint(ctx2, evt.point, channel);
1234
- if (!percent) return;
1235
- const orientation = ctx2.activeOrientation || "horizontal";
1236
- const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
1237
- const value = normalizedValue.getChannelPercentValue(channel, channelPercent);
1238
- const color = normalizedValue.withChannelValue(channel, value);
1239
- set.value(ctx2, color);
1014
+ "CHANNEL_SLIDER.POINTER_DOWN": {
1015
+ target: "open:dragging",
1016
+ actions: ["setActiveChannel", "setChannelColorFromPoint", "focusChannelThumb"]
1240
1017
  },
1241
- setValue(ctx2, evt) {
1242
- set.value(ctx2, evt.value);
1018
+ "CHANNEL_SLIDER.FOCUS": {
1019
+ actions: ["setActiveChannel"]
1243
1020
  },
1244
- setFormat(ctx2, evt) {
1245
- set.format(ctx2, evt.format);
1021
+ "AREA.ARROW_LEFT": {
1022
+ actions: ["decrementAreaXChannel"]
1246
1023
  },
1247
- syncInputElements(ctx2) {
1248
- sync.inputs(ctx2);
1024
+ "AREA.ARROW_RIGHT": {
1025
+ actions: ["incrementAreaXChannel"]
1249
1026
  },
1250
- invokeOnChangeEnd(ctx2) {
1251
- invoke.changeEnd(ctx2);
1027
+ "AREA.ARROW_UP": {
1028
+ actions: ["incrementAreaYChannel"]
1252
1029
  },
1253
- setChannelColorFromInput(ctx2, evt) {
1254
- const { channel, isTextField, value } = evt;
1255
- const currentAlpha = ctx2.value.getChannelValue("alpha");
1256
- let color;
1257
- if (channel === "alpha") {
1258
- let valueAsNumber = parseFloat(value);
1259
- valueAsNumber = Number.isNaN(valueAsNumber) ? currentAlpha : valueAsNumber;
1260
- color = ctx2.value.withChannelValue("alpha", valueAsNumber);
1261
- } else if (isTextField) {
1262
- color = tryCatch(
1263
- () => parse(value).withChannelValue("alpha", currentAlpha),
1264
- () => ctx2.value
1265
- );
1266
- } else {
1267
- const current = ctx2.value.toFormat(ctx2.format);
1268
- const valueAsNumber = Number.isNaN(value) ? current.getChannelValue(channel) : value;
1269
- color = current.withChannelValue(channel, valueAsNumber);
1270
- }
1271
- sync.inputs(ctx2, color);
1272
- set.value(ctx2, color);
1030
+ "AREA.ARROW_DOWN": {
1031
+ actions: ["decrementAreaYChannel"]
1273
1032
  },
1274
- incrementChannel(ctx2, evt) {
1275
- const color = ctx2.value.incrementChannel(evt.channel, evt.step);
1276
- set.value(ctx2, color);
1033
+ "AREA.PAGE_UP": {
1034
+ actions: ["incrementAreaXChannel"]
1277
1035
  },
1278
- decrementChannel(ctx2, evt) {
1279
- const color = ctx2.value.decrementChannel(evt.channel, evt.step);
1280
- set.value(ctx2, color);
1036
+ "AREA.PAGE_DOWN": {
1037
+ actions: ["decrementAreaXChannel"]
1281
1038
  },
1282
- incrementAreaXChannel(ctx2, evt) {
1283
- const { xChannel } = evt.channel;
1284
- const color = ctx2.areaValue.incrementChannel(xChannel, evt.step);
1285
- set.value(ctx2, color);
1039
+ "CHANNEL_SLIDER.ARROW_LEFT": {
1040
+ actions: ["decrementChannel"]
1286
1041
  },
1287
- decrementAreaXChannel(ctx2, evt) {
1288
- const { xChannel } = evt.channel;
1289
- const color = ctx2.areaValue.decrementChannel(xChannel, evt.step);
1290
- set.value(ctx2, color);
1042
+ "CHANNEL_SLIDER.ARROW_RIGHT": {
1043
+ actions: ["incrementChannel"]
1291
1044
  },
1292
- incrementAreaYChannel(ctx2, evt) {
1293
- const { yChannel } = evt.channel;
1294
- const color = ctx2.areaValue.incrementChannel(yChannel, evt.step);
1295
- set.value(ctx2, color);
1045
+ "CHANNEL_SLIDER.ARROW_UP": {
1046
+ actions: ["incrementChannel"]
1296
1047
  },
1297
- decrementAreaYChannel(ctx2, evt) {
1298
- const { yChannel } = evt.channel;
1299
- const color = ctx2.areaValue.decrementChannel(yChannel, evt.step);
1300
- set.value(ctx2, color);
1048
+ "CHANNEL_SLIDER.ARROW_DOWN": {
1049
+ actions: ["decrementChannel"]
1301
1050
  },
1302
- setChannelToMax(ctx2, evt) {
1303
- const range = ctx2.value.getChannelRange(evt.channel);
1304
- const color = ctx2.value.withChannelValue(evt.channel, range.maxValue);
1305
- set.value(ctx2, color);
1051
+ "CHANNEL_SLIDER.PAGE_UP": {
1052
+ actions: ["incrementChannel"]
1306
1053
  },
1307
- setChannelToMin(ctx2, evt) {
1308
- const range = ctx2.value.getChannelRange(evt.channel);
1309
- const color = ctx2.value.withChannelValue(evt.channel, range.minValue);
1310
- set.value(ctx2, color);
1054
+ "CHANNEL_SLIDER.PAGE_DOWN": {
1055
+ actions: ["decrementChannel"]
1311
1056
  },
1312
- focusAreaThumb(ctx2) {
1313
- raf(() => {
1314
- dom.getAreaThumbEl(ctx2)?.focus({ preventScroll: true });
1315
- });
1057
+ "CHANNEL_SLIDER.HOME": {
1058
+ actions: ["setChannelToMin"]
1316
1059
  },
1317
- focusChannelThumb(ctx2, evt) {
1318
- raf(() => {
1319
- dom.getChannelSliderThumbEl(ctx2, evt.channel)?.focus({ preventScroll: true });
1320
- });
1060
+ "CHANNEL_SLIDER.END": {
1061
+ actions: ["setChannelToMax"]
1321
1062
  },
1322
- setInitialFocus(ctx2) {
1323
- if (!ctx2.openAutoFocus) return;
1324
- raf(() => {
1325
- const element = getInitialFocus({
1326
- root: dom.getContentEl(ctx2),
1327
- getInitialEl: ctx2.initialFocusEl
1328
- });
1329
- element?.focus({ preventScroll: true });
1330
- });
1063
+ "CHANNEL_INPUT.BLUR": {
1064
+ actions: ["setChannelColorFromInput"]
1331
1065
  },
1332
- setReturnFocus(ctx2) {
1333
- raf(() => {
1334
- dom.getTriggerEl(ctx2)?.focus({ preventScroll: true });
1335
- });
1066
+ INTERACT_OUTSIDE: [
1067
+ {
1068
+ guard: "isOpenControlled",
1069
+ actions: ["invokeOnClose"]
1070
+ },
1071
+ {
1072
+ guard: "shouldRestoreFocus",
1073
+ target: "focused",
1074
+ actions: ["invokeOnClose", "setReturnFocus"]
1075
+ },
1076
+ {
1077
+ target: "idle",
1078
+ actions: ["invokeOnClose"]
1079
+ }
1080
+ ],
1081
+ CLOSE: [
1082
+ {
1083
+ guard: "isOpenControlled",
1084
+ actions: ["invokeOnClose"]
1085
+ },
1086
+ {
1087
+ target: "idle",
1088
+ actions: ["invokeOnClose"]
1089
+ }
1090
+ ],
1091
+ "SWATCH_TRIGGER.CLICK": [
1092
+ {
1093
+ guard: and("isOpenControlled", "closeOnSelect"),
1094
+ actions: ["setValue", "invokeOnClose"]
1095
+ },
1096
+ {
1097
+ guard: "closeOnSelect",
1098
+ target: "focused",
1099
+ actions: ["setValue", "invokeOnClose", "setReturnFocus"]
1100
+ },
1101
+ {
1102
+ actions: ["setValue"]
1103
+ }
1104
+ ]
1105
+ }
1106
+ },
1107
+ "open:dragging": {
1108
+ tags: ["open"],
1109
+ exit: ["clearActiveChannel"],
1110
+ effects: ["trackPointerMove", "disableTextSelection", "trackPositioning", "trackDismissableElement"],
1111
+ on: {
1112
+ "CONTROLLED.CLOSE": [
1113
+ {
1114
+ guard: "shouldRestoreFocus",
1115
+ target: "focused",
1116
+ actions: ["setReturnFocus"]
1117
+ },
1118
+ {
1119
+ target: "idle"
1120
+ }
1121
+ ],
1122
+ "AREA.POINTER_MOVE": {
1123
+ actions: ["setAreaColorFromPoint", "focusAreaThumb"]
1336
1124
  },
1337
- syncFormatSelectElement(ctx2) {
1338
- sync.formatSelect(ctx2);
1125
+ "AREA.POINTER_UP": {
1126
+ target: "open",
1127
+ actions: ["invokeOnChangeEnd"]
1339
1128
  },
1340
- invokeOnOpen(ctx2) {
1341
- ctx2.onOpenChange?.({ open: true });
1129
+ "CHANNEL_SLIDER.POINTER_MOVE": {
1130
+ actions: ["setChannelColorFromPoint", "focusChannelThumb"]
1342
1131
  },
1343
- invokeOnClose(ctx2) {
1344
- ctx2.onOpenChange?.({ open: false });
1132
+ "CHANNEL_SLIDER.POINTER_UP": {
1133
+ target: "open",
1134
+ actions: ["invokeOnChangeEnd"]
1345
1135
  },
1346
- toggleVisibility(ctx2, evt, { send }) {
1347
- send({ type: ctx2.open ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: evt });
1136
+ INTERACT_OUTSIDE: [
1137
+ {
1138
+ guard: "isOpenControlled",
1139
+ actions: ["invokeOnClose"]
1140
+ },
1141
+ {
1142
+ guard: "shouldRestoreFocus",
1143
+ target: "focused",
1144
+ actions: ["invokeOnClose", "setReturnFocus"]
1145
+ },
1146
+ {
1147
+ target: "idle",
1148
+ actions: ["invokeOnClose"]
1149
+ }
1150
+ ],
1151
+ CLOSE: [
1152
+ {
1153
+ guard: "isOpenControlled",
1154
+ actions: ["invokeOnClose"]
1155
+ },
1156
+ {
1157
+ target: "idle",
1158
+ actions: ["invokeOnClose"]
1159
+ }
1160
+ ]
1161
+ }
1162
+ }
1163
+ },
1164
+ implementations: {
1165
+ guards: {
1166
+ closeOnSelect: ({ prop }) => !!prop("closeOnSelect"),
1167
+ isOpenControlled: ({ prop }) => prop("open") != null,
1168
+ shouldRestoreFocus: ({ context }) => !!context.get("restoreFocus")
1169
+ },
1170
+ effects: {
1171
+ trackPositioning({ context, prop, scope }) {
1172
+ if (!context.get("currentPlacement")) {
1173
+ context.set("currentPlacement", prop("positioning")?.placement);
1174
+ }
1175
+ const anchorEl = getTriggerEl(scope);
1176
+ const getPositionerEl2 = () => getPositionerEl(scope);
1177
+ return getPlacement(anchorEl, getPositionerEl2, {
1178
+ ...prop("positioning"),
1179
+ defer: true,
1180
+ onComplete(data) {
1181
+ context.set("currentPlacement", data.placement);
1182
+ }
1183
+ });
1184
+ },
1185
+ trackDismissableElement({ context, scope, prop, send }) {
1186
+ const getContentEl2 = () => getContentEl(scope);
1187
+ return trackDismissableElement(getContentEl2, {
1188
+ exclude: getTriggerEl(scope),
1189
+ defer: true,
1190
+ onInteractOutside(event) {
1191
+ prop("onInteractOutside")?.(event);
1192
+ if (event.defaultPrevented) return;
1193
+ context.set("restoreFocus", !(event.detail.focusable || event.detail.contextmenu));
1194
+ },
1195
+ onPointerDownOutside: prop("onPointerDownOutside"),
1196
+ onFocusOutside: prop("onFocusOutside"),
1197
+ onDismiss() {
1198
+ send({ type: "INTERACT_OUTSIDE" });
1199
+ }
1200
+ });
1201
+ },
1202
+ trackFormControl({ context, scope, send }) {
1203
+ const inputEl = getHiddenInputEl(scope);
1204
+ return trackFormControl(inputEl, {
1205
+ onFieldsetDisabledChange(disabled) {
1206
+ context.set("fieldsetDisabled", disabled);
1207
+ },
1208
+ onFormReset() {
1209
+ send({ type: "VALUE.SET", value: context.initial("value"), src: "form.reset" });
1210
+ }
1211
+ });
1212
+ },
1213
+ trackPointerMove({ context, scope, event, send }) {
1214
+ return trackPointerMove(scope.getDoc(), {
1215
+ onPointerMove({ point }) {
1216
+ const type = context.get("activeId") === "area" ? "AREA.POINTER_MOVE" : "CHANNEL_SLIDER.POINTER_MOVE";
1217
+ send({ type, point, format: event.format });
1218
+ },
1219
+ onPointerUp() {
1220
+ const type = context.get("activeId") === "area" ? "AREA.POINTER_UP" : "CHANNEL_SLIDER.POINTER_UP";
1221
+ send({ type });
1222
+ }
1223
+ });
1224
+ },
1225
+ disableTextSelection({ scope }) {
1226
+ return disableTextSelection({
1227
+ doc: scope.getDoc(),
1228
+ target: getContentEl(scope)
1229
+ });
1230
+ }
1231
+ },
1232
+ actions: {
1233
+ openEyeDropper({ scope, context }) {
1234
+ const win = scope.getWin();
1235
+ const isSupported = "EyeDropper" in win;
1236
+ if (!isSupported) return;
1237
+ const picker = new win.EyeDropper();
1238
+ picker.open().then(({ sRGBHex }) => {
1239
+ const format = context.get("value").getFormat();
1240
+ const color = parseColor(sRGBHex).toFormat(format);
1241
+ context.set("value", color);
1242
+ }).catch(() => void 0);
1243
+ },
1244
+ setActiveChannel({ context, event }) {
1245
+ context.set("activeId", event.id);
1246
+ if (event.channel) context.set("activeChannel", event.channel);
1247
+ if (event.orientation) context.set("activeOrientation", event.orientation);
1248
+ },
1249
+ clearActiveChannel({ context }) {
1250
+ context.set("activeChannel", null);
1251
+ context.set("activeId", null);
1252
+ context.set("activeOrientation", null);
1253
+ },
1254
+ setAreaColorFromPoint({ context, event, computed, scope }) {
1255
+ const v = event.format ? context.get("value").toFormat(event.format) : computed("areaValue");
1256
+ const { xChannel, yChannel } = event.channel || context.get("activeChannel");
1257
+ const percent = getAreaValueFromPoint(scope, event.point);
1258
+ if (!percent) return;
1259
+ const xValue = v.getChannelPercentValue(xChannel, percent.x);
1260
+ const yValue = v.getChannelPercentValue(yChannel, 1 - percent.y);
1261
+ const color = v.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
1262
+ context.set("value", color);
1263
+ },
1264
+ setChannelColorFromPoint({ context, event, computed, scope }) {
1265
+ const channel = event.channel || context.get("activeId");
1266
+ const normalizedValue = event.format ? context.get("value").toFormat(event.format) : computed("areaValue");
1267
+ const percent = getChannelSliderValueFromPoint(scope, event.point, channel);
1268
+ if (!percent) return;
1269
+ const orientation = context.get("activeOrientation") || "horizontal";
1270
+ const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
1271
+ const value = normalizedValue.getChannelPercentValue(channel, channelPercent);
1272
+ const color = normalizedValue.withChannelValue(channel, value);
1273
+ context.set("value", color);
1274
+ },
1275
+ setValue({ context, event }) {
1276
+ context.set("value", event.value);
1277
+ },
1278
+ setFormat({ context, event }) {
1279
+ context.set("format", event.format);
1280
+ },
1281
+ syncInputElements({ context, scope }) {
1282
+ syncInputs(scope, context.get("value"));
1283
+ },
1284
+ invokeOnChangeEnd({ context, prop, computed }) {
1285
+ prop("onValueChangeEnd")?.({
1286
+ value: context.get("value"),
1287
+ valueAsString: computed("valueAsString")
1288
+ });
1289
+ },
1290
+ setChannelColorFromInput({ context, event, scope }) {
1291
+ const { channel, isTextField, value } = event;
1292
+ const currentAlpha = context.get("value").getChannelValue("alpha");
1293
+ let color;
1294
+ if (channel === "alpha") {
1295
+ let valueAsNumber = parseFloat(value);
1296
+ valueAsNumber = Number.isNaN(valueAsNumber) ? currentAlpha : valueAsNumber;
1297
+ color = context.get("value").withChannelValue("alpha", valueAsNumber);
1298
+ } else if (isTextField) {
1299
+ color = tryCatch(
1300
+ () => parse(value).withChannelValue("alpha", currentAlpha),
1301
+ () => context.get("value")
1302
+ );
1303
+ } else {
1304
+ const current = context.get("value").toFormat(context.get("format"));
1305
+ const valueAsNumber = Number.isNaN(value) ? current.getChannelValue(channel) : value;
1306
+ color = current.withChannelValue(channel, valueAsNumber);
1348
1307
  }
1308
+ syncInputs(scope, context.get("value"), color);
1309
+ context.set("value", color);
1310
+ },
1311
+ incrementChannel({ context, event }) {
1312
+ const color = context.get("value").incrementChannel(event.channel, event.step);
1313
+ context.set("value", color);
1314
+ },
1315
+ decrementChannel({ context, event }) {
1316
+ const color = context.get("value").decrementChannel(event.channel, event.step);
1317
+ context.set("value", color);
1318
+ },
1319
+ incrementAreaXChannel({ context, event, computed }) {
1320
+ const { xChannel } = event.channel;
1321
+ const color = computed("areaValue").incrementChannel(xChannel, event.step);
1322
+ context.set("value", color);
1323
+ },
1324
+ decrementAreaXChannel({ context, event, computed }) {
1325
+ const { xChannel } = event.channel;
1326
+ const color = computed("areaValue").decrementChannel(xChannel, event.step);
1327
+ context.set("value", color);
1328
+ },
1329
+ incrementAreaYChannel({ context, event, computed }) {
1330
+ const { yChannel } = event.channel;
1331
+ const color = computed("areaValue").incrementChannel(yChannel, event.step);
1332
+ context.set("value", color);
1333
+ },
1334
+ decrementAreaYChannel({ context, event, computed }) {
1335
+ const { yChannel } = event.channel;
1336
+ const color = computed("areaValue").decrementChannel(yChannel, event.step);
1337
+ context.set("value", color);
1338
+ },
1339
+ setChannelToMax({ context, event }) {
1340
+ const value = context.get("value");
1341
+ const range = value.getChannelRange(event.channel);
1342
+ const color = value.withChannelValue(event.channel, range.maxValue);
1343
+ context.set("value", color);
1344
+ },
1345
+ setChannelToMin({ context, event }) {
1346
+ const value = context.get("value");
1347
+ const range = value.getChannelRange(event.channel);
1348
+ const color = value.withChannelValue(event.channel, range.minValue);
1349
+ context.set("value", color);
1350
+ },
1351
+ focusAreaThumb({ scope }) {
1352
+ raf(() => {
1353
+ getAreaThumbEl(scope)?.focus({ preventScroll: true });
1354
+ });
1355
+ },
1356
+ focusChannelThumb({ event, scope }) {
1357
+ raf(() => {
1358
+ getChannelSliderThumbEl(scope, event.channel)?.focus({ preventScroll: true });
1359
+ });
1360
+ },
1361
+ setInitialFocus({ prop, scope }) {
1362
+ if (!prop("openAutoFocus")) return;
1363
+ raf(() => {
1364
+ const element = getInitialFocus({
1365
+ root: getContentEl(scope),
1366
+ getInitialEl: prop("initialFocusEl")
1367
+ });
1368
+ element?.focus({ preventScroll: true });
1369
+ });
1370
+ },
1371
+ setReturnFocus({ scope }) {
1372
+ raf(() => {
1373
+ getTriggerEl(scope)?.focus({ preventScroll: true });
1374
+ });
1375
+ },
1376
+ syncFormatSelectElement({ context, scope }) {
1377
+ syncFormatSelect(scope, context.get("format"));
1349
1378
  },
1350
- compareFns: {
1351
- value: (a, b) => a.isEqual(b)
1379
+ invokeOnOpen({ prop }) {
1380
+ prop("onOpenChange")?.({ open: true });
1381
+ },
1382
+ invokeOnClose({ prop }) {
1383
+ prop("onOpenChange")?.({ open: false });
1384
+ },
1385
+ toggleVisibility({ prop, event, send }) {
1386
+ send({ type: prop("open") ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE", previousEvent: event });
1352
1387
  }
1353
1388
  }
1354
- );
1355
- }
1356
- var sync = {
1357
- // sync channel inputs
1358
- inputs(ctx, color) {
1359
- const channelInputs = dom.getChannelInputEls(ctx);
1360
- raf(() => {
1361
- channelInputs.forEach((inputEl) => {
1362
- const channel = inputEl.dataset.channel;
1363
- dom.setValue(inputEl, getChannelValue(color || ctx.value, channel));
1364
- });
1365
- });
1366
- },
1367
- // sync format select
1368
- formatSelect(ctx) {
1369
- const selectEl = dom.getFormatSelectEl(ctx);
1370
- raf(() => {
1371
- dom.setValue(selectEl, ctx.format);
1372
- });
1373
1389
  }
1374
- };
1375
- var invoke = {
1376
- changeEnd(ctx) {
1377
- const value = ctx.value.toFormat(ctx.format);
1378
- ctx.onValueChangeEnd?.({
1379
- value,
1380
- valueAsString: ctx.valueAsString
1381
- });
1382
- },
1383
- change(ctx) {
1384
- const value = ctx.value.toFormat(ctx.format);
1385
- ctx.onValueChange?.({
1386
- value,
1387
- valueAsString: ctx.valueAsString
1390
+ });
1391
+ function syncInputs(scope, currentValue, nextValue) {
1392
+ const channelInputEls = getChannelInputEls(scope);
1393
+ raf(() => {
1394
+ channelInputEls.forEach((inputEl) => {
1395
+ const channel = inputEl.dataset.channel;
1396
+ setElementValue(inputEl, getChannelValue(nextValue || currentValue, channel));
1388
1397
  });
1389
- dispatchInputValueEvent(dom.getHiddenInputEl(ctx), { value: ctx.valueAsString });
1390
- },
1391
- formatChange(ctx) {
1392
- ctx.onFormatChange?.({ format: ctx.format });
1393
- }
1394
- };
1395
- var set = {
1396
- value(ctx, color) {
1397
- if (!color || ctx.value.isEqual(color)) return;
1398
- ctx.value = color;
1399
- invoke.change(ctx);
1400
- },
1401
- format(ctx, format) {
1402
- if (ctx.format === format) return;
1403
- ctx.format = format;
1404
- invoke.formatChange(ctx);
1405
- }
1406
- };
1398
+ });
1399
+ }
1400
+ function syncFormatSelect(scope, format) {
1401
+ const selectEl = getFormatSelectEl(scope);
1402
+ if (!selectEl) return;
1403
+ raf(() => setElementValue(selectEl, format));
1404
+ }
1405
+ var props = createProps()([
1406
+ "closeOnSelect",
1407
+ "dir",
1408
+ "disabled",
1409
+ "format",
1410
+ "defaultFormat",
1411
+ "getRootNode",
1412
+ "id",
1413
+ "ids",
1414
+ "initialFocusEl",
1415
+ "name",
1416
+ "positioning",
1417
+ "onFocusOutside",
1418
+ "onFormatChange",
1419
+ "onInteractOutside",
1420
+ "onOpenChange",
1421
+ "onPointerDownOutside",
1422
+ "onValueChange",
1423
+ "onValueChangeEnd",
1424
+ "defaultOpen",
1425
+ "open",
1426
+ "positioning",
1427
+ "required",
1428
+ "readOnly",
1429
+ "value",
1430
+ "defaultValue",
1431
+ "invalid",
1432
+ "openAutoFocus"
1433
+ ]);
1434
+ var splitProps = createSplitProps(props);
1435
+ var areaProps = createProps()(["xChannel", "yChannel"]);
1436
+ var splitAreaProps = createSplitProps(areaProps);
1437
+ var channelProps = createProps()(["channel", "orientation"]);
1438
+ var splitChannelProps = createSplitProps(channelProps);
1439
+ var swatchTriggerProps = createProps()(["value", "disabled"]);
1440
+ var splitSwatchTriggerProps = createSplitProps(swatchTriggerProps);
1441
+ var swatchProps = createProps()(["value", "respectAlpha"]);
1442
+ var splitSwatchProps = createSplitProps(swatchProps);
1443
+ var transparencyGridProps = createProps()(["size"]);
1444
+ var splitTransparencyGridProps = createSplitProps(transparencyGridProps);
1407
1445
 
1408
- export { anatomy, connect, machine, parse };
1446
+ export { anatomy, areaProps, channelProps, connect, machine, parse, props, splitAreaProps, splitChannelProps, splitProps, splitSwatchProps, splitSwatchTriggerProps, splitTransparencyGridProps, swatchProps, swatchTriggerProps, transparencyGridProps };