chroma-panel 0.1.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/LICENSE +44 -0
- package/README.md +119 -0
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/a11y/contrast.cjs +107 -0
- package/dist/a11y/contrast.d.cts +34 -0
- package/dist/a11y/contrast.d.ts +34 -0
- package/dist/a11y/contrast.js +101 -0
- package/dist/color/convert.cjs +162 -0
- package/dist/color/convert.d.cts +16 -0
- package/dist/color/convert.d.ts +16 -0
- package/dist/color/convert.js +153 -0
- package/dist/color/parse.cjs +153 -0
- package/dist/color/parse.d.cts +7 -0
- package/dist/color/parse.d.ts +7 -0
- package/dist/color/parse.js +151 -0
- package/dist/color/serialize.cjs +79 -0
- package/dist/color/serialize.d.cts +11 -0
- package/dist/color/serialize.d.ts +11 -0
- package/dist/color/serialize.js +73 -0
- package/dist/color/sticky.cjs +20 -0
- package/dist/color/sticky.d.cts +6 -0
- package/dist/color/sticky.d.ts +6 -0
- package/dist/color/sticky.js +19 -0
- package/dist/color/types.d.cts +43 -0
- package/dist/color/types.d.ts +43 -0
- package/dist/components/ChromaPanel.cjs +254 -0
- package/dist/components/ChromaPanel.d.cts +47 -0
- package/dist/components/ChromaPanel.d.ts +47 -0
- package/dist/components/ChromaPanel.js +251 -0
- package/dist/components/ColorInput.cjs +128 -0
- package/dist/components/ColorInput.d.cts +19 -0
- package/dist/components/ColorInput.d.ts +19 -0
- package/dist/components/ColorInput.js +127 -0
- package/dist/components/ModeToolbar.cjs +33 -0
- package/dist/components/ModeToolbar.d.cts +10 -0
- package/dist/components/ModeToolbar.d.ts +10 -0
- package/dist/components/ModeToolbar.js +32 -0
- package/dist/components/PanelFooter.cjs +82 -0
- package/dist/components/PanelFooter.d.cts +5 -0
- package/dist/components/PanelFooter.d.ts +5 -0
- package/dist/components/PanelFooter.js +80 -0
- package/dist/components/Popover.cjs +154 -0
- package/dist/components/Popover.d.cts +13 -0
- package/dist/components/Popover.d.ts +13 -0
- package/dist/components/Popover.js +153 -0
- package/dist/contrast.cjs +10 -0
- package/dist/contrast.d.cts +2 -0
- package/dist/contrast.d.ts +2 -0
- package/dist/contrast.js +2 -0
- package/dist/core/context.cjs +30 -0
- package/dist/core/context.d.cts +43 -0
- package/dist/core/context.d.ts +43 -0
- package/dist/core/context.js +26 -0
- package/dist/core/dev.cjs +11 -0
- package/dist/core/dev.js +11 -0
- package/dist/core/store.cjs +43 -0
- package/dist/core/store.d.cts +17 -0
- package/dist/core/store.d.ts +17 -0
- package/dist/core/store.js +44 -0
- package/dist/core/styleInjector.cjs +38 -0
- package/dist/core/styleInjector.d.cts +4 -0
- package/dist/core/styleInjector.d.ts +4 -0
- package/dist/core/styleInjector.js +38 -0
- package/dist/core/useColorStore.cjs +43 -0
- package/dist/core/useColorStore.d.cts +6 -0
- package/dist/core/useColorStore.d.ts +6 -0
- package/dist/core/useColorStore.js +41 -0
- package/dist/core/useFormControl.cjs +87 -0
- package/dist/core/useFormControl.js +82 -0
- package/dist/core/useMediaQuery.cjs +48 -0
- package/dist/core/useMediaQuery.js +46 -0
- package/dist/core/usePointerDrag.cjs +177 -0
- package/dist/core/usePointerDrag.d.cts +35 -0
- package/dist/core/usePointerDrag.d.ts +35 -0
- package/dist/core/usePointerDrag.js +175 -0
- package/dist/core/useScrollFade.cjs +44 -0
- package/dist/core/useScrollFade.js +43 -0
- package/dist/core.cjs +33 -0
- package/dist/core.d.cts +7 -0
- package/dist/core.d.ts +7 -0
- package/dist/core.js +6 -0
- package/dist/data/defaults.cjs +123 -0
- package/dist/data/defaults.d.cts +6 -0
- package/dist/data/defaults.d.ts +6 -0
- package/dist/data/defaults.js +122 -0
- package/dist/data/namedColors.cjs +11 -0
- package/dist/data/namedColors.d.cts +3 -0
- package/dist/data/namedColors.d.ts +3 -0
- package/dist/data/namedColors.js +12 -0
- package/dist/image/extract.cjs +98 -0
- package/dist/image/extract.d.cts +16 -0
- package/dist/image/extract.d.ts +16 -0
- package/dist/image/extract.js +99 -0
- package/dist/image/mmcq.cjs +182 -0
- package/dist/image/mmcq.d.cts +8 -0
- package/dist/image/mmcq.d.ts +8 -0
- package/dist/image/mmcq.js +183 -0
- package/dist/image-worker.js +202 -0
- package/dist/image.cjs +12 -0
- package/dist/image.d.cts +4 -0
- package/dist/image.d.ts +4 -0
- package/dist/image.js +9 -0
- package/dist/index.cjs +119 -0
- package/dist/index.d.cts +36 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +44 -0
- package/dist/modes/gradients.cjs +48 -0
- package/dist/modes/gradients.js +43 -0
- package/dist/modes/image/index.cjs +193 -0
- package/dist/modes/image/index.d.cts +10 -0
- package/dist/modes/image/index.d.ts +10 -0
- package/dist/modes/image/index.js +191 -0
- package/dist/modes/palettes/index.cjs +76 -0
- package/dist/modes/palettes/index.d.cts +6 -0
- package/dist/modes/palettes/index.d.ts +6 -0
- package/dist/modes/palettes/index.js +74 -0
- package/dist/modes/pencils/index.cjs +36 -0
- package/dist/modes/pencils/index.d.cts +6 -0
- package/dist/modes/pencils/index.d.ts +6 -0
- package/dist/modes/pencils/index.js +34 -0
- package/dist/modes/registry.cjs +26 -0
- package/dist/modes/registry.d.cts +13 -0
- package/dist/modes/registry.d.ts +13 -0
- package/dist/modes/registry.js +25 -0
- package/dist/modes/sliders/index.cjs +300 -0
- package/dist/modes/sliders/index.d.cts +6 -0
- package/dist/modes/sliders/index.d.ts +6 -0
- package/dist/modes/sliders/index.js +298 -0
- package/dist/modes/wheel/index.cjs +62 -0
- package/dist/modes/wheel/index.d.cts +6 -0
- package/dist/modes/wheel/index.d.ts +6 -0
- package/dist/modes/wheel/index.js +60 -0
- package/dist/named-colors.cjs +3 -0
- package/dist/named-colors.d.cts +2 -0
- package/dist/named-colors.d.ts +2 -0
- package/dist/named-colors.js +2 -0
- package/dist/palettes.cjs +8 -0
- package/dist/palettes.d.cts +2 -0
- package/dist/palettes.d.ts +2 -0
- package/dist/palettes.js +7 -0
- package/dist/panel.cjs +80 -0
- package/dist/panel.d.cts +27 -0
- package/dist/panel.d.ts +27 -0
- package/dist/panel.js +27 -0
- package/dist/pencils.cjs +8 -0
- package/dist/pencils.d.cts +2 -0
- package/dist/pencils.d.ts +2 -0
- package/dist/pencils.js +7 -0
- package/dist/primitives/AxisInput.cjs +26 -0
- package/dist/primitives/AxisInput.js +25 -0
- package/dist/primitives/ChannelSlider.cjs +94 -0
- package/dist/primitives/ChannelSlider.d.cts +18 -0
- package/dist/primitives/ChannelSlider.d.ts +18 -0
- package/dist/primitives/ChannelSlider.js +93 -0
- package/dist/primitives/ColorArea.cjs +85 -0
- package/dist/primitives/ColorArea.d.cts +8 -0
- package/dist/primitives/ColorArea.d.ts +8 -0
- package/dist/primitives/ColorArea.js +84 -0
- package/dist/primitives/ColorDisc.cjs +95 -0
- package/dist/primitives/ColorDisc.d.cts +8 -0
- package/dist/primitives/ColorDisc.d.ts +8 -0
- package/dist/primitives/ColorDisc.js +94 -0
- package/dist/primitives/ColorField.cjs +68 -0
- package/dist/primitives/ColorField.d.cts +9 -0
- package/dist/primitives/ColorField.d.ts +9 -0
- package/dist/primitives/ColorField.js +67 -0
- package/dist/primitives/NumberField.cjs +65 -0
- package/dist/primitives/NumberField.d.cts +14 -0
- package/dist/primitives/NumberField.d.ts +14 -0
- package/dist/primitives/NumberField.js +64 -0
- package/dist/primitives/SegmentedControl.cjs +66 -0
- package/dist/primitives/SegmentedControl.d.cts +21 -0
- package/dist/primitives/SegmentedControl.d.ts +21 -0
- package/dist/primitives/SegmentedControl.js +65 -0
- package/dist/primitives/Swatch.cjs +22 -0
- package/dist/primitives/Swatch.d.cts +13 -0
- package/dist/primitives/Swatch.d.ts +13 -0
- package/dist/primitives/Swatch.js +21 -0
- package/dist/primitives/SwatchGrid.cjs +63 -0
- package/dist/primitives/SwatchGrid.d.cts +17 -0
- package/dist/primitives/SwatchGrid.d.ts +17 -0
- package/dist/primitives/SwatchGrid.js +62 -0
- package/dist/primitives/icons.cjs +149 -0
- package/dist/primitives/icons.d.cts +9 -0
- package/dist/primitives/icons.d.ts +9 -0
- package/dist/primitives/icons.js +141 -0
- package/dist/primitives/useEyedropper.cjs +30 -0
- package/dist/primitives/useEyedropper.d.cts +7 -0
- package/dist/primitives/useEyedropper.d.ts +7 -0
- package/dist/primitives/useEyedropper.js +29 -0
- package/dist/sliders.cjs +8 -0
- package/dist/sliders.d.cts +2 -0
- package/dist/sliders.d.ts +2 -0
- package/dist/sliders.js +7 -0
- package/dist/style.css +2 -0
- package/dist/styles/css.cjs +4 -0
- package/dist/styles/css.js +5 -0
- package/dist/wheel.cjs +8 -0
- package/dist/wheel.d.cts +2 -0
- package/dist/wheel.d.ts +2 -0
- package/dist/wheel.js +7 -0
- package/package.json +222 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
const require_useColorStore = require("../core/useColorStore.cjs");
|
|
5
|
+
const require_parse = require("../color/parse.cjs");
|
|
6
|
+
const require_serialize = require("../color/serialize.cjs");
|
|
7
|
+
const require_store = require("../core/store.cjs");
|
|
8
|
+
const require_useFormControl = require("../core/useFormControl.cjs");
|
|
9
|
+
const require_styleInjector = require("../core/styleInjector.cjs");
|
|
10
|
+
const require_css = require("../styles/css.cjs");
|
|
11
|
+
const require_ChromaPanel = require("./ChromaPanel.cjs");
|
|
12
|
+
const require_Popover = require("./Popover.cjs");
|
|
13
|
+
let react = require("react");
|
|
14
|
+
react = require_runtime.__toESM(react, 1);
|
|
15
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
16
|
+
//#region src/components/ColorInput.tsx
|
|
17
|
+
function ColorInput(props) {
|
|
18
|
+
const { open, defaultOpen = false, onOpenChange, name, form, required = false, readOnly = false, autoComplete, validationBehavior = "native", id, "aria-label": ariaLabel = "Choose a colour", triggerClassName, disabled: disabledProp = false, className, classNames = {}, format = "hex", value, defaultValue = require_ChromaPanel.DEFAULT_COLOR, store: externalStore, mode, defaultMode, onModeChange, ...panelProps } = props;
|
|
19
|
+
const triggerId = require_context.useStableId("cp-trigger-");
|
|
20
|
+
const hiddenRef = react.useRef(null);
|
|
21
|
+
const fieldsetDisabled = require_useFormControl.useFieldsetDisabled(hiddenRef);
|
|
22
|
+
const disabled = disabledProp || fieldsetDisabled;
|
|
23
|
+
const [trigger, setTrigger] = react.useState(null);
|
|
24
|
+
const shouldInject = panelProps.injectStyles ?? true;
|
|
25
|
+
react.useEffect(() => {
|
|
26
|
+
if (shouldInject) require_styleInjector.injectStyles(require_css.css, "v2", trigger);
|
|
27
|
+
}, [shouldInject, trigger]);
|
|
28
|
+
const [internalOpen, setInternalOpen] = react.useState(defaultOpen);
|
|
29
|
+
const isOpen = open ?? internalOpen;
|
|
30
|
+
const setOpen = react.useCallback((next) => {
|
|
31
|
+
if (open === void 0) setInternalOpen(next);
|
|
32
|
+
onOpenChange?.(next);
|
|
33
|
+
}, [open, onOpenChange]);
|
|
34
|
+
const ownStore = react.useMemo(() => {
|
|
35
|
+
const seed = value ?? defaultValue;
|
|
36
|
+
const parsed = typeof seed === "string" ? require_parse.parse(seed) : seed;
|
|
37
|
+
return require_store.createColorStore(parsed ?? require_ChromaPanel.FALLBACK);
|
|
38
|
+
}, []);
|
|
39
|
+
const store = externalStore ?? ownStore;
|
|
40
|
+
const [internalMode, setInternalMode] = react.useState(defaultMode);
|
|
41
|
+
const activeMode = mode ?? internalMode;
|
|
42
|
+
const handleModeChange = react.useCallback((next) => {
|
|
43
|
+
if (mode === void 0) setInternalMode(next);
|
|
44
|
+
onModeChange?.(next);
|
|
45
|
+
}, [mode, onModeChange]);
|
|
46
|
+
const closeFromPanel = react.useCallback(() => {
|
|
47
|
+
setOpen(false);
|
|
48
|
+
trigger?.focus({ preventScroll: true });
|
|
49
|
+
}, [setOpen, trigger]);
|
|
50
|
+
const formatRef = react.useRef(format);
|
|
51
|
+
react.useEffect(() => {
|
|
52
|
+
formatRef.current = format;
|
|
53
|
+
});
|
|
54
|
+
require_useColorStore.useTransientColor(store, (c) => {
|
|
55
|
+
trigger?.style.setProperty("--cp-trigger-color", require_serialize.toRgbaString(c));
|
|
56
|
+
const hidden = hiddenRef.current;
|
|
57
|
+
if (hidden !== null) require_useFormControl.setNativeValue(hidden, require_serialize.toFormat(c, formatRef.current));
|
|
58
|
+
});
|
|
59
|
+
require_useFormControl.useFormReset(hiddenRef, () => {
|
|
60
|
+
const parsed = typeof defaultValue === "string" ? require_parse.parse(defaultValue) : defaultValue;
|
|
61
|
+
if (parsed !== null && parsed !== void 0) store.ingest(parsed);
|
|
62
|
+
});
|
|
63
|
+
require_useFormControl.useConstraintValidation(hiddenRef, {
|
|
64
|
+
behavior: validationBehavior,
|
|
65
|
+
required,
|
|
66
|
+
isEmpty: false,
|
|
67
|
+
focusTrigger: () => trigger?.focus()
|
|
68
|
+
});
|
|
69
|
+
const seed = store.get();
|
|
70
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
71
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
72
|
+
ref: setTrigger,
|
|
73
|
+
type: "button",
|
|
74
|
+
id: id ?? triggerId,
|
|
75
|
+
className: require_context.cx("cp-trigger", classNames.trigger, triggerClassName, className),
|
|
76
|
+
style: { ["--cp-trigger-color"]: require_serialize.toRgbaString(seed) },
|
|
77
|
+
"aria-label": ariaLabel,
|
|
78
|
+
"aria-haspopup": "dialog",
|
|
79
|
+
"aria-expanded": isOpen,
|
|
80
|
+
"aria-readonly": readOnly || void 0,
|
|
81
|
+
disabled,
|
|
82
|
+
onClick: () => {
|
|
83
|
+
if (!readOnly) setOpen(!isOpen);
|
|
84
|
+
}
|
|
85
|
+
}),
|
|
86
|
+
name !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
87
|
+
ref: hiddenRef,
|
|
88
|
+
type: "text",
|
|
89
|
+
name,
|
|
90
|
+
form,
|
|
91
|
+
defaultValue: require_serialize.toFormat(seed, format),
|
|
92
|
+
disabled,
|
|
93
|
+
required,
|
|
94
|
+
readOnly,
|
|
95
|
+
autoComplete,
|
|
96
|
+
tabIndex: -1,
|
|
97
|
+
"aria-hidden": "true",
|
|
98
|
+
style: require_useFormControl.visuallyHiddenInput,
|
|
99
|
+
onChange: () => {}
|
|
100
|
+
}),
|
|
101
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Popover.Popover, {
|
|
102
|
+
anchor: trigger,
|
|
103
|
+
open: isOpen,
|
|
104
|
+
onClose: () => setOpen(false),
|
|
105
|
+
className: classNames.popover,
|
|
106
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
107
|
+
className: "cp-dialog",
|
|
108
|
+
role: "dialog",
|
|
109
|
+
"aria-label": ariaLabel,
|
|
110
|
+
"aria-modal": "false",
|
|
111
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ChromaPanel.ChromaPanel, {
|
|
112
|
+
...panelProps,
|
|
113
|
+
store,
|
|
114
|
+
value,
|
|
115
|
+
defaultValue,
|
|
116
|
+
format,
|
|
117
|
+
disabled: disabled || readOnly,
|
|
118
|
+
classNames,
|
|
119
|
+
mode: activeMode,
|
|
120
|
+
onModeChange: handleModeChange,
|
|
121
|
+
onClose: closeFromPanel
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
exports.ColorInput = ColorInput;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChromaPanelProps } from "./ChromaPanel.cjs";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/components/ColorInput.d.ts
|
|
4
|
+
export interface ColorInputProps extends ChromaPanelProps {
|
|
5
|
+
open?: boolean;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
name?: string;
|
|
9
|
+
form?: string;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
autoComplete?: string;
|
|
13
|
+
validationBehavior?: "native" | "aria";
|
|
14
|
+
id?: string;
|
|
15
|
+
"aria-label"?: string;
|
|
16
|
+
triggerClassName?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function ColorInput(props: ColorInputProps): React.ReactElement;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChromaPanelProps } from "./ChromaPanel.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/components/ColorInput.d.ts
|
|
4
|
+
export interface ColorInputProps extends ChromaPanelProps {
|
|
5
|
+
open?: boolean;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
onOpenChange?: (open: boolean) => void;
|
|
8
|
+
name?: string;
|
|
9
|
+
form?: string;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
autoComplete?: string;
|
|
13
|
+
validationBehavior?: "native" | "aria";
|
|
14
|
+
id?: string;
|
|
15
|
+
"aria-label"?: string;
|
|
16
|
+
triggerClassName?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function ColorInput(props: ColorInputProps): React.ReactElement;
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx, useStableId } from "../core/context.js";
|
|
3
|
+
import { useTransientColor } from "../core/useColorStore.js";
|
|
4
|
+
import { parse } from "../color/parse.js";
|
|
5
|
+
import { toFormat, toRgbaString } from "../color/serialize.js";
|
|
6
|
+
import { createColorStore } from "../core/store.js";
|
|
7
|
+
import { setNativeValue, useConstraintValidation, useFieldsetDisabled, useFormReset, visuallyHiddenInput } from "../core/useFormControl.js";
|
|
8
|
+
import { injectStyles } from "../core/styleInjector.js";
|
|
9
|
+
import { css } from "../styles/css.js";
|
|
10
|
+
import { ChromaPanel, DEFAULT_COLOR, FALLBACK } from "./ChromaPanel.js";
|
|
11
|
+
import { Popover } from "./Popover.js";
|
|
12
|
+
import * as React from "react";
|
|
13
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
//#region src/components/ColorInput.tsx
|
|
15
|
+
function ColorInput(props) {
|
|
16
|
+
const { open, defaultOpen = false, onOpenChange, name, form, required = false, readOnly = false, autoComplete, validationBehavior = "native", id, "aria-label": ariaLabel = "Choose a colour", triggerClassName, disabled: disabledProp = false, className, classNames = {}, format = "hex", value, defaultValue = DEFAULT_COLOR, store: externalStore, mode, defaultMode, onModeChange, ...panelProps } = props;
|
|
17
|
+
const triggerId = useStableId("cp-trigger-");
|
|
18
|
+
const hiddenRef = React.useRef(null);
|
|
19
|
+
const fieldsetDisabled = useFieldsetDisabled(hiddenRef);
|
|
20
|
+
const disabled = disabledProp || fieldsetDisabled;
|
|
21
|
+
const [trigger, setTrigger] = React.useState(null);
|
|
22
|
+
const shouldInject = panelProps.injectStyles ?? true;
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
if (shouldInject) injectStyles(css, "v2", trigger);
|
|
25
|
+
}, [shouldInject, trigger]);
|
|
26
|
+
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
27
|
+
const isOpen = open ?? internalOpen;
|
|
28
|
+
const setOpen = React.useCallback((next) => {
|
|
29
|
+
if (open === void 0) setInternalOpen(next);
|
|
30
|
+
onOpenChange?.(next);
|
|
31
|
+
}, [open, onOpenChange]);
|
|
32
|
+
const ownStore = React.useMemo(() => {
|
|
33
|
+
const seed = value ?? defaultValue;
|
|
34
|
+
const parsed = typeof seed === "string" ? parse(seed) : seed;
|
|
35
|
+
return createColorStore(parsed ?? FALLBACK);
|
|
36
|
+
}, []);
|
|
37
|
+
const store = externalStore ?? ownStore;
|
|
38
|
+
const [internalMode, setInternalMode] = React.useState(defaultMode);
|
|
39
|
+
const activeMode = mode ?? internalMode;
|
|
40
|
+
const handleModeChange = React.useCallback((next) => {
|
|
41
|
+
if (mode === void 0) setInternalMode(next);
|
|
42
|
+
onModeChange?.(next);
|
|
43
|
+
}, [mode, onModeChange]);
|
|
44
|
+
const closeFromPanel = React.useCallback(() => {
|
|
45
|
+
setOpen(false);
|
|
46
|
+
trigger?.focus({ preventScroll: true });
|
|
47
|
+
}, [setOpen, trigger]);
|
|
48
|
+
const formatRef = React.useRef(format);
|
|
49
|
+
React.useEffect(() => {
|
|
50
|
+
formatRef.current = format;
|
|
51
|
+
});
|
|
52
|
+
useTransientColor(store, (c) => {
|
|
53
|
+
trigger?.style.setProperty("--cp-trigger-color", toRgbaString(c));
|
|
54
|
+
const hidden = hiddenRef.current;
|
|
55
|
+
if (hidden !== null) setNativeValue(hidden, toFormat(c, formatRef.current));
|
|
56
|
+
});
|
|
57
|
+
useFormReset(hiddenRef, () => {
|
|
58
|
+
const parsed = typeof defaultValue === "string" ? parse(defaultValue) : defaultValue;
|
|
59
|
+
if (parsed !== null && parsed !== void 0) store.ingest(parsed);
|
|
60
|
+
});
|
|
61
|
+
useConstraintValidation(hiddenRef, {
|
|
62
|
+
behavior: validationBehavior,
|
|
63
|
+
required,
|
|
64
|
+
isEmpty: false,
|
|
65
|
+
focusTrigger: () => trigger?.focus()
|
|
66
|
+
});
|
|
67
|
+
const seed = store.get();
|
|
68
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
+
/* @__PURE__ */ jsx("button", {
|
|
70
|
+
ref: setTrigger,
|
|
71
|
+
type: "button",
|
|
72
|
+
id: id ?? triggerId,
|
|
73
|
+
className: cx("cp-trigger", classNames.trigger, triggerClassName, className),
|
|
74
|
+
style: { ["--cp-trigger-color"]: toRgbaString(seed) },
|
|
75
|
+
"aria-label": ariaLabel,
|
|
76
|
+
"aria-haspopup": "dialog",
|
|
77
|
+
"aria-expanded": isOpen,
|
|
78
|
+
"aria-readonly": readOnly || void 0,
|
|
79
|
+
disabled,
|
|
80
|
+
onClick: () => {
|
|
81
|
+
if (!readOnly) setOpen(!isOpen);
|
|
82
|
+
}
|
|
83
|
+
}),
|
|
84
|
+
name !== void 0 && /* @__PURE__ */ jsx("input", {
|
|
85
|
+
ref: hiddenRef,
|
|
86
|
+
type: "text",
|
|
87
|
+
name,
|
|
88
|
+
form,
|
|
89
|
+
defaultValue: toFormat(seed, format),
|
|
90
|
+
disabled,
|
|
91
|
+
required,
|
|
92
|
+
readOnly,
|
|
93
|
+
autoComplete,
|
|
94
|
+
tabIndex: -1,
|
|
95
|
+
"aria-hidden": "true",
|
|
96
|
+
style: visuallyHiddenInput,
|
|
97
|
+
onChange: () => {}
|
|
98
|
+
}),
|
|
99
|
+
/* @__PURE__ */ jsx(Popover, {
|
|
100
|
+
anchor: trigger,
|
|
101
|
+
open: isOpen,
|
|
102
|
+
onClose: () => setOpen(false),
|
|
103
|
+
className: classNames.popover,
|
|
104
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
105
|
+
className: "cp-dialog",
|
|
106
|
+
role: "dialog",
|
|
107
|
+
"aria-label": ariaLabel,
|
|
108
|
+
"aria-modal": "false",
|
|
109
|
+
children: /* @__PURE__ */ jsx(ChromaPanel, {
|
|
110
|
+
...panelProps,
|
|
111
|
+
store,
|
|
112
|
+
value,
|
|
113
|
+
defaultValue,
|
|
114
|
+
format,
|
|
115
|
+
disabled: disabled || readOnly,
|
|
116
|
+
classNames,
|
|
117
|
+
mode: activeMode,
|
|
118
|
+
onModeChange: handleModeChange,
|
|
119
|
+
onClose: closeFromPanel
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
] });
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
export { ColorInput };
|
|
127
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
const require_SegmentedControl = require("../primitives/SegmentedControl.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
react = require_runtime.__toESM(react, 1);
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
//#region src/components/ModeToolbar.tsx
|
|
9
|
+
function ModeToolbar(props) {
|
|
10
|
+
const { modes, activeId, onSelect } = props;
|
|
11
|
+
const { classNames, idPrefix, disabled } = require_context.usePanel();
|
|
12
|
+
const items = react.useMemo(() => modes.map((mode) => {
|
|
13
|
+
const Icon = mode.icon;
|
|
14
|
+
return {
|
|
15
|
+
id: mode.id,
|
|
16
|
+
label: mode.label,
|
|
17
|
+
content: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {})
|
|
18
|
+
};
|
|
19
|
+
}), [modes]);
|
|
20
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SegmentedControl.SegmentedControl, {
|
|
21
|
+
items,
|
|
22
|
+
value: activeId,
|
|
23
|
+
onChange: onSelect,
|
|
24
|
+
ariaLabel: "Picker mode",
|
|
25
|
+
disabled,
|
|
26
|
+
segmentId: (id) => `${idPrefix}-tab-${id}`,
|
|
27
|
+
controls: (id) => `${idPrefix}-panel-${id}`,
|
|
28
|
+
className: require_context.cx("cp-toolbar", classNames.toolbar),
|
|
29
|
+
tabClassName: require_context.cx(classNames.tab)
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
exports.ModeToolbar = ModeToolbar;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PickerMode } from "../modes/registry.cjs";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/components/ModeToolbar.d.ts
|
|
4
|
+
export interface ModeToolbarProps {
|
|
5
|
+
modes: PickerMode[];
|
|
6
|
+
activeId: string;
|
|
7
|
+
onSelect: (id: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function ModeToolbar(props: ModeToolbarProps): React.ReactElement;
|
|
10
|
+
//#endregion
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PickerMode } from "../modes/registry.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/components/ModeToolbar.d.ts
|
|
4
|
+
export interface ModeToolbarProps {
|
|
5
|
+
modes: PickerMode[];
|
|
6
|
+
activeId: string;
|
|
7
|
+
onSelect: (id: string) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function ModeToolbar(props: ModeToolbarProps): React.ReactElement;
|
|
10
|
+
//#endregion
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx, usePanel } from "../core/context.js";
|
|
3
|
+
import { SegmentedControl } from "../primitives/SegmentedControl.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/ModeToolbar.tsx
|
|
7
|
+
function ModeToolbar(props) {
|
|
8
|
+
const { modes, activeId, onSelect } = props;
|
|
9
|
+
const { classNames, idPrefix, disabled } = usePanel();
|
|
10
|
+
const items = React.useMemo(() => modes.map((mode) => {
|
|
11
|
+
const Icon = mode.icon;
|
|
12
|
+
return {
|
|
13
|
+
id: mode.id,
|
|
14
|
+
label: mode.label,
|
|
15
|
+
content: /* @__PURE__ */ jsx(Icon, {})
|
|
16
|
+
};
|
|
17
|
+
}), [modes]);
|
|
18
|
+
return /* @__PURE__ */ jsx(SegmentedControl, {
|
|
19
|
+
items,
|
|
20
|
+
value: activeId,
|
|
21
|
+
onChange: onSelect,
|
|
22
|
+
ariaLabel: "Picker mode",
|
|
23
|
+
disabled,
|
|
24
|
+
segmentId: (id) => `${idPrefix}-tab-${id}`,
|
|
25
|
+
controls: (id) => `${idPrefix}-panel-${id}`,
|
|
26
|
+
className: cx("cp-toolbar", classNames.toolbar),
|
|
27
|
+
tabClassName: cx(classNames.tab)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ModeToolbar };
|
|
32
|
+
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
const require_parse = require("../color/parse.cjs");
|
|
5
|
+
const require_serialize = require("../color/serialize.cjs");
|
|
6
|
+
const require_icons = require("../primitives/icons.cjs");
|
|
7
|
+
const require_useScrollFade = require("../core/useScrollFade.cjs");
|
|
8
|
+
const require_useEyedropper = require("../primitives/useEyedropper.cjs");
|
|
9
|
+
let react = require("react");
|
|
10
|
+
react = require_runtime.__toESM(react, 1);
|
|
11
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
|
+
//#region src/components/PanelFooter.tsx
|
|
13
|
+
function PanelFooter() {
|
|
14
|
+
const { store, classNames, options, disabled } = require_context.usePanel();
|
|
15
|
+
const { supported, pick } = require_useEyedropper.useEyedropper();
|
|
16
|
+
const handlePick = async () => {
|
|
17
|
+
const hex = await pick();
|
|
18
|
+
if (hex === null) return;
|
|
19
|
+
const parsed = require_parse.parse(hex);
|
|
20
|
+
if (parsed === null) return;
|
|
21
|
+
store.ingest(parsed);
|
|
22
|
+
store.commit();
|
|
23
|
+
};
|
|
24
|
+
const recentsRef = react.useRef(null);
|
|
25
|
+
const [current, setCurrent] = react.useState(null);
|
|
26
|
+
react.useEffect(() => store.subscribeCommit((c) => setCurrent(require_serialize.toHex(c).toLowerCase())), [store]);
|
|
27
|
+
const recents = options.showRecentColors ? options.recentColors.filter((color) => {
|
|
28
|
+
if (current === null) return true;
|
|
29
|
+
const parsed = require_parse.parse(color);
|
|
30
|
+
return (parsed === null ? color : require_serialize.toHex(parsed)).toLowerCase() !== current;
|
|
31
|
+
}).slice(0, 10) : [];
|
|
32
|
+
const showEyedropper = options.showEyedropper && supported;
|
|
33
|
+
require_useScrollFade.useScrollFade(recentsRef, recents.length, "x");
|
|
34
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
35
|
+
className: require_context.cx("cp-footer", classNames.footer),
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
38
|
+
className: "cp-preview",
|
|
39
|
+
"aria-hidden": "true"
|
|
40
|
+
}),
|
|
41
|
+
recents.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
42
|
+
ref: recentsRef,
|
|
43
|
+
className: "cp-recents",
|
|
44
|
+
"aria-label": "Recent colours",
|
|
45
|
+
children: recents.map((color, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
46
|
+
type: "button",
|
|
47
|
+
className: require_context.cx("cp-swatch", "cp-swatch-round", classNames.swatch),
|
|
48
|
+
style: { ["--cp-swatch-color"]: color },
|
|
49
|
+
"aria-label": `Recent colour ${color}`,
|
|
50
|
+
disabled,
|
|
51
|
+
onClick: () => {
|
|
52
|
+
const parsed = require_parse.parse(color);
|
|
53
|
+
if (parsed === null) return;
|
|
54
|
+
store.ingest(parsed);
|
|
55
|
+
store.commit();
|
|
56
|
+
}
|
|
57
|
+
}) }, `${color}-${index}`))
|
|
58
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cp-footer-spacer" }),
|
|
59
|
+
showEyedropper && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
60
|
+
type: "button",
|
|
61
|
+
className: "cp-icon-button",
|
|
62
|
+
"aria-label": "Pick a colour from the screen",
|
|
63
|
+
title: "Pick a colour from the screen",
|
|
64
|
+
disabled,
|
|
65
|
+
onClick: () => {
|
|
66
|
+
handlePick();
|
|
67
|
+
},
|
|
68
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons.EyedropperIcon, {})
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function pushRecent(list, hex, limit = 10) {
|
|
74
|
+
const key = hex.toLowerCase();
|
|
75
|
+
return [hex, ...list.filter((c) => {
|
|
76
|
+
const parsed = require_parse.parse(c);
|
|
77
|
+
return parsed === null ? c.toLowerCase() !== key : require_serialize.toHex(parsed).toLowerCase() !== key;
|
|
78
|
+
})].slice(0, limit);
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
exports.PanelFooter = PanelFooter;
|
|
82
|
+
exports.pushRecent = pushRecent;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx, usePanel } from "../core/context.js";
|
|
3
|
+
import { parse } from "../color/parse.js";
|
|
4
|
+
import { toHex } from "../color/serialize.js";
|
|
5
|
+
import { EyedropperIcon } from "../primitives/icons.js";
|
|
6
|
+
import { useScrollFade } from "../core/useScrollFade.js";
|
|
7
|
+
import { useEyedropper } from "../primitives/useEyedropper.js";
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region src/components/PanelFooter.tsx
|
|
11
|
+
function PanelFooter() {
|
|
12
|
+
const { store, classNames, options, disabled } = usePanel();
|
|
13
|
+
const { supported, pick } = useEyedropper();
|
|
14
|
+
const handlePick = async () => {
|
|
15
|
+
const hex = await pick();
|
|
16
|
+
if (hex === null) return;
|
|
17
|
+
const parsed = parse(hex);
|
|
18
|
+
if (parsed === null) return;
|
|
19
|
+
store.ingest(parsed);
|
|
20
|
+
store.commit();
|
|
21
|
+
};
|
|
22
|
+
const recentsRef = React.useRef(null);
|
|
23
|
+
const [current, setCurrent] = React.useState(null);
|
|
24
|
+
React.useEffect(() => store.subscribeCommit((c) => setCurrent(toHex(c).toLowerCase())), [store]);
|
|
25
|
+
const recents = options.showRecentColors ? options.recentColors.filter((color) => {
|
|
26
|
+
if (current === null) return true;
|
|
27
|
+
const parsed = parse(color);
|
|
28
|
+
return (parsed === null ? color : toHex(parsed)).toLowerCase() !== current;
|
|
29
|
+
}).slice(0, 10) : [];
|
|
30
|
+
const showEyedropper = options.showEyedropper && supported;
|
|
31
|
+
useScrollFade(recentsRef, recents.length, "x");
|
|
32
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
33
|
+
className: cx("cp-footer", classNames.footer),
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ jsx("div", {
|
|
36
|
+
className: "cp-preview",
|
|
37
|
+
"aria-hidden": "true"
|
|
38
|
+
}),
|
|
39
|
+
recents.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
40
|
+
ref: recentsRef,
|
|
41
|
+
className: "cp-recents",
|
|
42
|
+
"aria-label": "Recent colours",
|
|
43
|
+
children: recents.map((color, index) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
44
|
+
type: "button",
|
|
45
|
+
className: cx("cp-swatch", "cp-swatch-round", classNames.swatch),
|
|
46
|
+
style: { ["--cp-swatch-color"]: color },
|
|
47
|
+
"aria-label": `Recent colour ${color}`,
|
|
48
|
+
disabled,
|
|
49
|
+
onClick: () => {
|
|
50
|
+
const parsed = parse(color);
|
|
51
|
+
if (parsed === null) return;
|
|
52
|
+
store.ingest(parsed);
|
|
53
|
+
store.commit();
|
|
54
|
+
}
|
|
55
|
+
}) }, `${color}-${index}`))
|
|
56
|
+
}) : /* @__PURE__ */ jsx("div", { className: "cp-footer-spacer" }),
|
|
57
|
+
showEyedropper && /* @__PURE__ */ jsx("button", {
|
|
58
|
+
type: "button",
|
|
59
|
+
className: "cp-icon-button",
|
|
60
|
+
"aria-label": "Pick a colour from the screen",
|
|
61
|
+
title: "Pick a colour from the screen",
|
|
62
|
+
disabled,
|
|
63
|
+
onClick: () => {
|
|
64
|
+
handlePick();
|
|
65
|
+
},
|
|
66
|
+
children: /* @__PURE__ */ jsx(EyedropperIcon, {})
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function pushRecent(list, hex, limit = 10) {
|
|
72
|
+
const key = hex.toLowerCase();
|
|
73
|
+
return [hex, ...list.filter((c) => {
|
|
74
|
+
const parsed = parse(c);
|
|
75
|
+
return parsed === null ? c.toLowerCase() !== key : toHex(parsed).toLowerCase() !== key;
|
|
76
|
+
})].slice(0, limit);
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { PanelFooter, pushRecent };
|
|
80
|
+
|