@zag-js/color-picker 1.41.0 → 2.0.0-next.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/color-picker.anatomy.d.mts +2 -2
- package/dist/color-picker.anatomy.d.ts +2 -2
- package/dist/color-picker.anatomy.js +1 -0
- package/dist/color-picker.anatomy.mjs +1 -0
- package/dist/color-picker.connect.d.mts +1 -0
- package/dist/color-picker.connect.d.ts +1 -0
- package/dist/color-picker.connect.js +78 -42
- package/dist/color-picker.connect.mjs +79 -43
- package/dist/color-picker.dom.js +23 -22
- package/dist/color-picker.dom.mjs +23 -22
- package/dist/color-picker.machine.d.mts +1 -0
- package/dist/color-picker.machine.d.ts +1 -0
- package/dist/color-picker.machine.js +40 -17
- package/dist/color-picker.machine.mjs +40 -17
- package/dist/color-picker.props.d.mts +1 -0
- package/dist/color-picker.props.d.ts +1 -0
- package/dist/color-picker.types.d.mts +32 -1
- package/dist/color-picker.types.d.ts +32 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/utils/get-area-format.d.mts +6 -0
- package/dist/utils/get-area-format.d.ts +6 -0
- package/dist/utils/get-area-format.js +37 -0
- package/dist/utils/get-area-format.mjs +12 -0
- package/dist/utils/get-channel-display-color.js +7 -0
- package/dist/utils/get-channel-display-color.mjs +7 -0
- package/dist/utils/get-channel-input-value.d.mts +1 -0
- package/dist/utils/get-channel-input-value.d.ts +1 -0
- package/dist/utils/get-channel-input-value.js +39 -8
- package/dist/utils/get-channel-input-value.mjs +39 -8
- package/dist/utils/get-gamut-overlay-path.d.mts +33 -0
- package/dist/utils/get-gamut-overlay-path.d.ts +33 -0
- package/dist/utils/get-gamut-overlay-path.js +81 -0
- package/dist/utils/get-gamut-overlay-path.mjs +55 -0
- package/dist/utils/get-gamut-overlay-path.test.d.mts +2 -0
- package/dist/utils/get-gamut-overlay-path.test.d.ts +2 -0
- package/dist/utils/get-gamut-overlay-path.test.js +35 -0
- package/dist/utils/get-gamut-overlay-path.test.mjs +33 -0
- package/dist/utils/get-slider-background.d.mts +1 -0
- package/dist/utils/get-slider-background.d.ts +1 -0
- package/dist/utils/get-slider-background.js +16 -1
- package/dist/utils/get-slider-background.mjs +16 -1
- package/dist/utils/is-srgb-gamut.d.mts +6 -0
- package/dist/utils/is-srgb-gamut.d.ts +6 -0
- package/dist/utils/is-srgb-gamut.js +33 -0
- package/dist/utils/is-srgb-gamut.mjs +8 -0
- package/package.json +9 -9
|
@@ -15,6 +15,7 @@ import { getPlacement } from "@zag-js/popper";
|
|
|
15
15
|
import { tryCatch } from "@zag-js/utils";
|
|
16
16
|
import * as dom from "./color-picker.dom.mjs";
|
|
17
17
|
import { parse } from "./color-picker.parse.mjs";
|
|
18
|
+
import { getAreaFormat } from "./utils/get-area-format.mjs";
|
|
18
19
|
import { getChannelValue } from "./utils/get-channel-input-value.mjs";
|
|
19
20
|
import { prefixHex } from "./utils/is-valid-hex.mjs";
|
|
20
21
|
var { and } = createGuards();
|
|
@@ -70,11 +71,14 @@ var machine = createMachine({
|
|
|
70
71
|
activeId: bindable(() => ({ defaultValue: null })),
|
|
71
72
|
activeChannel: bindable(() => ({ defaultValue: null })),
|
|
72
73
|
activeOrientation: bindable(() => ({ defaultValue: null })),
|
|
74
|
+
areaBaseColor: bindable(() => ({ defaultValue: null })),
|
|
75
|
+
areaDragPosition: bindable(() => ({ defaultValue: null })),
|
|
73
76
|
fieldsetDisabled: bindable(() => ({ defaultValue: false })),
|
|
74
77
|
restoreFocus: bindable(() => ({ defaultValue: true })),
|
|
75
78
|
currentPlacement: bindable(() => ({
|
|
76
79
|
defaultValue: void 0
|
|
77
|
-
}))
|
|
80
|
+
})),
|
|
81
|
+
positioned: bindable(() => ({ defaultValue: false }))
|
|
78
82
|
};
|
|
79
83
|
},
|
|
80
84
|
computed: {
|
|
@@ -83,8 +87,7 @@ var machine = createMachine({
|
|
|
83
87
|
interactive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
|
|
84
88
|
valueAsString: ({ context }) => context.get("value").toString(context.get("format")),
|
|
85
89
|
areaValue: ({ context }) => {
|
|
86
|
-
|
|
87
|
-
return context.get("value").toFormat(format);
|
|
90
|
+
return context.get("value").toFormat(getAreaFormat(context.get("format")));
|
|
88
91
|
}
|
|
89
92
|
},
|
|
90
93
|
effects: ["trackFormControl"],
|
|
@@ -362,6 +365,7 @@ var machine = createMachine({
|
|
|
362
365
|
defer: true,
|
|
363
366
|
onComplete(data) {
|
|
364
367
|
context.set("currentPlacement", data.placement);
|
|
368
|
+
context.set("positioned", true);
|
|
365
369
|
}
|
|
366
370
|
});
|
|
367
371
|
},
|
|
@@ -432,36 +436,47 @@ var machine = createMachine({
|
|
|
432
436
|
});
|
|
433
437
|
}).catch(() => void 0);
|
|
434
438
|
},
|
|
435
|
-
setActiveChannel({ context, event }) {
|
|
439
|
+
setActiveChannel({ context, event, computed }) {
|
|
436
440
|
context.set("activeId", event.id);
|
|
437
441
|
if (event.channel) context.set("activeChannel", event.channel);
|
|
438
442
|
if (event.orientation) context.set("activeOrientation", event.orientation);
|
|
443
|
+
const areaFormat = getAreaFormat(context.get("format"));
|
|
444
|
+
if (areaFormat !== context.get("format")) {
|
|
445
|
+
context.set("areaBaseColor", computed("areaValue"));
|
|
446
|
+
}
|
|
439
447
|
},
|
|
440
448
|
clearActiveChannel({ context }) {
|
|
441
449
|
context.set("activeChannel", null);
|
|
442
450
|
context.set("activeId", null);
|
|
443
451
|
context.set("activeOrientation", null);
|
|
452
|
+
context.set("areaBaseColor", null);
|
|
453
|
+
context.set("areaDragPosition", null);
|
|
444
454
|
},
|
|
445
455
|
setAreaColorFromPoint({ context, event, computed, scope, prop }) {
|
|
446
|
-
const
|
|
456
|
+
const storeFormat = context.get("format");
|
|
457
|
+
const v = event.format ? context.get("value").toFormat(event.format) : context.get("areaBaseColor") ?? computed("areaValue");
|
|
447
458
|
const { xChannel, yChannel } = event.channel || context.get("activeChannel");
|
|
448
459
|
const percent = dom.getAreaValueFromPoint(scope, event.point, prop("dir"));
|
|
449
460
|
if (!percent) return;
|
|
461
|
+
context.set("areaDragPosition", { x: percent.x, y: percent.y });
|
|
450
462
|
const xValue = v.getChannelPercentValue(xChannel, percent.x);
|
|
451
463
|
const yValue = v.getChannelPercentValue(yChannel, 1 - percent.y);
|
|
452
|
-
const color = v.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue);
|
|
464
|
+
const color = v.withChannelValue(xChannel, xValue).withChannelValue(yChannel, yValue).toFormat(storeFormat);
|
|
453
465
|
context.set("value", color);
|
|
454
466
|
},
|
|
455
467
|
setChannelColorFromPoint({ context, event, computed, scope, prop }) {
|
|
468
|
+
const storeFormat = context.get("format");
|
|
456
469
|
const channel = event.channel || context.get("activeId");
|
|
457
|
-
const
|
|
470
|
+
const baseColor = context.get("areaBaseColor");
|
|
471
|
+
const normalizedValue = event.format ? context.get("value").toFormat(event.format) : baseColor ?? computed("areaValue");
|
|
458
472
|
const percent = dom.getChannelSliderValueFromPoint(scope, event.point, channel, prop("dir"));
|
|
459
473
|
if (!percent) return;
|
|
460
474
|
const orientation = event.orientation || context.get("activeOrientation") || "horizontal";
|
|
461
475
|
const channelPercent = orientation === "horizontal" ? percent.x : percent.y;
|
|
462
476
|
const value = normalizedValue.getChannelPercentValue(channel, channelPercent);
|
|
463
|
-
const
|
|
464
|
-
context.set("
|
|
477
|
+
const updatedBase = normalizedValue.withChannelValue(channel, value);
|
|
478
|
+
context.set("areaBaseColor", updatedBase);
|
|
479
|
+
context.set("value", updatedBase.toFormat(storeFormat));
|
|
465
480
|
},
|
|
466
481
|
setValue({ context, event }) {
|
|
467
482
|
const format = context.get("format");
|
|
@@ -518,24 +533,32 @@ var machine = createMachine({
|
|
|
518
533
|
const color = context.get("value").decrementChannel(event.channel, event.step);
|
|
519
534
|
context.set("value", color);
|
|
520
535
|
},
|
|
521
|
-
incrementAreaXChannel({ context, event
|
|
536
|
+
incrementAreaXChannel({ context, event }) {
|
|
522
537
|
const { xChannel } = event.channel;
|
|
523
|
-
const
|
|
538
|
+
const storeFormat = context.get("format");
|
|
539
|
+
const v = context.get("value").toFormat(getAreaFormat(storeFormat));
|
|
540
|
+
const color = v.incrementChannel(xChannel, event.step).toFormat(storeFormat);
|
|
524
541
|
context.set("value", color);
|
|
525
542
|
},
|
|
526
|
-
decrementAreaXChannel({ context, event
|
|
543
|
+
decrementAreaXChannel({ context, event }) {
|
|
527
544
|
const { xChannel } = event.channel;
|
|
528
|
-
const
|
|
545
|
+
const storeFormat = context.get("format");
|
|
546
|
+
const v = context.get("value").toFormat(getAreaFormat(storeFormat));
|
|
547
|
+
const color = v.decrementChannel(xChannel, event.step).toFormat(storeFormat);
|
|
529
548
|
context.set("value", color);
|
|
530
549
|
},
|
|
531
|
-
incrementAreaYChannel({ context, event
|
|
550
|
+
incrementAreaYChannel({ context, event }) {
|
|
532
551
|
const { yChannel } = event.channel;
|
|
533
|
-
const
|
|
552
|
+
const storeFormat = context.get("format");
|
|
553
|
+
const v = context.get("value").toFormat(getAreaFormat(storeFormat));
|
|
554
|
+
const color = v.incrementChannel(yChannel, event.step).toFormat(storeFormat);
|
|
534
555
|
context.set("value", color);
|
|
535
556
|
},
|
|
536
|
-
decrementAreaYChannel({ context, event
|
|
557
|
+
decrementAreaYChannel({ context, event }) {
|
|
537
558
|
const { yChannel } = event.channel;
|
|
538
|
-
const
|
|
559
|
+
const storeFormat = context.get("format");
|
|
560
|
+
const v = context.get("value").toFormat(getAreaFormat(storeFormat));
|
|
561
|
+
const color = v.decrementChannel(yChannel, event.step).toFormat(storeFormat);
|
|
539
562
|
context.set("value", color);
|
|
540
563
|
},
|
|
541
564
|
setChannelToMax({ context, event }) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AreaProps, ChannelProps, ColorPickerProps, SwatchProps, SwatchTriggerProps, TransparencyGridProps } from './color-picker.types.mjs';
|
|
2
2
|
import '@zag-js/color-utils';
|
|
3
|
+
import './utils/get-gamut-overlay-path.mjs';
|
|
3
4
|
import '@zag-js/core';
|
|
4
5
|
import '@zag-js/dismissable';
|
|
5
6
|
import '@zag-js/popper';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AreaProps, ChannelProps, ColorPickerProps, SwatchProps, SwatchTriggerProps, TransparencyGridProps } from './color-picker.types.js';
|
|
2
2
|
import '@zag-js/color-utils';
|
|
3
|
+
import './utils/get-gamut-overlay-path.js';
|
|
3
4
|
import '@zag-js/core';
|
|
4
5
|
import '@zag-js/dismissable';
|
|
5
6
|
import '@zag-js/popper';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ColorChannel, Color, ColorFormat, ColorAxes } from '@zag-js/color-utils';
|
|
2
2
|
export { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from '@zag-js/color-utils';
|
|
3
|
+
import { GamutOverlayData } from './utils/get-gamut-overlay-path.mjs';
|
|
3
4
|
import { Service, EventObject, Machine } from '@zag-js/core';
|
|
4
5
|
import { InteractOutsideHandlers } from '@zag-js/dismissable';
|
|
5
6
|
import { PositioningOptions } from '@zag-js/popper';
|
|
@@ -160,8 +161,14 @@ type ColorPickerSchema = {
|
|
|
160
161
|
activeId: string | null;
|
|
161
162
|
activeChannel: Partial<ColorAxes> | null;
|
|
162
163
|
activeOrientation: Orientation | null;
|
|
164
|
+
areaBaseColor: Color | null;
|
|
165
|
+
areaDragPosition: {
|
|
166
|
+
x: number;
|
|
167
|
+
y: number;
|
|
168
|
+
} | null;
|
|
163
169
|
fieldsetDisabled: boolean;
|
|
164
170
|
currentPlacement: PositioningOptions["placement"] | undefined;
|
|
171
|
+
positioned: boolean;
|
|
165
172
|
restoreFocus: boolean;
|
|
166
173
|
};
|
|
167
174
|
event: EventObject;
|
|
@@ -186,6 +193,16 @@ interface AreaProps {
|
|
|
186
193
|
xChannel?: ColorChannel | undefined;
|
|
187
194
|
yChannel?: ColorChannel | undefined;
|
|
188
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Same channel overrides as {@link AreaProps}, plus optional DPR for overlay sampling.
|
|
198
|
+
* Pass the **same** object to `getAreaProps`, `getGamutOverlay`, and `getGamutOverlayProps`.
|
|
199
|
+
*/
|
|
200
|
+
interface GamutOverlayProps extends AreaProps {
|
|
201
|
+
/**
|
|
202
|
+
* Overrides `globalThis.devicePixelRatio` for boundary resolution (default browser DPR in connect).
|
|
203
|
+
*/
|
|
204
|
+
pixelRatio?: number | undefined;
|
|
205
|
+
}
|
|
189
206
|
interface SwatchTriggerProps {
|
|
190
207
|
/**
|
|
191
208
|
* The color value
|
|
@@ -236,6 +253,11 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
236
253
|
* The current color value (as a Color object)
|
|
237
254
|
*/
|
|
238
255
|
valueAsString: string;
|
|
256
|
+
/**
|
|
257
|
+
* Whether the current color lies inside the sRGB gamut (linear RGB cube).
|
|
258
|
+
* When `false`, wide-gamut CSS strings may still be valid while 8-bit RGB / hex are clamped.
|
|
259
|
+
*/
|
|
260
|
+
isInSrgbGamut: boolean;
|
|
239
261
|
/**
|
|
240
262
|
* Function to set the color value
|
|
241
263
|
*/
|
|
@@ -282,6 +304,15 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
282
304
|
getValueTextProps: () => T["element"];
|
|
283
305
|
getAreaProps: (props?: AreaProps) => T["element"];
|
|
284
306
|
getAreaBackgroundProps: (props?: AreaProps) => T["element"];
|
|
307
|
+
/**
|
|
308
|
+
* SVG path + label position for the sRGB gamut boundary (oklch/oklab + HSB area only); `null` when not shown.
|
|
309
|
+
* Use the **same** `props` as {@link getAreaProps} / {@link getGamutOverlayProps} (including `pixelRatio`).
|
|
310
|
+
*/
|
|
311
|
+
getGamutOverlay: (props?: GamutOverlayProps) => GamutOverlayData | null;
|
|
312
|
+
/**
|
|
313
|
+
* Props for an `<svg>` gamut overlay; pair with {@link getGamutOverlay} using the same `props`.
|
|
314
|
+
*/
|
|
315
|
+
getGamutOverlayProps: (props?: GamutOverlayProps) => T["svg"];
|
|
285
316
|
getAreaThumbProps: (props?: AreaProps) => T["element"];
|
|
286
317
|
getChannelInputProps: (props: ChannelInputProps) => T["input"];
|
|
287
318
|
getChannelSliderProps: (props: ChannelSliderProps) => T["element"];
|
|
@@ -300,4 +331,4 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
300
331
|
getFormatTriggerProps: () => T["button"];
|
|
301
332
|
}
|
|
302
333
|
|
|
303
|
-
export type
|
|
334
|
+
export { type AreaProps, type ChannelInputProps, type ChannelProps, type ChannelSliderProps, type ColorPickerApi, type ColorPickerMachine, type ColorPickerProps, type ColorPickerSchema, type ColorPickerService, type ElementIds, type ExtendedColorChannel, type FormatChangeDetails, GamutOverlayData, type GamutOverlayProps, type OpenChangeDetails, type SwatchProps, type SwatchTriggerProps, type SwatchTriggerState, type TransparencyGridProps, type ValueChangeDetails };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ColorChannel, Color, ColorFormat, ColorAxes } from '@zag-js/color-utils';
|
|
2
2
|
export { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from '@zag-js/color-utils';
|
|
3
|
+
import { GamutOverlayData } from './utils/get-gamut-overlay-path.js';
|
|
3
4
|
import { Service, EventObject, Machine } from '@zag-js/core';
|
|
4
5
|
import { InteractOutsideHandlers } from '@zag-js/dismissable';
|
|
5
6
|
import { PositioningOptions } from '@zag-js/popper';
|
|
@@ -160,8 +161,14 @@ type ColorPickerSchema = {
|
|
|
160
161
|
activeId: string | null;
|
|
161
162
|
activeChannel: Partial<ColorAxes> | null;
|
|
162
163
|
activeOrientation: Orientation | null;
|
|
164
|
+
areaBaseColor: Color | null;
|
|
165
|
+
areaDragPosition: {
|
|
166
|
+
x: number;
|
|
167
|
+
y: number;
|
|
168
|
+
} | null;
|
|
163
169
|
fieldsetDisabled: boolean;
|
|
164
170
|
currentPlacement: PositioningOptions["placement"] | undefined;
|
|
171
|
+
positioned: boolean;
|
|
165
172
|
restoreFocus: boolean;
|
|
166
173
|
};
|
|
167
174
|
event: EventObject;
|
|
@@ -186,6 +193,16 @@ interface AreaProps {
|
|
|
186
193
|
xChannel?: ColorChannel | undefined;
|
|
187
194
|
yChannel?: ColorChannel | undefined;
|
|
188
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Same channel overrides as {@link AreaProps}, plus optional DPR for overlay sampling.
|
|
198
|
+
* Pass the **same** object to `getAreaProps`, `getGamutOverlay`, and `getGamutOverlayProps`.
|
|
199
|
+
*/
|
|
200
|
+
interface GamutOverlayProps extends AreaProps {
|
|
201
|
+
/**
|
|
202
|
+
* Overrides `globalThis.devicePixelRatio` for boundary resolution (default browser DPR in connect).
|
|
203
|
+
*/
|
|
204
|
+
pixelRatio?: number | undefined;
|
|
205
|
+
}
|
|
189
206
|
interface SwatchTriggerProps {
|
|
190
207
|
/**
|
|
191
208
|
* The color value
|
|
@@ -236,6 +253,11 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
236
253
|
* The current color value (as a Color object)
|
|
237
254
|
*/
|
|
238
255
|
valueAsString: string;
|
|
256
|
+
/**
|
|
257
|
+
* Whether the current color lies inside the sRGB gamut (linear RGB cube).
|
|
258
|
+
* When `false`, wide-gamut CSS strings may still be valid while 8-bit RGB / hex are clamped.
|
|
259
|
+
*/
|
|
260
|
+
isInSrgbGamut: boolean;
|
|
239
261
|
/**
|
|
240
262
|
* Function to set the color value
|
|
241
263
|
*/
|
|
@@ -282,6 +304,15 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
282
304
|
getValueTextProps: () => T["element"];
|
|
283
305
|
getAreaProps: (props?: AreaProps) => T["element"];
|
|
284
306
|
getAreaBackgroundProps: (props?: AreaProps) => T["element"];
|
|
307
|
+
/**
|
|
308
|
+
* SVG path + label position for the sRGB gamut boundary (oklch/oklab + HSB area only); `null` when not shown.
|
|
309
|
+
* Use the **same** `props` as {@link getAreaProps} / {@link getGamutOverlayProps} (including `pixelRatio`).
|
|
310
|
+
*/
|
|
311
|
+
getGamutOverlay: (props?: GamutOverlayProps) => GamutOverlayData | null;
|
|
312
|
+
/**
|
|
313
|
+
* Props for an `<svg>` gamut overlay; pair with {@link getGamutOverlay} using the same `props`.
|
|
314
|
+
*/
|
|
315
|
+
getGamutOverlayProps: (props?: GamutOverlayProps) => T["svg"];
|
|
285
316
|
getAreaThumbProps: (props?: AreaProps) => T["element"];
|
|
286
317
|
getChannelInputProps: (props: ChannelInputProps) => T["input"];
|
|
287
318
|
getChannelSliderProps: (props: ChannelSliderProps) => T["element"];
|
|
@@ -300,4 +331,4 @@ interface ColorPickerApi<T extends PropTypes = PropTypes> {
|
|
|
300
331
|
getFormatTriggerProps: () => T["button"];
|
|
301
332
|
}
|
|
302
333
|
|
|
303
|
-
export type
|
|
334
|
+
export { type AreaProps, type ChannelInputProps, type ChannelProps, type ChannelSliderProps, type ColorPickerApi, type ColorPickerMachine, type ColorPickerProps, type ColorPickerSchema, type ColorPickerService, type ElementIds, type ExtendedColorChannel, type FormatChangeDetails, GamutOverlayData, type GamutOverlayProps, type OpenChangeDetails, type SwatchProps, type SwatchTriggerProps, type SwatchTriggerState, type TransparencyGridProps, type ValueChangeDetails };
|
package/dist/index.d.mts
CHANGED
|
@@ -4,8 +4,9 @@ export { connect } from './color-picker.connect.mjs';
|
|
|
4
4
|
export { machine } from './color-picker.machine.mjs';
|
|
5
5
|
export { parse } from './color-picker.parse.mjs';
|
|
6
6
|
export { areaProps, channelProps, props, splitAreaProps, splitChannelProps, splitProps, splitSwatchProps, splitSwatchTriggerProps, splitTransparencyGridProps, swatchProps, swatchTriggerProps, transparencyGridProps } from './color-picker.props.mjs';
|
|
7
|
-
export { ColorPickerApi as Api, AreaProps, ChannelInputProps, ChannelProps, ChannelSliderProps, ElementIds, ExtendedColorChannel, FormatChangeDetails, ColorPickerMachine as Machine, OpenChangeDetails, ColorPickerProps as Props, ColorPickerService as Service, SwatchProps, SwatchTriggerProps, SwatchTriggerState, TransparencyGridProps, ValueChangeDetails } from './color-picker.types.mjs';
|
|
7
|
+
export { ColorPickerApi as Api, AreaProps, ChannelInputProps, ChannelProps, ChannelSliderProps, ElementIds, ExtendedColorChannel, FormatChangeDetails, GamutOverlayProps, ColorPickerMachine as Machine, OpenChangeDetails, ColorPickerProps as Props, ColorPickerService as Service, SwatchProps, SwatchTriggerProps, SwatchTriggerState, TransparencyGridProps, ValueChangeDetails } from './color-picker.types.mjs';
|
|
8
8
|
export { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from '@zag-js/color-utils';
|
|
9
|
+
export { GamutOverlayData } from './utils/get-gamut-overlay-path.mjs';
|
|
9
10
|
export { PositioningOptions } from '@zag-js/popper';
|
|
10
11
|
import '@zag-js/anatomy';
|
|
11
12
|
import '@zag-js/types';
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ export { connect } from './color-picker.connect.js';
|
|
|
4
4
|
export { machine } from './color-picker.machine.js';
|
|
5
5
|
export { parse } from './color-picker.parse.js';
|
|
6
6
|
export { areaProps, channelProps, props, splitAreaProps, splitChannelProps, splitProps, splitSwatchProps, splitSwatchTriggerProps, splitTransparencyGridProps, swatchProps, swatchTriggerProps, transparencyGridProps } from './color-picker.props.js';
|
|
7
|
-
export { ColorPickerApi as Api, AreaProps, ChannelInputProps, ChannelProps, ChannelSliderProps, ElementIds, ExtendedColorChannel, FormatChangeDetails, ColorPickerMachine as Machine, OpenChangeDetails, ColorPickerProps as Props, ColorPickerService as Service, SwatchProps, SwatchTriggerProps, SwatchTriggerState, TransparencyGridProps, ValueChangeDetails } from './color-picker.types.js';
|
|
7
|
+
export { ColorPickerApi as Api, AreaProps, ChannelInputProps, ChannelProps, ChannelSliderProps, ElementIds, ExtendedColorChannel, FormatChangeDetails, GamutOverlayProps, ColorPickerMachine as Machine, OpenChangeDetails, ColorPickerProps as Props, ColorPickerService as Service, SwatchProps, SwatchTriggerProps, SwatchTriggerState, TransparencyGridProps, ValueChangeDetails } from './color-picker.types.js';
|
|
8
8
|
export { Color, ColorAxes, ColorChannel, ColorFormat, ColorType } from '@zag-js/color-utils';
|
|
9
|
+
export { GamutOverlayData } from './utils/get-gamut-overlay-path.js';
|
|
9
10
|
export { PositioningOptions } from '@zag-js/popper';
|
|
10
11
|
import '@zag-js/anatomy';
|
|
11
12
|
import '@zag-js/types';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/utils/get-area-format.ts
|
|
21
|
+
var get_area_format_exports = {};
|
|
22
|
+
__export(get_area_format_exports, {
|
|
23
|
+
getAreaFormat: () => getAreaFormat
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(get_area_format_exports);
|
|
26
|
+
function getAreaFormat(format) {
|
|
27
|
+
if (format.startsWith("hsl")) return "hsla";
|
|
28
|
+
if (format.startsWith("hsb")) return "hsba";
|
|
29
|
+
if (format.startsWith("rgb")) return "rgba";
|
|
30
|
+
if (format === "oklab") return "hsba";
|
|
31
|
+
if (format === "oklch") return "hsba";
|
|
32
|
+
return "hsba";
|
|
33
|
+
}
|
|
34
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
35
|
+
0 && (module.exports = {
|
|
36
|
+
getAreaFormat
|
|
37
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/utils/get-area-format.ts
|
|
2
|
+
function getAreaFormat(format) {
|
|
3
|
+
if (format.startsWith("hsl")) return "hsla";
|
|
4
|
+
if (format.startsWith("hsb")) return "hsba";
|
|
5
|
+
if (format.startsWith("rgb")) return "rgba";
|
|
6
|
+
if (format === "oklab") return "hsba";
|
|
7
|
+
if (format === "oklch") return "hsba";
|
|
8
|
+
return "hsba";
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
getAreaFormat
|
|
12
|
+
};
|
|
@@ -25,10 +25,17 @@ __export(get_channel_display_color_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(get_channel_display_color_exports);
|
|
26
26
|
var import_color_utils = require("@zag-js/color-utils");
|
|
27
27
|
function getChannelDisplayColor(color, channel) {
|
|
28
|
+
const fmt = color.getFormat();
|
|
28
29
|
switch (channel) {
|
|
29
30
|
case "hue":
|
|
31
|
+
if (fmt === "oklch") {
|
|
32
|
+
return color.withChannelValue("alpha", 1);
|
|
33
|
+
}
|
|
30
34
|
return (0, import_color_utils.parseColor)(`hsl(${color.getChannelValue("hue")}, 100%, 50%)`);
|
|
31
35
|
case "lightness":
|
|
36
|
+
case "chroma":
|
|
37
|
+
case "a":
|
|
38
|
+
case "b":
|
|
32
39
|
case "brightness":
|
|
33
40
|
case "saturation":
|
|
34
41
|
case "red":
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
// src/utils/get-channel-display-color.ts
|
|
2
2
|
import { parseColor } from "@zag-js/color-utils";
|
|
3
3
|
function getChannelDisplayColor(color, channel) {
|
|
4
|
+
const fmt = color.getFormat();
|
|
4
5
|
switch (channel) {
|
|
5
6
|
case "hue":
|
|
7
|
+
if (fmt === "oklch") {
|
|
8
|
+
return color.withChannelValue("alpha", 1);
|
|
9
|
+
}
|
|
6
10
|
return parseColor(`hsl(${color.getChannelValue("hue")}, 100%, 50%)`);
|
|
7
11
|
case "lightness":
|
|
12
|
+
case "chroma":
|
|
13
|
+
case "a":
|
|
14
|
+
case "b":
|
|
8
15
|
case "brightness":
|
|
9
16
|
case "saturation":
|
|
10
17
|
case "red":
|
|
@@ -34,26 +34,45 @@ function getChannelValue(color, channel) {
|
|
|
34
34
|
return color.toString("css");
|
|
35
35
|
}
|
|
36
36
|
if (channel in color) {
|
|
37
|
-
return color
|
|
37
|
+
return roundedValue(color, channel);
|
|
38
38
|
}
|
|
39
|
-
const
|
|
39
|
+
const fmt = color.getFormat();
|
|
40
|
+
const isHSL = fmt === "hsla";
|
|
40
41
|
switch (channel) {
|
|
41
42
|
case "hue":
|
|
42
|
-
|
|
43
|
+
if (fmt === "oklch") {
|
|
44
|
+
return roundedValue(color.toFormat("oklch"), "hue");
|
|
45
|
+
}
|
|
46
|
+
return isHSL ? roundedValue(color.toFormat("hsla"), "hue") : roundedValue(color.toFormat("hsba"), "hue");
|
|
43
47
|
case "saturation":
|
|
44
|
-
return isHSL ? color.toFormat("hsla")
|
|
48
|
+
return isHSL ? roundedValue(color.toFormat("hsla"), "saturation") : roundedValue(color.toFormat("hsba"), "saturation");
|
|
45
49
|
case "lightness":
|
|
46
|
-
|
|
50
|
+
if (fmt === "oklab" || fmt === "oklch") {
|
|
51
|
+
return roundedValue(color, "lightness");
|
|
52
|
+
}
|
|
53
|
+
return roundedValue(color.toFormat("hsla"), "lightness");
|
|
47
54
|
case "brightness":
|
|
48
|
-
return color.toFormat("hsba")
|
|
55
|
+
return roundedValue(color.toFormat("hsba"), "brightness");
|
|
56
|
+
case "a":
|
|
57
|
+
case "b":
|
|
58
|
+
return roundedValue(color.toFormat("oklab"), channel);
|
|
59
|
+
case "chroma":
|
|
60
|
+
return roundedValue(color.toFormat("oklch"), channel);
|
|
49
61
|
case "red":
|
|
50
62
|
case "green":
|
|
51
63
|
case "blue":
|
|
52
|
-
return color.toFormat("rgba")
|
|
64
|
+
return roundedValue(color.toFormat("rgba"), channel);
|
|
53
65
|
default:
|
|
54
|
-
return color
|
|
66
|
+
return roundedValue(color, channel);
|
|
55
67
|
}
|
|
56
68
|
}
|
|
69
|
+
function roundedValue(color, channel) {
|
|
70
|
+
const value = color.getChannelValue(channel);
|
|
71
|
+
const { step } = color.getChannelRange(channel);
|
|
72
|
+
if (step >= 1) return Math.round(value).toString();
|
|
73
|
+
const decimals = Math.min(4, Math.max(0, Math.ceil(-Math.log10(step))));
|
|
74
|
+
return parseFloat(value.toFixed(decimals)).toString();
|
|
75
|
+
}
|
|
57
76
|
function getChannelRange(color, channel) {
|
|
58
77
|
switch (channel) {
|
|
59
78
|
case "hex":
|
|
@@ -68,11 +87,23 @@ function getChannelRange(color, channel) {
|
|
|
68
87
|
case "css":
|
|
69
88
|
return void 0;
|
|
70
89
|
case "hue":
|
|
90
|
+
if (color.getFormat() === "oklch") {
|
|
91
|
+
return color.toFormat("oklch").getChannelRange("hue");
|
|
92
|
+
}
|
|
93
|
+
return color.toFormat("hsla").getChannelRange(channel);
|
|
71
94
|
case "saturation":
|
|
72
95
|
case "lightness":
|
|
96
|
+
if (color.getFormat() === "oklab" || color.getFormat() === "oklch") {
|
|
97
|
+
return color.getChannelRange(channel);
|
|
98
|
+
}
|
|
73
99
|
return color.toFormat("hsla").getChannelRange(channel);
|
|
74
100
|
case "brightness":
|
|
75
101
|
return color.toFormat("hsba").getChannelRange(channel);
|
|
102
|
+
case "a":
|
|
103
|
+
case "b":
|
|
104
|
+
return color.toFormat("oklab").getChannelRange(channel);
|
|
105
|
+
case "chroma":
|
|
106
|
+
return color.toFormat("oklch").getChannelRange(channel);
|
|
76
107
|
case "red":
|
|
77
108
|
case "green":
|
|
78
109
|
case "blue":
|
|
@@ -9,26 +9,45 @@ function getChannelValue(color, channel) {
|
|
|
9
9
|
return color.toString("css");
|
|
10
10
|
}
|
|
11
11
|
if (channel in color) {
|
|
12
|
-
return color
|
|
12
|
+
return roundedValue(color, channel);
|
|
13
13
|
}
|
|
14
|
-
const
|
|
14
|
+
const fmt = color.getFormat();
|
|
15
|
+
const isHSL = fmt === "hsla";
|
|
15
16
|
switch (channel) {
|
|
16
17
|
case "hue":
|
|
17
|
-
|
|
18
|
+
if (fmt === "oklch") {
|
|
19
|
+
return roundedValue(color.toFormat("oklch"), "hue");
|
|
20
|
+
}
|
|
21
|
+
return isHSL ? roundedValue(color.toFormat("hsla"), "hue") : roundedValue(color.toFormat("hsba"), "hue");
|
|
18
22
|
case "saturation":
|
|
19
|
-
return isHSL ? color.toFormat("hsla")
|
|
23
|
+
return isHSL ? roundedValue(color.toFormat("hsla"), "saturation") : roundedValue(color.toFormat("hsba"), "saturation");
|
|
20
24
|
case "lightness":
|
|
21
|
-
|
|
25
|
+
if (fmt === "oklab" || fmt === "oklch") {
|
|
26
|
+
return roundedValue(color, "lightness");
|
|
27
|
+
}
|
|
28
|
+
return roundedValue(color.toFormat("hsla"), "lightness");
|
|
22
29
|
case "brightness":
|
|
23
|
-
return color.toFormat("hsba")
|
|
30
|
+
return roundedValue(color.toFormat("hsba"), "brightness");
|
|
31
|
+
case "a":
|
|
32
|
+
case "b":
|
|
33
|
+
return roundedValue(color.toFormat("oklab"), channel);
|
|
34
|
+
case "chroma":
|
|
35
|
+
return roundedValue(color.toFormat("oklch"), channel);
|
|
24
36
|
case "red":
|
|
25
37
|
case "green":
|
|
26
38
|
case "blue":
|
|
27
|
-
return color.toFormat("rgba")
|
|
39
|
+
return roundedValue(color.toFormat("rgba"), channel);
|
|
28
40
|
default:
|
|
29
|
-
return color
|
|
41
|
+
return roundedValue(color, channel);
|
|
30
42
|
}
|
|
31
43
|
}
|
|
44
|
+
function roundedValue(color, channel) {
|
|
45
|
+
const value = color.getChannelValue(channel);
|
|
46
|
+
const { step } = color.getChannelRange(channel);
|
|
47
|
+
if (step >= 1) return Math.round(value).toString();
|
|
48
|
+
const decimals = Math.min(4, Math.max(0, Math.ceil(-Math.log10(step))));
|
|
49
|
+
return parseFloat(value.toFixed(decimals)).toString();
|
|
50
|
+
}
|
|
32
51
|
function getChannelRange(color, channel) {
|
|
33
52
|
switch (channel) {
|
|
34
53
|
case "hex":
|
|
@@ -43,11 +62,23 @@ function getChannelRange(color, channel) {
|
|
|
43
62
|
case "css":
|
|
44
63
|
return void 0;
|
|
45
64
|
case "hue":
|
|
65
|
+
if (color.getFormat() === "oklch") {
|
|
66
|
+
return color.toFormat("oklch").getChannelRange("hue");
|
|
67
|
+
}
|
|
68
|
+
return color.toFormat("hsla").getChannelRange(channel);
|
|
46
69
|
case "saturation":
|
|
47
70
|
case "lightness":
|
|
71
|
+
if (color.getFormat() === "oklab" || color.getFormat() === "oklch") {
|
|
72
|
+
return color.getChannelRange(channel);
|
|
73
|
+
}
|
|
48
74
|
return color.toFormat("hsla").getChannelRange(channel);
|
|
49
75
|
case "brightness":
|
|
50
76
|
return color.toFormat("hsba").getChannelRange(channel);
|
|
77
|
+
case "a":
|
|
78
|
+
case "b":
|
|
79
|
+
return color.toFormat("oklab").getChannelRange(channel);
|
|
80
|
+
case "chroma":
|
|
81
|
+
return color.toFormat("oklch").getChannelRange(channel);
|
|
51
82
|
case "red":
|
|
52
83
|
case "green":
|
|
53
84
|
case "blue":
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Color, ColorChannel, ColorFormat } from '@zag-js/color-utils';
|
|
2
|
+
|
|
3
|
+
interface GamutOverlayOptions {
|
|
4
|
+
xChannel: ColorChannel;
|
|
5
|
+
yChannel: ColorChannel;
|
|
6
|
+
}
|
|
7
|
+
interface GamutOverlayData {
|
|
8
|
+
path: string;
|
|
9
|
+
labelPosition: {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface GamutOverlayComputeOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Device pixel ratio; higher values sample more rows along brightness (Chrome DevTools–style).
|
|
17
|
+
* Default `1` when not passed (callers may pass `globalThis.devicePixelRatio` in browsers).
|
|
18
|
+
*/
|
|
19
|
+
pixelRatio?: number | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Computes an SVG path (0–100 user units) tracing the sRGB gamut boundary
|
|
23
|
+
* over the HSB color area when in a wide-gamut output format (oklch/oklab).
|
|
24
|
+
*
|
|
25
|
+
* Approach (matching Chrome DevTools): treat the HSV area as Display P3 gamut,
|
|
26
|
+
* then for each brightness row, sweep saturation left→right to find where
|
|
27
|
+
* the P3 color exits the sRGB gamut.
|
|
28
|
+
*/
|
|
29
|
+
declare function getGamutOverlayData(areaValue: Color, axes: GamutOverlayOptions, format: ColorFormat, options?: GamutOverlayComputeOptions): GamutOverlayData | null;
|
|
30
|
+
/** Visible boundary rows scale with DPR (analogous to Chrome `step = 1 / devicePixelRatio` in px space). */
|
|
31
|
+
declare function gamutOverlayRowCount(pixelRatio: number): number;
|
|
32
|
+
|
|
33
|
+
export { type GamutOverlayComputeOptions, type GamutOverlayData, gamutOverlayRowCount, getGamutOverlayData };
|