@zag-js/color-picker 0.46.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +20 -10
- package/dist/index.d.ts +20 -10
- package/dist/index.js +65 -61
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +66 -62
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -14
- package/src/color-picker.connect.ts +63 -62
- package/src/color-picker.machine.ts +2 -2
- package/src/color-picker.types.ts +20 -10
|
@@ -5,13 +5,12 @@ import {
|
|
|
5
5
|
getEventStep,
|
|
6
6
|
getNativeEvent,
|
|
7
7
|
isLeftClick,
|
|
8
|
-
|
|
8
|
+
isModifierKey,
|
|
9
9
|
type EventKeyMap,
|
|
10
10
|
} from "@zag-js/dom-event"
|
|
11
|
-
import { dataAttr, query } from "@zag-js/dom-query"
|
|
11
|
+
import { dataAttr, query, visuallyHiddenStyle } from "@zag-js/dom-query"
|
|
12
12
|
import { getPlacementStyles } from "@zag-js/popper"
|
|
13
13
|
import type { NormalizeProps, PropTypes } from "@zag-js/types"
|
|
14
|
-
import { visuallyHiddenStyle } from "@zag-js/visually-hidden"
|
|
15
14
|
import { parts } from "./color-picker.anatomy"
|
|
16
15
|
import { dom } from "./color-picker.dom"
|
|
17
16
|
import type {
|
|
@@ -32,12 +31,12 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
32
31
|
const areaValue = state.context.areaValue
|
|
33
32
|
const valueAsString = state.context.valueAsString
|
|
34
33
|
|
|
35
|
-
const
|
|
36
|
-
const
|
|
34
|
+
const disabled = state.context.isDisabled
|
|
35
|
+
const interactive = state.context.isInteractive
|
|
37
36
|
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
37
|
+
const dragging = state.hasTag("dragging")
|
|
38
|
+
const open = state.hasTag("open")
|
|
39
|
+
const focused = state.hasTag("focused")
|
|
41
40
|
|
|
42
41
|
const getAreaChannels = (props: AreaProps) => {
|
|
43
42
|
const channels = areaValue.getChannels()
|
|
@@ -58,21 +57,19 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
58
57
|
return {
|
|
59
58
|
value: color,
|
|
60
59
|
valueAsString: color.toString("hex"),
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
checked: color.isEqual(value),
|
|
61
|
+
disabled: props.disabled || !interactive,
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
return {
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
dragging,
|
|
67
|
+
open,
|
|
69
68
|
valueAsString,
|
|
70
69
|
value,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
close() {
|
|
75
|
-
send({ type: "CLOSE" })
|
|
70
|
+
setOpen(_open) {
|
|
71
|
+
if (_open === open) return
|
|
72
|
+
send({ type: _open ? "OPEN" : "CLOSE" })
|
|
76
73
|
},
|
|
77
74
|
setValue(value) {
|
|
78
75
|
send({ type: "VALUE.SET", value: normalizeColor(value), src: "set-color" })
|
|
@@ -99,7 +96,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
99
96
|
...parts.root.attrs,
|
|
100
97
|
dir: state.context.dir,
|
|
101
98
|
id: dom.getRootId(state.context),
|
|
102
|
-
"data-disabled": dataAttr(
|
|
99
|
+
"data-disabled": dataAttr(disabled),
|
|
103
100
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
104
101
|
style: {
|
|
105
102
|
"--value": value.toString("css"),
|
|
@@ -111,9 +108,9 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
111
108
|
dir: state.context.dir,
|
|
112
109
|
id: dom.getLabelId(state.context),
|
|
113
110
|
htmlFor: dom.getHiddenInputId(state.context),
|
|
114
|
-
"data-disabled": dataAttr(
|
|
111
|
+
"data-disabled": dataAttr(disabled),
|
|
115
112
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
116
|
-
"data-focus": dataAttr(
|
|
113
|
+
"data-focus": dataAttr(focused),
|
|
117
114
|
onClick(event) {
|
|
118
115
|
event.preventDefault()
|
|
119
116
|
const inputEl = query(dom.getControlEl(state.context), "[data-channel=hex]")
|
|
@@ -125,33 +122,33 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
125
122
|
...parts.control.attrs,
|
|
126
123
|
id: dom.getControlId(state.context),
|
|
127
124
|
dir: state.context.dir,
|
|
128
|
-
"data-disabled": dataAttr(
|
|
125
|
+
"data-disabled": dataAttr(disabled),
|
|
129
126
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
130
|
-
"data-state":
|
|
131
|
-
"data-focus": dataAttr(
|
|
127
|
+
"data-state": open ? "open" : "closed",
|
|
128
|
+
"data-focus": dataAttr(focused),
|
|
132
129
|
}),
|
|
133
130
|
|
|
134
131
|
triggerProps: normalize.button({
|
|
135
132
|
...parts.trigger.attrs,
|
|
136
133
|
id: dom.getTriggerId(state.context),
|
|
137
134
|
dir: state.context.dir,
|
|
138
|
-
disabled:
|
|
135
|
+
disabled: disabled,
|
|
139
136
|
"aria-label": `select color. current color is ${valueAsString}`,
|
|
140
137
|
"aria-controls": dom.getContentId(state.context),
|
|
141
138
|
"aria-labelledby": dom.getLabelId(state.context),
|
|
142
|
-
"data-disabled": dataAttr(
|
|
139
|
+
"data-disabled": dataAttr(disabled),
|
|
143
140
|
"data-readonly": dataAttr(state.context.readOnly),
|
|
144
141
|
"data-placement": currentPlacement,
|
|
145
|
-
"aria-expanded": dataAttr(
|
|
146
|
-
"data-state":
|
|
147
|
-
"data-focus": dataAttr(
|
|
142
|
+
"aria-expanded": dataAttr(open),
|
|
143
|
+
"data-state": open ? "open" : "closed",
|
|
144
|
+
"data-focus": dataAttr(focused),
|
|
148
145
|
type: "button",
|
|
149
146
|
onClick() {
|
|
150
|
-
if (!
|
|
147
|
+
if (!interactive) return
|
|
151
148
|
send({ type: "TRIGGER.CLICK" })
|
|
152
149
|
},
|
|
153
150
|
onBlur() {
|
|
154
|
-
if (!
|
|
151
|
+
if (!interactive) return
|
|
155
152
|
send({ type: "TRIGGER.BLUR" })
|
|
156
153
|
},
|
|
157
154
|
style: {
|
|
@@ -171,8 +168,8 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
171
168
|
id: dom.getContentId(state.context),
|
|
172
169
|
dir: state.context.dir,
|
|
173
170
|
"data-placement": currentPlacement,
|
|
174
|
-
"data-state":
|
|
175
|
-
hidden: !
|
|
171
|
+
"data-state": open ? "open" : "closed",
|
|
172
|
+
hidden: !open,
|
|
176
173
|
}),
|
|
177
174
|
|
|
178
175
|
getAreaProps(props = {}) {
|
|
@@ -188,10 +185,10 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
188
185
|
id: dom.getAreaId(state.context),
|
|
189
186
|
role: "group",
|
|
190
187
|
onPointerDown(event) {
|
|
191
|
-
if (!
|
|
188
|
+
if (!interactive) return
|
|
192
189
|
|
|
193
190
|
const evt = getNativeEvent(event)
|
|
194
|
-
if (!isLeftClick(evt) ||
|
|
191
|
+
if (!isLeftClick(evt) || isModifierKey(evt)) return
|
|
195
192
|
|
|
196
193
|
const point = getEventPoint(evt)
|
|
197
194
|
const channel = { xChannel, yChannel }
|
|
@@ -242,8 +239,8 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
242
239
|
...parts.areaThumb.attrs,
|
|
243
240
|
id: dom.getAreaThumbId(state.context),
|
|
244
241
|
dir: state.context.dir,
|
|
245
|
-
tabIndex:
|
|
246
|
-
"data-disabled": dataAttr(
|
|
242
|
+
tabIndex: disabled ? undefined : 0,
|
|
243
|
+
"data-disabled": dataAttr(disabled),
|
|
247
244
|
role: "slider",
|
|
248
245
|
"aria-valuemin": 0,
|
|
249
246
|
"aria-valuemax": 100,
|
|
@@ -261,11 +258,12 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
261
258
|
background: areaValue.withChannelValue("alpha", 1).toString("css"),
|
|
262
259
|
},
|
|
263
260
|
onFocus() {
|
|
264
|
-
if (!
|
|
261
|
+
if (!interactive) return
|
|
265
262
|
send({ type: "AREA.FOCUS", id: "area", channel })
|
|
266
263
|
},
|
|
267
264
|
onKeyDown(event) {
|
|
268
|
-
if (
|
|
265
|
+
if (event.defaultPrevented) return
|
|
266
|
+
if (!interactive) return
|
|
269
267
|
|
|
270
268
|
const step = getEventStep(event)
|
|
271
269
|
|
|
@@ -330,10 +328,10 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
330
328
|
"data-orientation": orientation,
|
|
331
329
|
role: "presentation",
|
|
332
330
|
onPointerDown(event) {
|
|
333
|
-
if (!
|
|
331
|
+
if (!interactive) return
|
|
334
332
|
|
|
335
333
|
const evt = getNativeEvent(event)
|
|
336
|
-
if (!isLeftClick(evt) ||
|
|
334
|
+
if (!isLeftClick(evt) || isModifierKey(evt)) return
|
|
337
335
|
|
|
338
336
|
const point = getEventPoint(evt)
|
|
339
337
|
send({ type: "CHANNEL_SLIDER.POINTER_DOWN", channel, point, id: channel, orientation })
|
|
@@ -386,11 +384,11 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
386
384
|
id: dom.getChannelSliderThumbId(state.context, channel),
|
|
387
385
|
role: "slider",
|
|
388
386
|
"aria-label": channel,
|
|
389
|
-
tabIndex:
|
|
387
|
+
tabIndex: disabled ? undefined : 0,
|
|
390
388
|
"data-channel": channel,
|
|
391
|
-
"data-disabled": dataAttr(
|
|
389
|
+
"data-disabled": dataAttr(disabled),
|
|
392
390
|
"data-orientation": orientation,
|
|
393
|
-
"aria-disabled": dataAttr(
|
|
391
|
+
"aria-disabled": dataAttr(disabled),
|
|
394
392
|
"aria-orientation": orientation,
|
|
395
393
|
"aria-valuemax": maxValue,
|
|
396
394
|
"aria-valuemin": minValue,
|
|
@@ -403,11 +401,13 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
403
401
|
...placementStyles,
|
|
404
402
|
},
|
|
405
403
|
onFocus() {
|
|
406
|
-
if (!
|
|
404
|
+
if (!interactive) return
|
|
407
405
|
send({ type: "CHANNEL_SLIDER.FOCUS", channel })
|
|
408
406
|
},
|
|
409
407
|
onKeyDown(event) {
|
|
410
|
-
if (
|
|
408
|
+
if (event.defaultPrevented) return
|
|
409
|
+
if (!interactive) return
|
|
410
|
+
|
|
411
411
|
const step = getEventStep(event) * stepValue
|
|
412
412
|
|
|
413
413
|
const keyMap: EventKeyMap = {
|
|
@@ -463,32 +463,33 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
463
463
|
"aria-label": channel,
|
|
464
464
|
spellCheck: false,
|
|
465
465
|
autoComplete: "off",
|
|
466
|
-
disabled:
|
|
467
|
-
"data-disabled": dataAttr(
|
|
466
|
+
disabled: disabled,
|
|
467
|
+
"data-disabled": dataAttr(disabled),
|
|
468
468
|
readOnly: state.context.readOnly,
|
|
469
469
|
defaultValue: getChannelValue(value, channel),
|
|
470
470
|
min: range?.minValue,
|
|
471
471
|
max: range?.maxValue,
|
|
472
472
|
step: range?.step,
|
|
473
473
|
onBeforeInput(event) {
|
|
474
|
-
if (isTextField || !
|
|
474
|
+
if (isTextField || !interactive) return
|
|
475
475
|
const value = event.currentTarget.value
|
|
476
476
|
if (value.match(/[^0-9.]/g)) {
|
|
477
477
|
event.preventDefault()
|
|
478
478
|
}
|
|
479
479
|
},
|
|
480
480
|
onFocus(event) {
|
|
481
|
-
if (!
|
|
481
|
+
if (!interactive) return
|
|
482
482
|
send({ type: "CHANNEL_INPUT.FOCUS", channel })
|
|
483
483
|
event.target.select()
|
|
484
484
|
},
|
|
485
485
|
onBlur(event) {
|
|
486
|
-
if (!
|
|
486
|
+
if (!interactive) return
|
|
487
487
|
const value = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber
|
|
488
488
|
send({ type: "CHANNEL_INPUT.BLUR", channel, value, isTextField })
|
|
489
489
|
},
|
|
490
490
|
onKeyDown(event) {
|
|
491
|
-
if (
|
|
491
|
+
if (event.defaultPrevented) return
|
|
492
|
+
if (!interactive) return
|
|
492
493
|
if (event.key === "Enter") {
|
|
493
494
|
const value = isTextField ? event.currentTarget.value : event.currentTarget.valueAsNumber
|
|
494
495
|
send({ type: "CHANNEL_INPUT.CHANGE", channel, value, isTextField })
|
|
@@ -505,7 +506,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
505
506
|
|
|
506
507
|
hiddenInputProps: normalize.input({
|
|
507
508
|
type: "text",
|
|
508
|
-
disabled:
|
|
509
|
+
disabled: disabled,
|
|
509
510
|
name: state.context.name,
|
|
510
511
|
id: dom.getHiddenInputId(state.context),
|
|
511
512
|
style: visuallyHiddenStyle,
|
|
@@ -516,11 +517,11 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
516
517
|
...parts.eyeDropperTrigger.attrs,
|
|
517
518
|
type: "button",
|
|
518
519
|
dir: state.context.dir,
|
|
519
|
-
disabled:
|
|
520
|
-
"data-disabled": dataAttr(
|
|
520
|
+
disabled: disabled,
|
|
521
|
+
"data-disabled": dataAttr(disabled),
|
|
521
522
|
"aria-label": "Pick a color from the screen",
|
|
522
523
|
onClick() {
|
|
523
|
-
if (!
|
|
524
|
+
if (!interactive) return
|
|
524
525
|
send("EYEDROPPER.CLICK")
|
|
525
526
|
},
|
|
526
527
|
}),
|
|
@@ -536,15 +537,15 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
536
537
|
const triggerState = getSwatchTriggerState(props)
|
|
537
538
|
return normalize.button({
|
|
538
539
|
...parts.swatchTrigger.attrs,
|
|
539
|
-
disabled: triggerState.
|
|
540
|
+
disabled: triggerState.disabled,
|
|
540
541
|
dir: state.context.dir,
|
|
541
542
|
type: "button",
|
|
542
543
|
"aria-label": `select ${triggerState.valueAsString} as the color`,
|
|
543
|
-
"data-state": triggerState.
|
|
544
|
+
"data-state": triggerState.checked ? "checked" : "unchecked",
|
|
544
545
|
"data-value": triggerState.valueAsString,
|
|
545
|
-
"data-disabled": dataAttr(triggerState.
|
|
546
|
+
"data-disabled": dataAttr(triggerState.disabled),
|
|
546
547
|
onClick() {
|
|
547
|
-
if (triggerState.
|
|
548
|
+
if (triggerState.disabled) return
|
|
548
549
|
send({ type: "SWATCH_TRIGGER.CLICK", value: triggerState.value })
|
|
549
550
|
},
|
|
550
551
|
style: {
|
|
@@ -558,7 +559,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
558
559
|
return normalize.element({
|
|
559
560
|
...parts.swatchIndicator.attrs,
|
|
560
561
|
dir: state.context.dir,
|
|
561
|
-
hidden: !triggerState.
|
|
562
|
+
hidden: !triggerState.checked,
|
|
562
563
|
})
|
|
563
564
|
},
|
|
564
565
|
|
|
@@ -568,7 +569,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
568
569
|
return normalize.element({
|
|
569
570
|
...parts.swatch.attrs,
|
|
570
571
|
dir: state.context.dir,
|
|
571
|
-
"data-state": triggerState.
|
|
572
|
+
"data-state": triggerState.checked ? "checked" : "unchecked",
|
|
572
573
|
"data-value": triggerState.valueAsString,
|
|
573
574
|
style: {
|
|
574
575
|
position: "relative",
|
|
@@ -594,7 +595,7 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
|
|
|
594
595
|
"aria-label": "change color format",
|
|
595
596
|
dir: state.context.dir,
|
|
596
597
|
defaultValue: state.context.format,
|
|
597
|
-
disabled:
|
|
598
|
+
disabled: disabled,
|
|
598
599
|
onChange(event) {
|
|
599
600
|
const format = assertFormat(event.currentTarget.value)
|
|
600
601
|
send({ type: "FORMAT.SET", format, src: "format-select" })
|
|
@@ -404,11 +404,11 @@ export function machine(userContext: UserDefinedContext) {
|
|
|
404
404
|
openEyeDropper(ctx) {
|
|
405
405
|
const isSupported = "EyeDropper" in dom.getWin(ctx)
|
|
406
406
|
if (!isSupported) return
|
|
407
|
-
const win = dom.getWin(ctx)
|
|
407
|
+
const win = dom.getWin(ctx)
|
|
408
408
|
const picker = new win.EyeDropper()
|
|
409
409
|
picker
|
|
410
410
|
.open()
|
|
411
|
-
.then(({ sRGBHex }
|
|
411
|
+
.then(({ sRGBHex }) => {
|
|
412
412
|
const format = ctx.value.getFormat()
|
|
413
413
|
const color = parseColor(sRGBHex).toFormat(format) as Color
|
|
414
414
|
set.value(ctx, color)
|
|
@@ -7,6 +7,20 @@ import type { MaybeFunction } from "@zag-js/utils"
|
|
|
7
7
|
|
|
8
8
|
export type ExtendedColorChannel = ColorChannel | "hex" | "css"
|
|
9
9
|
|
|
10
|
+
// patch the global window object to include the EyeDropper API
|
|
11
|
+
|
|
12
|
+
interface EyeDropper {
|
|
13
|
+
new (): EyeDropper
|
|
14
|
+
open: (options?: { signal?: AbortSignal }) => Promise<{ sRGBHex: string }>
|
|
15
|
+
[Symbol.toStringTag]: "EyeDropper"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare global {
|
|
19
|
+
interface Window {
|
|
20
|
+
EyeDropper: EyeDropper
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
/* -----------------------------------------------------------------------------
|
|
11
25
|
* Callback details
|
|
12
26
|
* -----------------------------------------------------------------------------*/
|
|
@@ -218,8 +232,8 @@ export interface SwatchTriggerProps {
|
|
|
218
232
|
export interface SwatchTriggerState {
|
|
219
233
|
value: Color
|
|
220
234
|
valueAsString: string
|
|
221
|
-
|
|
222
|
-
|
|
235
|
+
checked: boolean
|
|
236
|
+
disabled: boolean
|
|
223
237
|
}
|
|
224
238
|
|
|
225
239
|
export interface SwatchProps {
|
|
@@ -241,11 +255,11 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
241
255
|
/**
|
|
242
256
|
* Whether the color picker is being dragged
|
|
243
257
|
*/
|
|
244
|
-
|
|
258
|
+
dragging: boolean
|
|
245
259
|
/**
|
|
246
260
|
* Whether the color picker is open
|
|
247
261
|
*/
|
|
248
|
-
|
|
262
|
+
open: boolean
|
|
249
263
|
/**
|
|
250
264
|
* The current color value (as a string)
|
|
251
265
|
*/
|
|
@@ -283,13 +297,9 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
|
|
|
283
297
|
*/
|
|
284
298
|
setAlpha(value: number): void
|
|
285
299
|
/**
|
|
286
|
-
* Function to open the color picker
|
|
287
|
-
*/
|
|
288
|
-
open(): void
|
|
289
|
-
/**
|
|
290
|
-
* Function to close the color picker
|
|
300
|
+
* Function to open or close the color picker
|
|
291
301
|
*/
|
|
292
|
-
|
|
302
|
+
setOpen(open: boolean): void
|
|
293
303
|
|
|
294
304
|
rootProps: T["element"]
|
|
295
305
|
labelProps: T["element"]
|