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,154 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_context = require("../core/context.cjs");
|
|
4
|
+
const require_useMediaQuery = require("../core/useMediaQuery.cjs");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
react = require_runtime.__toESM(react, 1);
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react_dom = require("react-dom");
|
|
9
|
+
//#region src/components/Popover.tsx
|
|
10
|
+
const MARGIN = 8;
|
|
11
|
+
const MIN_AVAILABLE = 160;
|
|
12
|
+
const FOCUSABLE = "a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])";
|
|
13
|
+
function Popover(props) {
|
|
14
|
+
const { anchor, open, onClose, offset = 8, sheetOnMobile = true, className, children } = props;
|
|
15
|
+
const panelRef = react.useRef(null);
|
|
16
|
+
const [position, setPosition] = react.useState(null);
|
|
17
|
+
const compact = require_useMediaQuery.useMediaQuery(require_useMediaQuery.COMPACT_QUERY);
|
|
18
|
+
const asSheet = sheetOnMobile && compact;
|
|
19
|
+
const [mounted, setMounted] = react.useState(false);
|
|
20
|
+
react.useEffect(() => setMounted(true), []);
|
|
21
|
+
const place = react.useCallback(() => {
|
|
22
|
+
const panel = panelRef.current;
|
|
23
|
+
if (anchor === null || panel === null) return;
|
|
24
|
+
const a = anchor.getBoundingClientRect();
|
|
25
|
+
const p = panel.getBoundingClientRect();
|
|
26
|
+
const below = window.innerHeight - a.bottom - offset - MARGIN;
|
|
27
|
+
const above = a.top - offset - MARGIN;
|
|
28
|
+
let top;
|
|
29
|
+
let available;
|
|
30
|
+
if (p.height <= below || below >= above && p.height > above) {
|
|
31
|
+
top = a.bottom + offset;
|
|
32
|
+
available = below;
|
|
33
|
+
} else {
|
|
34
|
+
available = above;
|
|
35
|
+
top = Math.max(MARGIN, a.top - offset - p.height);
|
|
36
|
+
}
|
|
37
|
+
let left = a.left;
|
|
38
|
+
const maxLeft = window.innerWidth - p.width - MARGIN;
|
|
39
|
+
if (left > maxLeft) left = Math.max(MARGIN, maxLeft);
|
|
40
|
+
if (left < MARGIN) left = MARGIN;
|
|
41
|
+
setPosition({
|
|
42
|
+
top: top + window.scrollY,
|
|
43
|
+
left: left + window.scrollX,
|
|
44
|
+
available: Math.max(available, MIN_AVAILABLE)
|
|
45
|
+
});
|
|
46
|
+
}, [anchor, offset]);
|
|
47
|
+
react.useLayoutEffect(() => {
|
|
48
|
+
if (!open || asSheet) {
|
|
49
|
+
setPosition(null);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
place();
|
|
53
|
+
window.addEventListener("scroll", place, true);
|
|
54
|
+
window.addEventListener("resize", place);
|
|
55
|
+
return () => {
|
|
56
|
+
window.removeEventListener("scroll", place, true);
|
|
57
|
+
window.removeEventListener("resize", place);
|
|
58
|
+
};
|
|
59
|
+
}, [
|
|
60
|
+
open,
|
|
61
|
+
asSheet,
|
|
62
|
+
place
|
|
63
|
+
]);
|
|
64
|
+
const hasFocused = react.useRef(false);
|
|
65
|
+
const visible = asSheet || position !== null;
|
|
66
|
+
react.useEffect(() => {
|
|
67
|
+
if (!open) {
|
|
68
|
+
hasFocused.current = false;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const panel = panelRef.current;
|
|
72
|
+
if (panel === null || !visible || hasFocused.current) return;
|
|
73
|
+
hasFocused.current = true;
|
|
74
|
+
const previous = document.activeElement;
|
|
75
|
+
(panel.querySelector(FOCUSABLE) ?? panel).focus({ preventScroll: true });
|
|
76
|
+
return () => {
|
|
77
|
+
if (panel.contains(document.activeElement)) previous?.focus({ preventScroll: true });
|
|
78
|
+
};
|
|
79
|
+
}, [open, visible]);
|
|
80
|
+
react.useEffect(() => {
|
|
81
|
+
if (!open) return;
|
|
82
|
+
const onKeyDown = (event) => {
|
|
83
|
+
if (event.key === "Escape") {
|
|
84
|
+
event.stopPropagation();
|
|
85
|
+
onClose();
|
|
86
|
+
anchor?.focus({ preventScroll: true });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (event.key !== "Tab") return;
|
|
90
|
+
const panel = panelRef.current;
|
|
91
|
+
if (panel === null) return;
|
|
92
|
+
const items = Array.from(panel.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null || el === document.activeElement);
|
|
93
|
+
if (items.length === 0) return;
|
|
94
|
+
const first = items[0];
|
|
95
|
+
const last = items[items.length - 1];
|
|
96
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
last.focus();
|
|
99
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
100
|
+
event.preventDefault();
|
|
101
|
+
first.focus();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const onPointerDown = (event) => {
|
|
105
|
+
const target = event.target;
|
|
106
|
+
if (panelRef.current?.contains(target) === true) return;
|
|
107
|
+
if (anchor?.contains(target) === true) return;
|
|
108
|
+
onClose();
|
|
109
|
+
};
|
|
110
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
111
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
112
|
+
return () => {
|
|
113
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
114
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
115
|
+
};
|
|
116
|
+
}, [
|
|
117
|
+
open,
|
|
118
|
+
onClose,
|
|
119
|
+
anchor
|
|
120
|
+
]);
|
|
121
|
+
if (!open || !mounted) return null;
|
|
122
|
+
if (asSheet) return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
123
|
+
className: "cp-sheet-root",
|
|
124
|
+
"data-cp-open": "true",
|
|
125
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
126
|
+
className: "cp-scrim",
|
|
127
|
+
"aria-hidden": "true"
|
|
128
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
129
|
+
ref: panelRef,
|
|
130
|
+
className: require_context.cx("cp-sheet", className),
|
|
131
|
+
tabIndex: -1,
|
|
132
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
133
|
+
type: "button",
|
|
134
|
+
className: "cp-grabber",
|
|
135
|
+
"aria-label": "Close",
|
|
136
|
+
onClick: onClose
|
|
137
|
+
}), children]
|
|
138
|
+
})]
|
|
139
|
+
}), document.body);
|
|
140
|
+
return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
141
|
+
ref: panelRef,
|
|
142
|
+
className: require_context.cx("cp-popover", className),
|
|
143
|
+
tabIndex: -1,
|
|
144
|
+
style: {
|
|
145
|
+
top: position?.top ?? 0,
|
|
146
|
+
left: position?.left ?? 0,
|
|
147
|
+
visibility: position === null ? "hidden" : "visible",
|
|
148
|
+
...position === null ? null : { ["--cp-available-h"]: `${position.available}px` }
|
|
149
|
+
},
|
|
150
|
+
children
|
|
151
|
+
}), document.body);
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
exports.Popover = Popover;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/components/Popover.d.ts
|
|
3
|
+
export interface PopoverProps {
|
|
4
|
+
anchor: HTMLElement | null;
|
|
5
|
+
open: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
offset?: number;
|
|
8
|
+
sheetOnMobile?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function Popover(props: PopoverProps): React.ReactElement | null;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/components/Popover.d.ts
|
|
3
|
+
export interface PopoverProps {
|
|
4
|
+
anchor: HTMLElement | null;
|
|
5
|
+
open: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
offset?: number;
|
|
8
|
+
sheetOnMobile?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function Popover(props: PopoverProps): React.ReactElement | null;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cx } from "../core/context.js";
|
|
3
|
+
import { COMPACT_QUERY, useMediaQuery } from "../core/useMediaQuery.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { createPortal } from "react-dom";
|
|
7
|
+
//#region src/components/Popover.tsx
|
|
8
|
+
const MARGIN = 8;
|
|
9
|
+
const MIN_AVAILABLE = 160;
|
|
10
|
+
const FOCUSABLE = "a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])";
|
|
11
|
+
function Popover(props) {
|
|
12
|
+
const { anchor, open, onClose, offset = 8, sheetOnMobile = true, className, children } = props;
|
|
13
|
+
const panelRef = React.useRef(null);
|
|
14
|
+
const [position, setPosition] = React.useState(null);
|
|
15
|
+
const compact = useMediaQuery(COMPACT_QUERY);
|
|
16
|
+
const asSheet = sheetOnMobile && compact;
|
|
17
|
+
const [mounted, setMounted] = React.useState(false);
|
|
18
|
+
React.useEffect(() => setMounted(true), []);
|
|
19
|
+
const place = React.useCallback(() => {
|
|
20
|
+
const panel = panelRef.current;
|
|
21
|
+
if (anchor === null || panel === null) return;
|
|
22
|
+
const a = anchor.getBoundingClientRect();
|
|
23
|
+
const p = panel.getBoundingClientRect();
|
|
24
|
+
const below = window.innerHeight - a.bottom - offset - MARGIN;
|
|
25
|
+
const above = a.top - offset - MARGIN;
|
|
26
|
+
let top;
|
|
27
|
+
let available;
|
|
28
|
+
if (p.height <= below || below >= above && p.height > above) {
|
|
29
|
+
top = a.bottom + offset;
|
|
30
|
+
available = below;
|
|
31
|
+
} else {
|
|
32
|
+
available = above;
|
|
33
|
+
top = Math.max(MARGIN, a.top - offset - p.height);
|
|
34
|
+
}
|
|
35
|
+
let left = a.left;
|
|
36
|
+
const maxLeft = window.innerWidth - p.width - MARGIN;
|
|
37
|
+
if (left > maxLeft) left = Math.max(MARGIN, maxLeft);
|
|
38
|
+
if (left < MARGIN) left = MARGIN;
|
|
39
|
+
setPosition({
|
|
40
|
+
top: top + window.scrollY,
|
|
41
|
+
left: left + window.scrollX,
|
|
42
|
+
available: Math.max(available, MIN_AVAILABLE)
|
|
43
|
+
});
|
|
44
|
+
}, [anchor, offset]);
|
|
45
|
+
React.useLayoutEffect(() => {
|
|
46
|
+
if (!open || asSheet) {
|
|
47
|
+
setPosition(null);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
place();
|
|
51
|
+
window.addEventListener("scroll", place, true);
|
|
52
|
+
window.addEventListener("resize", place);
|
|
53
|
+
return () => {
|
|
54
|
+
window.removeEventListener("scroll", place, true);
|
|
55
|
+
window.removeEventListener("resize", place);
|
|
56
|
+
};
|
|
57
|
+
}, [
|
|
58
|
+
open,
|
|
59
|
+
asSheet,
|
|
60
|
+
place
|
|
61
|
+
]);
|
|
62
|
+
const hasFocused = React.useRef(false);
|
|
63
|
+
const visible = asSheet || position !== null;
|
|
64
|
+
React.useEffect(() => {
|
|
65
|
+
if (!open) {
|
|
66
|
+
hasFocused.current = false;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const panel = panelRef.current;
|
|
70
|
+
if (panel === null || !visible || hasFocused.current) return;
|
|
71
|
+
hasFocused.current = true;
|
|
72
|
+
const previous = document.activeElement;
|
|
73
|
+
(panel.querySelector(FOCUSABLE) ?? panel).focus({ preventScroll: true });
|
|
74
|
+
return () => {
|
|
75
|
+
if (panel.contains(document.activeElement)) previous?.focus({ preventScroll: true });
|
|
76
|
+
};
|
|
77
|
+
}, [open, visible]);
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
if (!open) return;
|
|
80
|
+
const onKeyDown = (event) => {
|
|
81
|
+
if (event.key === "Escape") {
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
onClose();
|
|
84
|
+
anchor?.focus({ preventScroll: true });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (event.key !== "Tab") return;
|
|
88
|
+
const panel = panelRef.current;
|
|
89
|
+
if (panel === null) return;
|
|
90
|
+
const items = Array.from(panel.querySelectorAll(FOCUSABLE)).filter((el) => el.offsetParent !== null || el === document.activeElement);
|
|
91
|
+
if (items.length === 0) return;
|
|
92
|
+
const first = items[0];
|
|
93
|
+
const last = items[items.length - 1];
|
|
94
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
last.focus();
|
|
97
|
+
} else if (!event.shiftKey && document.activeElement === last) {
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
first.focus();
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const onPointerDown = (event) => {
|
|
103
|
+
const target = event.target;
|
|
104
|
+
if (panelRef.current?.contains(target) === true) return;
|
|
105
|
+
if (anchor?.contains(target) === true) return;
|
|
106
|
+
onClose();
|
|
107
|
+
};
|
|
108
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
109
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
110
|
+
return () => {
|
|
111
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
112
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
113
|
+
};
|
|
114
|
+
}, [
|
|
115
|
+
open,
|
|
116
|
+
onClose,
|
|
117
|
+
anchor
|
|
118
|
+
]);
|
|
119
|
+
if (!open || !mounted) return null;
|
|
120
|
+
if (asSheet) return createPortal(/* @__PURE__ */ jsxs("div", {
|
|
121
|
+
className: "cp-sheet-root",
|
|
122
|
+
"data-cp-open": "true",
|
|
123
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
124
|
+
className: "cp-scrim",
|
|
125
|
+
"aria-hidden": "true"
|
|
126
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
127
|
+
ref: panelRef,
|
|
128
|
+
className: cx("cp-sheet", className),
|
|
129
|
+
tabIndex: -1,
|
|
130
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
131
|
+
type: "button",
|
|
132
|
+
className: "cp-grabber",
|
|
133
|
+
"aria-label": "Close",
|
|
134
|
+
onClick: onClose
|
|
135
|
+
}), children]
|
|
136
|
+
})]
|
|
137
|
+
}), document.body);
|
|
138
|
+
return createPortal(/* @__PURE__ */ jsx("div", {
|
|
139
|
+
ref: panelRef,
|
|
140
|
+
className: cx("cp-popover", className),
|
|
141
|
+
tabIndex: -1,
|
|
142
|
+
style: {
|
|
143
|
+
top: position?.top ?? 0,
|
|
144
|
+
left: position?.left ?? 0,
|
|
145
|
+
visibility: position === null ? "hidden" : "visible",
|
|
146
|
+
...position === null ? null : { ["--cp-available-h"]: `${position.available}px` }
|
|
147
|
+
},
|
|
148
|
+
children
|
|
149
|
+
}), document.body);
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
export { Popover };
|
|
153
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_contrast = require("./a11y/contrast.cjs");
|
|
3
|
+
exports.apcaContrast = require_contrast.apcaContrast;
|
|
4
|
+
exports.contrastRatio = require_contrast.contrastRatio;
|
|
5
|
+
exports.contrastReport = require_contrast.contrastReport;
|
|
6
|
+
exports.meetsContrast = require_contrast.meetsContrast;
|
|
7
|
+
exports.meetsNonTextContrast = require_contrast.meetsNonTextContrast;
|
|
8
|
+
exports.readableTextColor = require_contrast.readableTextColor;
|
|
9
|
+
exports.relativeLuminance = require_contrast.relativeLuminance;
|
|
10
|
+
exports.wcagLevel = require_contrast.wcagLevel;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel } from "./a11y/contrast.cjs";
|
|
2
|
+
export { type ContrastOptions, type ContrastReport, type TextSize, type WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { ContrastOptions, ContrastReport, TextSize, WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel } from "./a11y/contrast.js";
|
|
2
|
+
export { type ContrastOptions, type ContrastReport, type TextSize, type WcagLevel, apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel };
|
package/dist/contrast.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel } from "./a11y/contrast.js";
|
|
2
|
+
export { apcaContrast, contrastRatio, contrastReport, meetsContrast, meetsNonTextContrast, readableTextColor, relativeLuminance, wcagLevel };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
react = require_runtime.__toESM(react, 1);
|
|
5
|
+
//#region src/core/context.ts
|
|
6
|
+
const PanelContext = react.createContext(null);
|
|
7
|
+
const PanelProvider = PanelContext.Provider;
|
|
8
|
+
function usePanel() {
|
|
9
|
+
const value = react.useContext(PanelContext);
|
|
10
|
+
if (value === null) throw new Error("chroma-panel: this component must be rendered inside <ChromaPanel> or <ColorInput>.");
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function cx(...parts) {
|
|
14
|
+
let out = "";
|
|
15
|
+
for (const part of parts) if (typeof part === "string" && part !== "") out = out === "" ? part : out + " " + part;
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
let idCounter = 0;
|
|
19
|
+
function useStableId(prefix) {
|
|
20
|
+
const reactUseId = react.useId;
|
|
21
|
+
if (typeof reactUseId === "function") return prefix + reactUseId().replace(/:/g, "");
|
|
22
|
+
const ref = react.useRef(null);
|
|
23
|
+
if (ref.current === null) ref.current = prefix + String(++idCounter);
|
|
24
|
+
return ref.current;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.PanelProvider = PanelProvider;
|
|
28
|
+
exports.cx = cx;
|
|
29
|
+
exports.usePanel = usePanel;
|
|
30
|
+
exports.useStableId = useStableId;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ColorStore } from "./store.cjs";
|
|
2
|
+
import "react";
|
|
3
|
+
//#region src/core/context.d.ts
|
|
4
|
+
export interface ChromaClassNames {
|
|
5
|
+
root?: string;
|
|
6
|
+
titlebar?: string;
|
|
7
|
+
toolbar?: string;
|
|
8
|
+
tab?: string;
|
|
9
|
+
panel?: string;
|
|
10
|
+
footer?: string;
|
|
11
|
+
swatch?: string;
|
|
12
|
+
slider?: string;
|
|
13
|
+
thumb?: string;
|
|
14
|
+
field?: string;
|
|
15
|
+
trigger?: string;
|
|
16
|
+
popover?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ColorPalette {
|
|
19
|
+
name: string;
|
|
20
|
+
colors: (string | {
|
|
21
|
+
color: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
})[];
|
|
24
|
+
}
|
|
25
|
+
export interface PanelOptions {
|
|
26
|
+
modeProps: Record<string, Record<string, unknown>>;
|
|
27
|
+
palettes: ColorPalette[] | undefined;
|
|
28
|
+
pencils: string[] | undefined;
|
|
29
|
+
showAlpha: boolean;
|
|
30
|
+
showEyedropper: boolean;
|
|
31
|
+
showRecentColors: boolean;
|
|
32
|
+
recentColors: string[];
|
|
33
|
+
onRecentColorsChange?: (colors: string[]) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface PanelContextValue {
|
|
36
|
+
store: ColorStore;
|
|
37
|
+
disabled: boolean;
|
|
38
|
+
classNames: ChromaClassNames;
|
|
39
|
+
options: PanelOptions;
|
|
40
|
+
idPrefix: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function usePanel(): PanelContextValue;
|
|
43
|
+
//#endregion
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ColorStore } from "./store.js";
|
|
2
|
+
import "react";
|
|
3
|
+
//#region src/core/context.d.ts
|
|
4
|
+
export interface ChromaClassNames {
|
|
5
|
+
root?: string;
|
|
6
|
+
titlebar?: string;
|
|
7
|
+
toolbar?: string;
|
|
8
|
+
tab?: string;
|
|
9
|
+
panel?: string;
|
|
10
|
+
footer?: string;
|
|
11
|
+
swatch?: string;
|
|
12
|
+
slider?: string;
|
|
13
|
+
thumb?: string;
|
|
14
|
+
field?: string;
|
|
15
|
+
trigger?: string;
|
|
16
|
+
popover?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ColorPalette {
|
|
19
|
+
name: string;
|
|
20
|
+
colors: (string | {
|
|
21
|
+
color: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
})[];
|
|
24
|
+
}
|
|
25
|
+
export interface PanelOptions {
|
|
26
|
+
modeProps: Record<string, Record<string, unknown>>;
|
|
27
|
+
palettes: ColorPalette[] | undefined;
|
|
28
|
+
pencils: string[] | undefined;
|
|
29
|
+
showAlpha: boolean;
|
|
30
|
+
showEyedropper: boolean;
|
|
31
|
+
showRecentColors: boolean;
|
|
32
|
+
recentColors: string[];
|
|
33
|
+
onRecentColorsChange?: (colors: string[]) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface PanelContextValue {
|
|
36
|
+
store: ColorStore;
|
|
37
|
+
disabled: boolean;
|
|
38
|
+
classNames: ChromaClassNames;
|
|
39
|
+
options: PanelOptions;
|
|
40
|
+
idPrefix: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function usePanel(): PanelContextValue;
|
|
43
|
+
//#endregion
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/core/context.ts
|
|
4
|
+
const PanelContext = React.createContext(null);
|
|
5
|
+
const PanelProvider = PanelContext.Provider;
|
|
6
|
+
function usePanel() {
|
|
7
|
+
const value = React.useContext(PanelContext);
|
|
8
|
+
if (value === null) throw new Error("chroma-panel: this component must be rendered inside <ChromaPanel> or <ColorInput>.");
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function cx(...parts) {
|
|
12
|
+
let out = "";
|
|
13
|
+
for (const part of parts) if (typeof part === "string" && part !== "") out = out === "" ? part : out + " " + part;
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
let idCounter = 0;
|
|
17
|
+
function useStableId(prefix) {
|
|
18
|
+
const reactUseId = React.useId;
|
|
19
|
+
if (typeof reactUseId === "function") return prefix + reactUseId().replace(/:/g, "");
|
|
20
|
+
const ref = React.useRef(null);
|
|
21
|
+
if (ref.current === null) ref.current = prefix + String(++idCounter);
|
|
22
|
+
return ref.current;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { PanelProvider, cx, usePanel, useStableId };
|
|
26
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/core/dev.ts
|
|
2
|
+
const isDev = typeof process !== "undefined" && typeof process.env === "object" ? process.env.NODE_ENV !== "production" : false;
|
|
3
|
+
const warned = /* @__PURE__ */ new Set();
|
|
4
|
+
function warnOnce(message) {
|
|
5
|
+
if (!isDev || warned.has(message)) return;
|
|
6
|
+
warned.add(message);
|
|
7
|
+
console.warn(`chroma-panel: ${message}`);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
exports.isDev = isDev;
|
|
11
|
+
exports.warnOnce = warnOnce;
|
package/dist/core/dev.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/core/dev.ts
|
|
2
|
+
const isDev = typeof process !== "undefined" && typeof process.env === "object" ? process.env.NODE_ENV !== "production" : false;
|
|
3
|
+
const warned = /* @__PURE__ */ new Set();
|
|
4
|
+
function warnOnce(message) {
|
|
5
|
+
if (!isDev || warned.has(message)) return;
|
|
6
|
+
warned.add(message);
|
|
7
|
+
console.warn(`chroma-panel: ${message}`);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { isDev, warnOnce };
|
|
11
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const require_sticky = require("../color/sticky.cjs");
|
|
2
|
+
//#region src/core/store.ts
|
|
3
|
+
function createColorStore(initial) {
|
|
4
|
+
let state = initial;
|
|
5
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
const commitListeners = /* @__PURE__ */ new Set();
|
|
7
|
+
function emit() {
|
|
8
|
+
for (const listener of Array.from(listeners)) listener(state);
|
|
9
|
+
}
|
|
10
|
+
function set(next) {
|
|
11
|
+
if (require_sticky.sameHsva(state, next)) return;
|
|
12
|
+
state = next;
|
|
13
|
+
emit();
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
get: () => state,
|
|
17
|
+
set,
|
|
18
|
+
patch: (partial) => set({
|
|
19
|
+
...state,
|
|
20
|
+
...partial
|
|
21
|
+
}),
|
|
22
|
+
ingest: (next) => set(require_sticky.ingest(next, state)),
|
|
23
|
+
commit: () => {
|
|
24
|
+
for (const listener of Array.from(commitListeners)) listener(state);
|
|
25
|
+
},
|
|
26
|
+
subscribe: (listener) => {
|
|
27
|
+
listeners.add(listener);
|
|
28
|
+
return () => {
|
|
29
|
+
listeners.delete(listener);
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
subscribeCommit: (listener) => {
|
|
33
|
+
commitListeners.add(listener);
|
|
34
|
+
return () => {
|
|
35
|
+
commitListeners.delete(listener);
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
getSnapshot: () => state,
|
|
39
|
+
getServerSnapshot: () => state
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.createColorStore = createColorStore;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hsva } from "../color/types.cjs";
|
|
2
|
+
//#region src/core/store.d.ts
|
|
3
|
+
export type ColorListener = (color: Hsva) => void;
|
|
4
|
+
export type Unsubscribe = () => void;
|
|
5
|
+
export interface ColorStore {
|
|
6
|
+
get(): Hsva;
|
|
7
|
+
set(next: Hsva): void;
|
|
8
|
+
patch(partial: Partial<Hsva>): void;
|
|
9
|
+
ingest(next: Hsva): void;
|
|
10
|
+
commit(): void;
|
|
11
|
+
subscribe(listener: ColorListener): Unsubscribe;
|
|
12
|
+
subscribeCommit(listener: ColorListener): Unsubscribe;
|
|
13
|
+
getSnapshot(): Hsva;
|
|
14
|
+
getServerSnapshot(): Hsva;
|
|
15
|
+
}
|
|
16
|
+
export declare function createColorStore(initial: Hsva): ColorStore;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hsva } from "../color/types.js";
|
|
2
|
+
//#region src/core/store.d.ts
|
|
3
|
+
export type ColorListener = (color: Hsva) => void;
|
|
4
|
+
export type Unsubscribe = () => void;
|
|
5
|
+
export interface ColorStore {
|
|
6
|
+
get(): Hsva;
|
|
7
|
+
set(next: Hsva): void;
|
|
8
|
+
patch(partial: Partial<Hsva>): void;
|
|
9
|
+
ingest(next: Hsva): void;
|
|
10
|
+
commit(): void;
|
|
11
|
+
subscribe(listener: ColorListener): Unsubscribe;
|
|
12
|
+
subscribeCommit(listener: ColorListener): Unsubscribe;
|
|
13
|
+
getSnapshot(): Hsva;
|
|
14
|
+
getServerSnapshot(): Hsva;
|
|
15
|
+
}
|
|
16
|
+
export declare function createColorStore(initial: Hsva): ColorStore;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ingest, sameHsva } from "../color/sticky.js";
|
|
2
|
+
//#region src/core/store.ts
|
|
3
|
+
function createColorStore(initial) {
|
|
4
|
+
let state = initial;
|
|
5
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
const commitListeners = /* @__PURE__ */ new Set();
|
|
7
|
+
function emit() {
|
|
8
|
+
for (const listener of Array.from(listeners)) listener(state);
|
|
9
|
+
}
|
|
10
|
+
function set(next) {
|
|
11
|
+
if (sameHsva(state, next)) return;
|
|
12
|
+
state = next;
|
|
13
|
+
emit();
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
get: () => state,
|
|
17
|
+
set,
|
|
18
|
+
patch: (partial) => set({
|
|
19
|
+
...state,
|
|
20
|
+
...partial
|
|
21
|
+
}),
|
|
22
|
+
ingest: (next) => set(ingest(next, state)),
|
|
23
|
+
commit: () => {
|
|
24
|
+
for (const listener of Array.from(commitListeners)) listener(state);
|
|
25
|
+
},
|
|
26
|
+
subscribe: (listener) => {
|
|
27
|
+
listeners.add(listener);
|
|
28
|
+
return () => {
|
|
29
|
+
listeners.delete(listener);
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
subscribeCommit: (listener) => {
|
|
33
|
+
commitListeners.add(listener);
|
|
34
|
+
return () => {
|
|
35
|
+
commitListeners.delete(listener);
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
getSnapshot: () => state,
|
|
39
|
+
getServerSnapshot: () => state
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createColorStore };
|
|
44
|
+
|