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,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
const require_convert = require("../color/convert.cjs");
|
|
5
|
+
const require_useColorStore = require("../core/useColorStore.cjs");
|
|
6
|
+
let react = require("react");
|
|
7
|
+
react = require_runtime.__toESM(react, 1);
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
//#region src/primitives/NumberField.tsx
|
|
10
|
+
function NumberField(props) {
|
|
11
|
+
const { label, min, max, step, read, write, className } = props;
|
|
12
|
+
const { store, disabled, classNames } = require_context.usePanel();
|
|
13
|
+
const id = require_context.useStableId("cp-num-");
|
|
14
|
+
const inputRef = react.useRef(null);
|
|
15
|
+
const focused = react.useRef(false);
|
|
16
|
+
const fns = react.useRef({
|
|
17
|
+
read,
|
|
18
|
+
write
|
|
19
|
+
});
|
|
20
|
+
react.useEffect(() => {
|
|
21
|
+
fns.current = {
|
|
22
|
+
read,
|
|
23
|
+
write
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
require_useColorStore.useTransientColor(store, (c) => {
|
|
27
|
+
if (focused.current) return;
|
|
28
|
+
const el = inputRef.current;
|
|
29
|
+
if (el !== null) el.value = String(Math.round(fns.current.read(c)));
|
|
30
|
+
});
|
|
31
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
32
|
+
className: require_context.cx("cp-field", classNames.field, className),
|
|
33
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
34
|
+
className: "cp-field-label",
|
|
35
|
+
htmlFor: id,
|
|
36
|
+
children: label
|
|
37
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
38
|
+
ref: inputRef,
|
|
39
|
+
id,
|
|
40
|
+
className: "cp-input",
|
|
41
|
+
type: "number",
|
|
42
|
+
inputMode: "numeric",
|
|
43
|
+
min,
|
|
44
|
+
max,
|
|
45
|
+
step: step ?? 1,
|
|
46
|
+
defaultValue: Math.round(read(store.get())),
|
|
47
|
+
disabled,
|
|
48
|
+
onFocus: () => {
|
|
49
|
+
focused.current = true;
|
|
50
|
+
},
|
|
51
|
+
onChange: (e) => {
|
|
52
|
+
const raw = e.currentTarget.valueAsNumber;
|
|
53
|
+
if (Number.isNaN(raw)) return;
|
|
54
|
+
store.set(fns.current.write(require_convert.clamp(raw, min, max), store.get()));
|
|
55
|
+
},
|
|
56
|
+
onBlur: (e) => {
|
|
57
|
+
focused.current = false;
|
|
58
|
+
e.currentTarget.value = String(Math.round(fns.current.read(store.get())));
|
|
59
|
+
store.commit();
|
|
60
|
+
}
|
|
61
|
+
})]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
exports.NumberField = NumberField;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Hsva } from "../color/types.cjs";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/primitives/NumberField.d.ts
|
|
4
|
+
export interface NumberFieldProps {
|
|
5
|
+
label: string;
|
|
6
|
+
min: number;
|
|
7
|
+
max: number;
|
|
8
|
+
step?: number;
|
|
9
|
+
read: (color: Hsva) => number;
|
|
10
|
+
write: (value: number, current: Hsva) => Hsva;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function NumberField(props: NumberFieldProps): React.ReactElement;
|
|
14
|
+
//#endregion
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Hsva } from "../color/types.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/primitives/NumberField.d.ts
|
|
4
|
+
export interface NumberFieldProps {
|
|
5
|
+
label: string;
|
|
6
|
+
min: number;
|
|
7
|
+
max: number;
|
|
8
|
+
step?: number;
|
|
9
|
+
read: (color: Hsva) => number;
|
|
10
|
+
write: (value: number, current: Hsva) => Hsva;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function NumberField(props: NumberFieldProps): React.ReactElement;
|
|
14
|
+
//#endregion
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx, usePanel, useStableId } from "../core/context.js";
|
|
3
|
+
import { clamp } from "../color/convert.js";
|
|
4
|
+
import { useTransientColor } from "../core/useColorStore.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/primitives/NumberField.tsx
|
|
8
|
+
function NumberField(props) {
|
|
9
|
+
const { label, min, max, step, read, write, className } = props;
|
|
10
|
+
const { store, disabled, classNames } = usePanel();
|
|
11
|
+
const id = useStableId("cp-num-");
|
|
12
|
+
const inputRef = React.useRef(null);
|
|
13
|
+
const focused = React.useRef(false);
|
|
14
|
+
const fns = React.useRef({
|
|
15
|
+
read,
|
|
16
|
+
write
|
|
17
|
+
});
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
fns.current = {
|
|
20
|
+
read,
|
|
21
|
+
write
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
useTransientColor(store, (c) => {
|
|
25
|
+
if (focused.current) return;
|
|
26
|
+
const el = inputRef.current;
|
|
27
|
+
if (el !== null) el.value = String(Math.round(fns.current.read(c)));
|
|
28
|
+
});
|
|
29
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
30
|
+
className: cx("cp-field", classNames.field, className),
|
|
31
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
32
|
+
className: "cp-field-label",
|
|
33
|
+
htmlFor: id,
|
|
34
|
+
children: label
|
|
35
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
36
|
+
ref: inputRef,
|
|
37
|
+
id,
|
|
38
|
+
className: "cp-input",
|
|
39
|
+
type: "number",
|
|
40
|
+
inputMode: "numeric",
|
|
41
|
+
min,
|
|
42
|
+
max,
|
|
43
|
+
step: step ?? 1,
|
|
44
|
+
defaultValue: Math.round(read(store.get())),
|
|
45
|
+
disabled,
|
|
46
|
+
onFocus: () => {
|
|
47
|
+
focused.current = true;
|
|
48
|
+
},
|
|
49
|
+
onChange: (e) => {
|
|
50
|
+
const raw = e.currentTarget.valueAsNumber;
|
|
51
|
+
if (Number.isNaN(raw)) return;
|
|
52
|
+
store.set(fns.current.write(clamp(raw, min, max), store.get()));
|
|
53
|
+
},
|
|
54
|
+
onBlur: (e) => {
|
|
55
|
+
focused.current = false;
|
|
56
|
+
e.currentTarget.value = String(Math.round(fns.current.read(store.get())));
|
|
57
|
+
store.commit();
|
|
58
|
+
}
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { NumberField };
|
|
64
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
let react = require("react");
|
|
5
|
+
react = require_runtime.__toESM(react, 1);
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
//#region src/primitives/SegmentedControl.tsx
|
|
8
|
+
function SegmentedControl(props) {
|
|
9
|
+
const { items, value, onChange, size = "md", ariaLabel, controls, segmentId, disabled = false, className, tabClassName } = props;
|
|
10
|
+
const refs = react.useRef([]);
|
|
11
|
+
const activeIndex = Math.max(0, items.findIndex((item) => item.id === value));
|
|
12
|
+
const move = (to) => {
|
|
13
|
+
const wrapped = (to + items.length) % items.length;
|
|
14
|
+
const item = items[wrapped];
|
|
15
|
+
if (item === void 0) return;
|
|
16
|
+
onChange(item.id);
|
|
17
|
+
refs.current[wrapped]?.focus();
|
|
18
|
+
};
|
|
19
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
20
|
+
className: require_context.cx("cp-seg", size === "sm" && "cp-seg-sm", className),
|
|
21
|
+
role: "tablist",
|
|
22
|
+
"aria-label": ariaLabel,
|
|
23
|
+
"aria-orientation": "horizontal",
|
|
24
|
+
style: {
|
|
25
|
+
["--cp-seg-count"]: items.length,
|
|
26
|
+
["--cp-seg-active"]: activeIndex
|
|
27
|
+
},
|
|
28
|
+
children: items.map((item, index) => {
|
|
29
|
+
const selected = item.id === value;
|
|
30
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
31
|
+
ref: (el) => {
|
|
32
|
+
refs.current[index] = el;
|
|
33
|
+
},
|
|
34
|
+
type: "button",
|
|
35
|
+
role: "tab",
|
|
36
|
+
id: segmentId?.(item.id),
|
|
37
|
+
"aria-controls": controls?.(item.id),
|
|
38
|
+
"aria-selected": selected,
|
|
39
|
+
"aria-label": item.label,
|
|
40
|
+
title: item.label,
|
|
41
|
+
tabIndex: selected ? 0 : -1,
|
|
42
|
+
disabled,
|
|
43
|
+
className: require_context.cx("cp-tab", tabClassName),
|
|
44
|
+
onClick: () => onChange(item.id),
|
|
45
|
+
onKeyDown: (event) => {
|
|
46
|
+
if (event.key === "ArrowRight") {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
move(index + 1);
|
|
49
|
+
} else if (event.key === "ArrowLeft") {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
move(index - 1);
|
|
52
|
+
} else if (event.key === "Home") {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
move(0);
|
|
55
|
+
} else if (event.key === "End") {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
move(items.length - 1);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
children: item.content
|
|
61
|
+
}, item.id);
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
exports.SegmentedControl = SegmentedControl;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/SegmentedControl.d.ts
|
|
3
|
+
export interface SegmentedItem {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
content: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export interface SegmentedControlProps {
|
|
9
|
+
items: SegmentedItem[];
|
|
10
|
+
value: string;
|
|
11
|
+
onChange: (id: string) => void;
|
|
12
|
+
size?: "md" | "sm";
|
|
13
|
+
ariaLabel: string;
|
|
14
|
+
controls?: (id: string) => string;
|
|
15
|
+
segmentId?: (id: string) => string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
tabClassName?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function SegmentedControl(props: SegmentedControlProps): React.ReactElement;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/SegmentedControl.d.ts
|
|
3
|
+
export interface SegmentedItem {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
content: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export interface SegmentedControlProps {
|
|
9
|
+
items: SegmentedItem[];
|
|
10
|
+
value: string;
|
|
11
|
+
onChange: (id: string) => void;
|
|
12
|
+
size?: "md" | "sm";
|
|
13
|
+
ariaLabel: string;
|
|
14
|
+
controls?: (id: string) => string;
|
|
15
|
+
segmentId?: (id: string) => string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
tabClassName?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function SegmentedControl(props: SegmentedControlProps): React.ReactElement;
|
|
21
|
+
//#endregion
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../core/context.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/primitives/SegmentedControl.tsx
|
|
6
|
+
function SegmentedControl(props) {
|
|
7
|
+
const { items, value, onChange, size = "md", ariaLabel, controls, segmentId, disabled = false, className, tabClassName } = props;
|
|
8
|
+
const refs = React.useRef([]);
|
|
9
|
+
const activeIndex = Math.max(0, items.findIndex((item) => item.id === value));
|
|
10
|
+
const move = (to) => {
|
|
11
|
+
const wrapped = (to + items.length) % items.length;
|
|
12
|
+
const item = items[wrapped];
|
|
13
|
+
if (item === void 0) return;
|
|
14
|
+
onChange(item.id);
|
|
15
|
+
refs.current[wrapped]?.focus();
|
|
16
|
+
};
|
|
17
|
+
return /* @__PURE__ */ jsx("div", {
|
|
18
|
+
className: cx("cp-seg", size === "sm" && "cp-seg-sm", className),
|
|
19
|
+
role: "tablist",
|
|
20
|
+
"aria-label": ariaLabel,
|
|
21
|
+
"aria-orientation": "horizontal",
|
|
22
|
+
style: {
|
|
23
|
+
["--cp-seg-count"]: items.length,
|
|
24
|
+
["--cp-seg-active"]: activeIndex
|
|
25
|
+
},
|
|
26
|
+
children: items.map((item, index) => {
|
|
27
|
+
const selected = item.id === value;
|
|
28
|
+
return /* @__PURE__ */ jsx("button", {
|
|
29
|
+
ref: (el) => {
|
|
30
|
+
refs.current[index] = el;
|
|
31
|
+
},
|
|
32
|
+
type: "button",
|
|
33
|
+
role: "tab",
|
|
34
|
+
id: segmentId?.(item.id),
|
|
35
|
+
"aria-controls": controls?.(item.id),
|
|
36
|
+
"aria-selected": selected,
|
|
37
|
+
"aria-label": item.label,
|
|
38
|
+
title: item.label,
|
|
39
|
+
tabIndex: selected ? 0 : -1,
|
|
40
|
+
disabled,
|
|
41
|
+
className: cx("cp-tab", tabClassName),
|
|
42
|
+
onClick: () => onChange(item.id),
|
|
43
|
+
onKeyDown: (event) => {
|
|
44
|
+
if (event.key === "ArrowRight") {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
move(index + 1);
|
|
47
|
+
} else if (event.key === "ArrowLeft") {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
move(index - 1);
|
|
50
|
+
} else if (event.key === "Home") {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
move(0);
|
|
53
|
+
} else if (event.key === "End") {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
move(items.length - 1);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
children: item.content
|
|
59
|
+
}, item.id);
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { SegmentedControl };
|
|
65
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
let react = require("react");
|
|
5
|
+
react = require_runtime.__toESM(react, 1);
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
//#region src/primitives/Swatch.tsx
|
|
8
|
+
function Swatch(props) {
|
|
9
|
+
const { color, label, matchKey, round, disabled, onSelect, className } = props;
|
|
10
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
11
|
+
type: "button",
|
|
12
|
+
className: require_context.cx("cp-swatch", round === true && "cp-swatch-round", className),
|
|
13
|
+
style: { ["--cp-swatch-color"]: color },
|
|
14
|
+
"data-cp-color": matchKey ?? color,
|
|
15
|
+
"aria-label": label ?? color,
|
|
16
|
+
"aria-pressed": false,
|
|
17
|
+
disabled,
|
|
18
|
+
onClick: () => onSelect?.(color)
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
exports.Swatch = Swatch;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/Swatch.d.ts
|
|
3
|
+
export interface SwatchProps {
|
|
4
|
+
color: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
matchKey?: string;
|
|
7
|
+
round?: boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
onSelect?: (color: string) => void;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function Swatch(props: SwatchProps): React.ReactElement;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/Swatch.d.ts
|
|
3
|
+
export interface SwatchProps {
|
|
4
|
+
color: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
matchKey?: string;
|
|
7
|
+
round?: boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
onSelect?: (color: string) => void;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function Swatch(props: SwatchProps): React.ReactElement;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../core/context.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/primitives/Swatch.tsx
|
|
6
|
+
function Swatch(props) {
|
|
7
|
+
const { color, label, matchKey, round, disabled, onSelect, className } = props;
|
|
8
|
+
return /* @__PURE__ */ jsx("button", {
|
|
9
|
+
type: "button",
|
|
10
|
+
className: cx("cp-swatch", round === true && "cp-swatch-round", className),
|
|
11
|
+
style: { ["--cp-swatch-color"]: color },
|
|
12
|
+
"data-cp-color": matchKey ?? color,
|
|
13
|
+
"aria-label": label ?? color,
|
|
14
|
+
"aria-pressed": false,
|
|
15
|
+
disabled,
|
|
16
|
+
onClick: () => onSelect?.(color)
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { Swatch };
|
|
21
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
let react = require("react");
|
|
8
|
+
react = require_runtime.__toESM(react, 1);
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
//#region src/primitives/SwatchGrid.tsx
|
|
11
|
+
function SwatchGrid(props) {
|
|
12
|
+
const { swatches, columns = 10, variant = "spaced", round = false, label, className } = props;
|
|
13
|
+
const { store, disabled, classNames } = require_context.usePanel();
|
|
14
|
+
const gridRef = react.useRef(null);
|
|
15
|
+
const selected = react.useRef(null);
|
|
16
|
+
require_useColorStore.useTransientColor(store, (c) => {
|
|
17
|
+
const grid = gridRef.current;
|
|
18
|
+
if (grid === null) return;
|
|
19
|
+
const hex = require_serialize.toHex(c);
|
|
20
|
+
const next = grid.querySelector(`[data-cp-color="${hex}"]`);
|
|
21
|
+
if (next === selected.current) return;
|
|
22
|
+
selected.current?.setAttribute("aria-pressed", "false");
|
|
23
|
+
next?.setAttribute("aria-pressed", "true");
|
|
24
|
+
selected.current = next;
|
|
25
|
+
});
|
|
26
|
+
const handleClick = (event) => {
|
|
27
|
+
const target = event.target.closest("[data-cp-color]");
|
|
28
|
+
if (target === null) return;
|
|
29
|
+
const parsed = require_parse.parse(target.getAttribute("data-cp-color") ?? "");
|
|
30
|
+
if (parsed === null) return;
|
|
31
|
+
store.ingest(parsed);
|
|
32
|
+
store.commit();
|
|
33
|
+
};
|
|
34
|
+
const grid = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
35
|
+
ref: gridRef,
|
|
36
|
+
className: require_context.cx("cp-swatch-grid", variant === "spaced" && className),
|
|
37
|
+
style: { ["--cp-columns"]: columns },
|
|
38
|
+
"data-cp-variant": variant,
|
|
39
|
+
"data-cp-large": swatches.length > 1e3 ? "true" : void 0,
|
|
40
|
+
"aria-label": label,
|
|
41
|
+
onClick: handleClick,
|
|
42
|
+
children: swatches.map((swatch, index) => {
|
|
43
|
+
const key = require_parse.parse(swatch.color);
|
|
44
|
+
const match = key === null ? swatch.color : require_serialize.toHex(key);
|
|
45
|
+
return /* @__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", round && "cp-swatch-round", classNames.swatch),
|
|
48
|
+
style: { ["--cp-swatch-color"]: swatch.color },
|
|
49
|
+
"data-cp-color": match,
|
|
50
|
+
"aria-label": swatch.name ?? swatch.color,
|
|
51
|
+
"aria-pressed": false,
|
|
52
|
+
disabled
|
|
53
|
+
}) }, `${swatch.color}-${index}`);
|
|
54
|
+
})
|
|
55
|
+
});
|
|
56
|
+
if (variant === "mosaic") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
57
|
+
className: require_context.cx("cp-mosaic", className),
|
|
58
|
+
children: grid
|
|
59
|
+
});
|
|
60
|
+
return grid;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
exports.SwatchGrid = SwatchGrid;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/SwatchGrid.d.ts
|
|
3
|
+
export interface SwatchEntry {
|
|
4
|
+
color: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
}
|
|
7
|
+
export type SwatchVariant = "mosaic" | "spaced";
|
|
8
|
+
export interface SwatchGridProps {
|
|
9
|
+
swatches: SwatchEntry[];
|
|
10
|
+
columns?: number;
|
|
11
|
+
variant?: SwatchVariant;
|
|
12
|
+
round?: boolean;
|
|
13
|
+
label: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function SwatchGrid(props: SwatchGridProps): React.ReactElement;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/SwatchGrid.d.ts
|
|
3
|
+
export interface SwatchEntry {
|
|
4
|
+
color: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
}
|
|
7
|
+
export type SwatchVariant = "mosaic" | "spaced";
|
|
8
|
+
export interface SwatchGridProps {
|
|
9
|
+
swatches: SwatchEntry[];
|
|
10
|
+
columns?: number;
|
|
11
|
+
variant?: SwatchVariant;
|
|
12
|
+
round?: boolean;
|
|
13
|
+
label: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function SwatchGrid(props: SwatchGridProps): React.ReactElement;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx, usePanel } from "../core/context.js";
|
|
3
|
+
import { useTransientColor } from "../core/useColorStore.js";
|
|
4
|
+
import { parse } from "../color/parse.js";
|
|
5
|
+
import { toHex } from "../color/serialize.js";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region src/primitives/SwatchGrid.tsx
|
|
9
|
+
function SwatchGrid(props) {
|
|
10
|
+
const { swatches, columns = 10, variant = "spaced", round = false, label, className } = props;
|
|
11
|
+
const { store, disabled, classNames } = usePanel();
|
|
12
|
+
const gridRef = React.useRef(null);
|
|
13
|
+
const selected = React.useRef(null);
|
|
14
|
+
useTransientColor(store, (c) => {
|
|
15
|
+
const grid = gridRef.current;
|
|
16
|
+
if (grid === null) return;
|
|
17
|
+
const hex = toHex(c);
|
|
18
|
+
const next = grid.querySelector(`[data-cp-color="${hex}"]`);
|
|
19
|
+
if (next === selected.current) return;
|
|
20
|
+
selected.current?.setAttribute("aria-pressed", "false");
|
|
21
|
+
next?.setAttribute("aria-pressed", "true");
|
|
22
|
+
selected.current = next;
|
|
23
|
+
});
|
|
24
|
+
const handleClick = (event) => {
|
|
25
|
+
const target = event.target.closest("[data-cp-color]");
|
|
26
|
+
if (target === null) return;
|
|
27
|
+
const parsed = parse(target.getAttribute("data-cp-color") ?? "");
|
|
28
|
+
if (parsed === null) return;
|
|
29
|
+
store.ingest(parsed);
|
|
30
|
+
store.commit();
|
|
31
|
+
};
|
|
32
|
+
const grid = /* @__PURE__ */ jsx("ul", {
|
|
33
|
+
ref: gridRef,
|
|
34
|
+
className: cx("cp-swatch-grid", variant === "spaced" && className),
|
|
35
|
+
style: { ["--cp-columns"]: columns },
|
|
36
|
+
"data-cp-variant": variant,
|
|
37
|
+
"data-cp-large": swatches.length > 1e3 ? "true" : void 0,
|
|
38
|
+
"aria-label": label,
|
|
39
|
+
onClick: handleClick,
|
|
40
|
+
children: swatches.map((swatch, index) => {
|
|
41
|
+
const key = parse(swatch.color);
|
|
42
|
+
const match = key === null ? swatch.color : toHex(key);
|
|
43
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
|
|
44
|
+
type: "button",
|
|
45
|
+
className: cx("cp-swatch", round && "cp-swatch-round", classNames.swatch),
|
|
46
|
+
style: { ["--cp-swatch-color"]: swatch.color },
|
|
47
|
+
"data-cp-color": match,
|
|
48
|
+
"aria-label": swatch.name ?? swatch.color,
|
|
49
|
+
"aria-pressed": false,
|
|
50
|
+
disabled
|
|
51
|
+
}) }, `${swatch.color}-${index}`);
|
|
52
|
+
})
|
|
53
|
+
});
|
|
54
|
+
if (variant === "mosaic") return /* @__PURE__ */ jsx("div", {
|
|
55
|
+
className: cx("cp-mosaic", className),
|
|
56
|
+
children: grid
|
|
57
|
+
});
|
|
58
|
+
return grid;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { SwatchGrid };
|
|
62
|
+
|