@puzzle-ui/ui 0.3.0 → 0.5.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/README.md +70 -70
- package/dist/components/actions/button/button.css +5 -2
- package/dist/components/actions/button-group/button-group.css +16 -17
- package/dist/components/data-display/badge/badge.css +15 -2
- package/dist/components/data-display/badge/index.cjs +13 -2
- package/dist/components/data-display/badge/index.cjs.map +1 -1
- package/dist/components/data-display/badge/index.d.cts +7 -2
- package/dist/components/data-display/badge/index.d.ts +7 -2
- package/dist/components/data-display/badge/index.js +13 -2
- package/dist/components/data-display/badge/index.js.map +1 -1
- package/dist/components/data-display/empty-state/empty-state.css +128 -0
- package/dist/components/data-display/empty-state/empty-state.utils.cjs +6 -0
- package/dist/components/data-display/empty-state/empty-state.utils.cjs.map +1 -0
- package/dist/components/data-display/empty-state/empty-state.utils.js +6 -0
- package/dist/components/data-display/empty-state/empty-state.utils.js.map +1 -0
- package/dist/components/data-display/empty-state/index.cjs +49 -0
- package/dist/components/data-display/empty-state/index.cjs.map +1 -0
- package/dist/components/data-display/empty-state/index.d.cts +19 -0
- package/dist/components/data-display/empty-state/index.d.ts +19 -0
- package/dist/components/data-display/empty-state/index.js +44 -0
- package/dist/components/data-display/empty-state/index.js.map +1 -0
- package/dist/components/data-display/rating/index.cjs +84 -0
- package/dist/components/data-display/rating/index.cjs.map +1 -0
- package/dist/components/data-display/rating/index.d.cts +3 -0
- package/dist/components/data-display/rating/index.d.ts +3 -0
- package/dist/components/data-display/rating/index.js +84 -0
- package/dist/components/data-display/rating/index.js.map +1 -0
- package/dist/components/data-display/rating/rating.css +72 -0
- package/dist/components/data-display/rating/rating.types.d.cts +15 -0
- package/dist/components/data-display/rating/rating.types.d.ts +15 -0
- package/dist/components/data-display/rating/rating.utils.cjs +27 -0
- package/dist/components/data-display/rating/rating.utils.cjs.map +1 -0
- package/dist/components/data-display/rating/rating.utils.js +25 -0
- package/dist/components/data-display/rating/rating.utils.js.map +1 -0
- package/dist/components/editors/text-editor/editor.cjs.map +1 -1
- package/dist/components/editors/text-editor/editor.js.map +1 -1
- package/dist/components/editors/text-editor/text-document.cjs.map +1 -1
- package/dist/components/editors/text-editor/text-document.js.map +1 -1
- package/dist/components/editors/text-editor/text-parser.cjs.map +1 -1
- package/dist/components/editors/text-editor/text-parser.js.map +1 -1
- package/dist/components/editors/text-editor/text-renderer.cjs.map +1 -1
- package/dist/components/editors/text-editor/text-renderer.js.map +1 -1
- package/dist/components/forms/autocomplete/index.cjs.map +1 -1
- package/dist/components/forms/autocomplete/index.js.map +1 -1
- package/dist/components/forms/checkbox/checkbox.css +2 -10
- package/dist/components/forms/color-picker/color-picker.css +351 -0
- package/dist/components/forms/color-picker/color-picker.types.d.cts +25 -0
- package/dist/components/forms/color-picker/color-picker.types.d.ts +25 -0
- package/dist/components/forms/color-picker/color-picker.utils.cjs +116 -0
- package/dist/components/forms/color-picker/color-picker.utils.cjs.map +1 -0
- package/dist/components/forms/color-picker/color-picker.utils.js +109 -0
- package/dist/components/forms/color-picker/color-picker.utils.js.map +1 -0
- package/dist/components/forms/color-picker/index.cjs +340 -0
- package/dist/components/forms/color-picker/index.cjs.map +1 -0
- package/dist/components/forms/color-picker/index.d.cts +3 -0
- package/dist/components/forms/color-picker/index.d.ts +3 -0
- package/dist/components/forms/color-picker/index.js +340 -0
- package/dist/components/forms/color-picker/index.js.map +1 -0
- package/dist/components/forms/file-upload/file-upload.utils.cjs.map +1 -1
- package/dist/components/forms/file-upload/file-upload.utils.js.map +1 -1
- package/dist/components/forms/input/number-input.js +5 -5
- package/dist/components/forms/input/number-input.js.map +1 -1
- package/dist/components/forms/input-group/index.d.cts +3 -0
- package/dist/components/forms/input-group/index.d.ts +3 -0
- package/dist/components/forms/input-group/input-group.cjs +18 -0
- package/dist/components/forms/input-group/input-group.cjs.map +1 -0
- package/dist/components/forms/input-group/input-group.css +62 -0
- package/dist/components/forms/input-group/input-group.d.cts +7 -0
- package/dist/components/forms/input-group/input-group.d.ts +7 -0
- package/dist/components/forms/input-group/input-group.js +18 -0
- package/dist/components/forms/input-group/input-group.js.map +1 -0
- package/dist/components/forms/input-group/input-group.types.d.cts +7 -0
- package/dist/components/forms/input-group/input-group.types.d.ts +7 -0
- package/dist/components/forms/input-group/input-group.utils.cjs +5 -0
- package/dist/components/forms/input-group/input-group.utils.cjs.map +1 -0
- package/dist/components/forms/input-group/input-group.utils.js +5 -0
- package/dist/components/forms/input-group/input-group.utils.js.map +1 -0
- package/dist/components/forms/radio-group/index.d.cts +2 -1
- package/dist/components/forms/radio-group/index.d.ts +2 -1
- package/dist/components/forms/select/index.cjs.map +1 -1
- package/dist/components/forms/select/index.js.map +1 -1
- package/dist/components/forms/slider/index.cjs +1 -1
- package/dist/components/forms/slider/index.cjs.map +1 -1
- package/dist/components/forms/slider/index.js +1 -1
- package/dist/components/forms/slider/index.js.map +1 -1
- package/dist/components/forms/stepper/index.d.cts +4 -2
- package/dist/components/forms/stepper/index.d.ts +4 -2
- package/dist/components/forms/time-picker/index.cjs +108 -0
- package/dist/components/forms/time-picker/index.cjs.map +1 -0
- package/dist/components/forms/time-picker/index.d.cts +3 -0
- package/dist/components/forms/time-picker/index.d.ts +3 -0
- package/dist/components/forms/time-picker/index.js +108 -0
- package/dist/components/forms/time-picker/index.js.map +1 -0
- package/dist/components/forms/time-picker/time-picker.css +166 -0
- package/dist/components/forms/time-picker/time-picker.types.d.cts +34 -0
- package/dist/components/forms/time-picker/time-picker.types.d.ts +34 -0
- package/dist/components/forms/time-picker/time-picker.utils.cjs +25 -0
- package/dist/components/forms/time-picker/time-picker.utils.cjs.map +1 -0
- package/dist/components/forms/time-picker/time-picker.utils.js +24 -0
- package/dist/components/forms/time-picker/time-picker.utils.js.map +1 -0
- package/dist/components/forms/token-input/index.cjs +189 -0
- package/dist/components/forms/token-input/index.cjs.map +1 -0
- package/dist/components/forms/token-input/index.d.cts +3 -0
- package/dist/components/forms/token-input/index.d.ts +3 -0
- package/dist/components/forms/token-input/index.js +189 -0
- package/dist/components/forms/token-input/index.js.map +1 -0
- package/dist/components/forms/token-input/token-input.css +145 -0
- package/dist/components/forms/token-input/token-input.types.d.cts +48 -0
- package/dist/components/forms/token-input/token-input.types.d.ts +48 -0
- package/dist/components/forms/token-input/token-input.utils.cjs +30 -0
- package/dist/components/forms/token-input/token-input.utils.cjs.map +1 -0
- package/dist/components/forms/token-input/token-input.utils.js +24 -0
- package/dist/components/forms/token-input/token-input.utils.js.map +1 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio.css +14 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs +11 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio.utils.cjs.map +1 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js +11 -0
- package/dist/components/layout/aspect-ratio/aspect-ratio.utils.js.map +1 -0
- package/dist/components/layout/aspect-ratio/index.cjs +16 -0
- package/dist/components/layout/aspect-ratio/index.cjs.map +1 -0
- package/dist/components/layout/aspect-ratio/index.d.cts +11 -0
- package/dist/components/layout/aspect-ratio/index.d.ts +11 -0
- package/dist/components/layout/aspect-ratio/index.js +16 -0
- package/dist/components/layout/aspect-ratio/index.js.map +1 -0
- package/dist/components/layout/container/container.css +1 -0
- package/dist/components/layout/page-layout/page-layout.css +1 -0
- package/dist/components/layout/resizable-panels/index.cjs +1 -1
- package/dist/components/layout/resizable-panels/index.cjs.map +1 -1
- package/dist/components/layout/resizable-panels/index.js +1 -1
- package/dist/components/layout/resizable-panels/index.js.map +1 -1
- package/dist/components/layout/resizable-panels/resizable-panels.utils.cjs.map +1 -1
- package/dist/components/layout/resizable-panels/resizable-panels.utils.js.map +1 -1
- package/dist/components/layout/scroll-area/index.cjs +27 -0
- package/dist/components/layout/scroll-area/index.cjs.map +1 -0
- package/dist/components/layout/scroll-area/index.d.cts +15 -0
- package/dist/components/layout/scroll-area/index.d.ts +15 -0
- package/dist/components/layout/scroll-area/index.js +27 -0
- package/dist/components/layout/scroll-area/index.js.map +1 -0
- package/dist/components/layout/scroll-area/scroll-area.css +25 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.cjs +8 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.cjs.map +1 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.d.cts +2 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.d.ts +2 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.js +8 -0
- package/dist/components/layout/scroll-area/scroll-area.utils.js.map +1 -0
- package/dist/components/layout/section/index.cjs +10 -4
- package/dist/components/layout/section/index.cjs.map +1 -1
- package/dist/components/layout/section/index.d.cts +1 -1
- package/dist/components/layout/section/index.d.ts +1 -1
- package/dist/components/layout/section/index.js +11 -5
- package/dist/components/layout/section/index.js.map +1 -1
- package/dist/components/layout/section/section.css +9 -3
- package/dist/components/layout/section/types.d.cts +5 -5
- package/dist/components/layout/section/types.d.ts +5 -5
- package/dist/components/layout/separator/index.cjs +18 -0
- package/dist/components/layout/separator/index.cjs.map +1 -0
- package/dist/components/layout/separator/index.d.cts +17 -0
- package/dist/components/layout/separator/index.d.ts +17 -0
- package/dist/components/layout/separator/index.js +18 -0
- package/dist/components/layout/separator/index.js.map +1 -0
- package/dist/components/layout/separator/separator.css +15 -0
- package/dist/components/layout/separator/separator.utils.cjs +11 -0
- package/dist/components/layout/separator/separator.utils.cjs.map +1 -0
- package/dist/components/layout/separator/separator.utils.d.cts +2 -0
- package/dist/components/layout/separator/separator.utils.d.ts +2 -0
- package/dist/components/layout/separator/separator.utils.js +11 -0
- package/dist/components/layout/separator/separator.utils.js.map +1 -0
- package/dist/components/layout/stack/index.cjs +18 -2
- package/dist/components/layout/stack/index.cjs.map +1 -1
- package/dist/components/layout/stack/index.d.cts +8 -6
- package/dist/components/layout/stack/index.d.ts +8 -6
- package/dist/components/layout/stack/index.js +18 -2
- package/dist/components/layout/stack/index.js.map +1 -1
- package/dist/components/layout/stack/stack.css +118 -138
- package/dist/components/navigation/accordion/index.cjs.map +1 -1
- package/dist/components/navigation/accordion/index.js.map +1 -1
- package/dist/components/navigation/carousel/index.cjs +5 -2
- package/dist/components/navigation/carousel/index.cjs.map +1 -1
- package/dist/components/navigation/carousel/index.js +5 -2
- package/dist/components/navigation/carousel/index.js.map +1 -1
- package/dist/components/navigation/pagination/index.cjs +146 -0
- package/dist/components/navigation/pagination/index.cjs.map +1 -0
- package/dist/components/navigation/pagination/index.d.cts +3 -0
- package/dist/components/navigation/pagination/index.d.ts +3 -0
- package/dist/components/navigation/pagination/index.js +146 -0
- package/dist/components/navigation/pagination/index.js.map +1 -0
- package/dist/components/navigation/pagination/pagination.css +134 -0
- package/dist/components/navigation/pagination/pagination.types.d.cts +38 -0
- package/dist/components/navigation/pagination/pagination.types.d.ts +38 -0
- package/dist/components/navigation/pagination/pagination.utils.cjs +54 -0
- package/dist/components/navigation/pagination/pagination.utils.cjs.map +1 -0
- package/dist/components/navigation/pagination/pagination.utils.js +53 -0
- package/dist/components/navigation/pagination/pagination.utils.js.map +1 -0
- package/dist/components/navigation/tabs/index.d.cts +3 -2
- package/dist/components/navigation/tabs/index.d.ts +3 -2
- package/dist/components/navigation/tree-view/index.cjs.map +1 -1
- package/dist/components/navigation/tree-view/index.js.map +1 -1
- package/dist/components/overlays/context-menu/context-menu.css +151 -0
- package/dist/components/overlays/context-menu/context-menu.types.d.cts +69 -0
- package/dist/components/overlays/context-menu/context-menu.types.d.ts +69 -0
- package/dist/components/overlays/context-menu/context-menu.utils.cjs +46 -0
- package/dist/components/overlays/context-menu/context-menu.utils.cjs.map +1 -0
- package/dist/components/overlays/context-menu/context-menu.utils.js +40 -0
- package/dist/components/overlays/context-menu/context-menu.utils.js.map +1 -0
- package/dist/components/overlays/context-menu/index.cjs +830 -0
- package/dist/components/overlays/context-menu/index.cjs.map +1 -0
- package/dist/components/overlays/context-menu/index.d.cts +42 -0
- package/dist/components/overlays/context-menu/index.d.ts +42 -0
- package/dist/components/overlays/context-menu/index.js +818 -0
- package/dist/components/overlays/context-menu/index.js.map +1 -0
- package/dist/components/overlays/dropdown-menu/dropdown-menu-content.cjs.map +1 -1
- package/dist/components/overlays/dropdown-menu/dropdown-menu-content.js.map +1 -1
- package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.cjs.map +1 -1
- package/dist/components/overlays/dropdown-menu/dropdown-menu.utils.js.map +1 -1
- package/dist/components/typography/heading.cjs +6 -2
- package/dist/components/typography/heading.cjs.map +1 -1
- package/dist/components/typography/heading.d.cts +3 -2
- package/dist/components/typography/heading.d.ts +3 -2
- package/dist/components/typography/heading.js +6 -2
- package/dist/components/typography/heading.js.map +1 -1
- package/dist/components/typography/text.cjs +6 -2
- package/dist/components/typography/text.cjs.map +1 -1
- package/dist/components/typography/text.d.cts +3 -2
- package/dist/components/typography/text.d.ts +3 -2
- package/dist/components/typography/text.js +6 -2
- package/dist/components/typography/text.js.map +1 -1
- package/dist/components/utilities/preview/index.cjs +89 -21
- package/dist/components/utilities/preview/index.cjs.map +1 -1
- package/dist/components/utilities/preview/index.d.cts +6 -2
- package/dist/components/utilities/preview/index.d.ts +6 -2
- package/dist/components/utilities/preview/index.js +89 -21
- package/dist/components/utilities/preview/index.js.map +1 -1
- package/dist/components/utilities/preview/preview.css +26 -11
- package/dist/components/utilities/transition/index.d.cts +1 -1
- package/dist/components/utilities/transition/index.d.ts +1 -1
- package/dist/index.cjs +136 -97
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +12 -1
- package/package.json +7 -6
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Popout } from "../../overlays/popout/index.js";
|
|
3
|
+
import { DEFAULT_HSV, hsvToFormat, parseColorToHsvInBrowser, resolveCssColor } from "./color-picker.utils.js";
|
|
4
|
+
import "./color-picker.css";
|
|
5
|
+
import { clamp, cn, isColorDark } from "@puzzle-ui/core";
|
|
6
|
+
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
// src/components/forms/color-picker/index.tsx
|
|
9
|
+
const getSwatchValue = (swatch) => typeof swatch === "string" ? swatch : swatch.value;
|
|
10
|
+
const getSwatchLabel = (swatch) => typeof swatch === "string" ? swatch : swatch.label ?? swatch.value;
|
|
11
|
+
const ColorPicker = (props) => {
|
|
12
|
+
const { value, defaultValue, onChange, label, description, placeholder = "Select color", colors = [], format = "hexa", clearable = true, clearLabel = "Clear color", open, defaultOpen = false, onOpenChange, position = "bottom", align = "start", disabled = false, className, style, rootClassName, popoverClassName, id, ref, ...triggerProps } = props;
|
|
13
|
+
const generatedId = useId();
|
|
14
|
+
const triggerId = id ?? generatedId;
|
|
15
|
+
const labelId = `${generatedId}-label`;
|
|
16
|
+
const descriptionId = `${generatedId}-description`;
|
|
17
|
+
const panelId = `${generatedId}-panel`;
|
|
18
|
+
const areaId = `${generatedId}-area`;
|
|
19
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
20
|
+
const isControlled = Object.prototype.hasOwnProperty.call(props, "value");
|
|
21
|
+
const selectedColor = isControlled ? value : internalValue;
|
|
22
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
23
|
+
const isOpen = open ?? internalOpen;
|
|
24
|
+
const [hsv, setHsv] = useState(() => (selectedColor ? parseColorToHsvInBrowser(selectedColor) : null) ?? DEFAULT_HSV);
|
|
25
|
+
const [inputValue, setInputValue] = useState(selectedColor ?? "");
|
|
26
|
+
const [inputError, setInputError] = useState(false);
|
|
27
|
+
const areaRef = useRef(null);
|
|
28
|
+
const changeOpen = useCallback((nextOpen) => {
|
|
29
|
+
if (open === void 0) setInternalOpen(nextOpen);
|
|
30
|
+
onOpenChange?.(nextOpen);
|
|
31
|
+
}, [open, onOpenChange]);
|
|
32
|
+
const commitColor = useCallback((nextColor) => {
|
|
33
|
+
if (!isControlled) setInternalValue(nextColor);
|
|
34
|
+
onChange?.(nextColor);
|
|
35
|
+
setInputValue(nextColor ?? "");
|
|
36
|
+
setInputError(false);
|
|
37
|
+
}, [isControlled, onChange]);
|
|
38
|
+
const updateHsv = useCallback((next) => {
|
|
39
|
+
const normalized = {
|
|
40
|
+
h: (next.h % 360 + 360) % 360,
|
|
41
|
+
s: clamp(next.s, 0, 100),
|
|
42
|
+
v: clamp(next.v, 0, 100),
|
|
43
|
+
a: clamp(next.a, 0, 1)
|
|
44
|
+
};
|
|
45
|
+
setHsv(normalized);
|
|
46
|
+
commitColor(hsvToFormat(normalized, format));
|
|
47
|
+
}, [commitColor, format]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!selectedColor) {
|
|
50
|
+
setHsv(DEFAULT_HSV);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const parsed = parseColorToHsvInBrowser(selectedColor);
|
|
54
|
+
if (parsed) setHsv(parsed);
|
|
55
|
+
}, [selectedColor]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!isOpen) {
|
|
58
|
+
setInputValue(selectedColor ?? "");
|
|
59
|
+
setInputError(false);
|
|
60
|
+
}
|
|
61
|
+
}, [isOpen, selectedColor]);
|
|
62
|
+
const updateArea = (event) => {
|
|
63
|
+
if (event.type === "pointermove" && event.buttons !== 1) return;
|
|
64
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
65
|
+
if (rect.width <= 0 || rect.height <= 0) return;
|
|
66
|
+
const saturation = clamp((event.clientX - rect.left) / rect.width * 100, 0, 100);
|
|
67
|
+
const brightness = clamp((1 - (event.clientY - rect.top) / rect.height) * 100, 0, 100);
|
|
68
|
+
updateHsv({
|
|
69
|
+
...hsv,
|
|
70
|
+
s: saturation,
|
|
71
|
+
v: brightness
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const handleAreaKeyDown = (event) => {
|
|
75
|
+
const step = event.shiftKey ? 10 : 1;
|
|
76
|
+
let saturation = hsv.s;
|
|
77
|
+
let brightness = hsv.v;
|
|
78
|
+
switch (event.key) {
|
|
79
|
+
case "ArrowLeft":
|
|
80
|
+
saturation -= step;
|
|
81
|
+
break;
|
|
82
|
+
case "ArrowRight":
|
|
83
|
+
saturation += step;
|
|
84
|
+
break;
|
|
85
|
+
case "ArrowUp":
|
|
86
|
+
brightness += step;
|
|
87
|
+
break;
|
|
88
|
+
case "ArrowDown":
|
|
89
|
+
brightness -= step;
|
|
90
|
+
break;
|
|
91
|
+
case "Home":
|
|
92
|
+
saturation = 0;
|
|
93
|
+
break;
|
|
94
|
+
case "End":
|
|
95
|
+
saturation = 100;
|
|
96
|
+
break;
|
|
97
|
+
default: return;
|
|
98
|
+
}
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
updateHsv({
|
|
101
|
+
...hsv,
|
|
102
|
+
s: saturation,
|
|
103
|
+
v: brightness
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
const selectSwatch = (color) => {
|
|
107
|
+
commitColor(color);
|
|
108
|
+
const parsed = parseColorToHsvInBrowser(color);
|
|
109
|
+
if (parsed) setHsv(parsed);
|
|
110
|
+
};
|
|
111
|
+
const applyInput = () => {
|
|
112
|
+
const color = inputValue.trim();
|
|
113
|
+
const parsed = parseColorToHsvInBrowser(color);
|
|
114
|
+
if (!parsed) {
|
|
115
|
+
setInputError(true);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
commitColor(color);
|
|
119
|
+
setHsv(parsed);
|
|
120
|
+
};
|
|
121
|
+
const hueColor = `hsl(${hsv.h}, 100%, 50%)`;
|
|
122
|
+
const colorAreaStyle = { "--puzzle-color-picker-hue": hueColor };
|
|
123
|
+
const triggerSwatchStyle = { background: selectedColor ? resolveCssColor(selectedColor) ?? selectedColor : void 0 };
|
|
124
|
+
const clearColor = () => {
|
|
125
|
+
commitColor(void 0);
|
|
126
|
+
setHsv(DEFAULT_HSV);
|
|
127
|
+
};
|
|
128
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
129
|
+
className: cn("puzzle-color-picker", rootClassName),
|
|
130
|
+
"data-disabled": disabled || void 0,
|
|
131
|
+
children: [
|
|
132
|
+
label && /* @__PURE__ */ jsx("label", {
|
|
133
|
+
id: labelId,
|
|
134
|
+
className: "puzzle-color-picker__label",
|
|
135
|
+
htmlFor: triggerId,
|
|
136
|
+
children: label
|
|
137
|
+
}),
|
|
138
|
+
/* @__PURE__ */ jsx(Popout, {
|
|
139
|
+
position,
|
|
140
|
+
align,
|
|
141
|
+
action: "click",
|
|
142
|
+
open: isOpen,
|
|
143
|
+
onOpenChange: changeOpen,
|
|
144
|
+
closeOnOutsideClick: true,
|
|
145
|
+
closeOnEscape: true,
|
|
146
|
+
contentClassName: cn("puzzle-color-picker__popover", popoverClassName),
|
|
147
|
+
trigger: /* @__PURE__ */ jsxs("button", {
|
|
148
|
+
...triggerProps,
|
|
149
|
+
ref,
|
|
150
|
+
id: triggerId,
|
|
151
|
+
type: "button",
|
|
152
|
+
className: cn("puzzle-color-picker__trigger", className),
|
|
153
|
+
style,
|
|
154
|
+
disabled,
|
|
155
|
+
"aria-label": label ? void 0 : "Choose color",
|
|
156
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
157
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
158
|
+
"aria-haspopup": "dialog",
|
|
159
|
+
"aria-expanded": isOpen,
|
|
160
|
+
"aria-controls": isOpen ? panelId : void 0,
|
|
161
|
+
children: [
|
|
162
|
+
/* @__PURE__ */ jsx("span", {
|
|
163
|
+
className: "puzzle-color-picker__trigger-swatch",
|
|
164
|
+
style: triggerSwatchStyle,
|
|
165
|
+
"aria-hidden": "true"
|
|
166
|
+
}),
|
|
167
|
+
/* @__PURE__ */ jsx("span", {
|
|
168
|
+
className: "puzzle-color-picker__trigger-value",
|
|
169
|
+
children: selectedColor ?? placeholder
|
|
170
|
+
}),
|
|
171
|
+
/* @__PURE__ */ jsx("span", {
|
|
172
|
+
className: "puzzle-color-picker__trigger-chevron",
|
|
173
|
+
"aria-hidden": "true",
|
|
174
|
+
children: "▾"
|
|
175
|
+
})
|
|
176
|
+
]
|
|
177
|
+
}),
|
|
178
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
179
|
+
id: panelId,
|
|
180
|
+
className: "puzzle-color-picker__panel",
|
|
181
|
+
role: "dialog",
|
|
182
|
+
"aria-label": label ? `Choose ${label}` : "Choose color",
|
|
183
|
+
children: [
|
|
184
|
+
/* @__PURE__ */ jsxs("div", {
|
|
185
|
+
ref: areaRef,
|
|
186
|
+
id: areaId,
|
|
187
|
+
className: "puzzle-color-picker__area",
|
|
188
|
+
style: colorAreaStyle,
|
|
189
|
+
onPointerDown: (event) => {
|
|
190
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
191
|
+
updateArea(event);
|
|
192
|
+
},
|
|
193
|
+
onPointerMove: updateArea,
|
|
194
|
+
onKeyDown: handleAreaKeyDown,
|
|
195
|
+
role: "group",
|
|
196
|
+
"aria-label": "Color saturation and brightness",
|
|
197
|
+
tabIndex: 0,
|
|
198
|
+
children: [
|
|
199
|
+
/* @__PURE__ */ jsx("span", {
|
|
200
|
+
className: "puzzle-color-picker__area-saturation",
|
|
201
|
+
"aria-hidden": "true"
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsx("span", {
|
|
204
|
+
className: "puzzle-color-picker__area-brightness",
|
|
205
|
+
"aria-hidden": "true"
|
|
206
|
+
}),
|
|
207
|
+
/* @__PURE__ */ jsx("span", {
|
|
208
|
+
className: "puzzle-color-picker__area-indicator",
|
|
209
|
+
style: {
|
|
210
|
+
left: `${hsv.s}%`,
|
|
211
|
+
top: `${100 - hsv.v}%`
|
|
212
|
+
},
|
|
213
|
+
"aria-hidden": "true"
|
|
214
|
+
})
|
|
215
|
+
]
|
|
216
|
+
}),
|
|
217
|
+
/* @__PURE__ */ jsxs("div", {
|
|
218
|
+
className: "puzzle-color-picker__sliders",
|
|
219
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
220
|
+
className: "puzzle-color-picker__slider-row",
|
|
221
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Hue" }), /* @__PURE__ */ jsx("input", {
|
|
222
|
+
type: "range",
|
|
223
|
+
min: 0,
|
|
224
|
+
max: 359,
|
|
225
|
+
value: Math.round(hsv.h),
|
|
226
|
+
"aria-label": "Hue",
|
|
227
|
+
onChange: (event) => updateHsv({
|
|
228
|
+
...hsv,
|
|
229
|
+
h: Number(event.currentTarget.value)
|
|
230
|
+
}),
|
|
231
|
+
className: "puzzle-color-picker__hue-slider"
|
|
232
|
+
})]
|
|
233
|
+
}), /* @__PURE__ */ jsxs("label", {
|
|
234
|
+
className: "puzzle-color-picker__slider-row",
|
|
235
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Opacity" }), /* @__PURE__ */ jsx("input", {
|
|
236
|
+
type: "range",
|
|
237
|
+
min: 0,
|
|
238
|
+
max: 100,
|
|
239
|
+
value: Math.round(hsv.a * 100),
|
|
240
|
+
"aria-label": "Opacity",
|
|
241
|
+
onChange: (event) => updateHsv({
|
|
242
|
+
...hsv,
|
|
243
|
+
a: Number(event.currentTarget.value) / 100
|
|
244
|
+
}),
|
|
245
|
+
className: "puzzle-color-picker__opacity-slider",
|
|
246
|
+
style: { "--puzzle-color-picker-hue": hueColor }
|
|
247
|
+
})]
|
|
248
|
+
})]
|
|
249
|
+
}),
|
|
250
|
+
/* @__PURE__ */ jsxs("div", {
|
|
251
|
+
className: "puzzle-color-picker__input-section",
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsx("label", {
|
|
254
|
+
htmlFor: `${generatedId}-input`,
|
|
255
|
+
className: "puzzle-color-picker__input-label",
|
|
256
|
+
children: "Color value"
|
|
257
|
+
}),
|
|
258
|
+
/* @__PURE__ */ jsxs("div", {
|
|
259
|
+
className: "puzzle-color-picker__input-row",
|
|
260
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
261
|
+
id: `${generatedId}-input`,
|
|
262
|
+
type: "text",
|
|
263
|
+
value: inputValue,
|
|
264
|
+
spellCheck: false,
|
|
265
|
+
autoComplete: "off",
|
|
266
|
+
"aria-label": "Color value",
|
|
267
|
+
"aria-invalid": inputError || void 0,
|
|
268
|
+
placeholder: "#RRGGBB",
|
|
269
|
+
onChange: (event) => {
|
|
270
|
+
setInputValue(event.currentTarget.value);
|
|
271
|
+
setInputError(false);
|
|
272
|
+
},
|
|
273
|
+
onKeyDown: (event) => {
|
|
274
|
+
if (event.key === "Enter") {
|
|
275
|
+
event.preventDefault();
|
|
276
|
+
applyInput();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
280
|
+
type: "button",
|
|
281
|
+
className: "puzzle-color-picker__apply",
|
|
282
|
+
onClick: applyInput,
|
|
283
|
+
children: "Apply"
|
|
284
|
+
})]
|
|
285
|
+
}),
|
|
286
|
+
inputError && /* @__PURE__ */ jsx("p", {
|
|
287
|
+
className: "puzzle-color-picker__error",
|
|
288
|
+
role: "alert",
|
|
289
|
+
children: "Enter a valid CSS color."
|
|
290
|
+
})
|
|
291
|
+
]
|
|
292
|
+
}),
|
|
293
|
+
(clearable || colors.length > 0) && /* @__PURE__ */ jsxs("div", {
|
|
294
|
+
className: "puzzle-color-picker__swatches-section",
|
|
295
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
296
|
+
className: "puzzle-color-picker__section-label",
|
|
297
|
+
children: "Presets"
|
|
298
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
299
|
+
className: "puzzle-color-picker__swatches",
|
|
300
|
+
role: "group",
|
|
301
|
+
"aria-label": "Preset colors",
|
|
302
|
+
children: [clearable && /* @__PURE__ */ jsx("button", {
|
|
303
|
+
type: "button",
|
|
304
|
+
className: "puzzle-color-picker__swatch puzzle-color-picker__clear",
|
|
305
|
+
"aria-label": clearLabel,
|
|
306
|
+
"aria-pressed": selectedColor === void 0,
|
|
307
|
+
title: clearLabel,
|
|
308
|
+
onClick: clearColor,
|
|
309
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true" })
|
|
310
|
+
}), colors.map((swatch, index) => {
|
|
311
|
+
const color = getSwatchValue(swatch);
|
|
312
|
+
const swatchLabel = getSwatchLabel(swatch);
|
|
313
|
+
return /* @__PURE__ */ jsx("button", {
|
|
314
|
+
type: "button",
|
|
315
|
+
className: "puzzle-color-picker__swatch",
|
|
316
|
+
style: { background: resolveCssColor(color) ?? color },
|
|
317
|
+
"aria-label": swatchLabel,
|
|
318
|
+
"aria-pressed": selectedColor === color,
|
|
319
|
+
title: swatchLabel,
|
|
320
|
+
"data-selected": selectedColor === color || void 0,
|
|
321
|
+
"data-dark": isColorDark(color) || void 0,
|
|
322
|
+
onClick: () => selectSwatch(color)
|
|
323
|
+
}, `${color}-${index}`);
|
|
324
|
+
})]
|
|
325
|
+
})]
|
|
326
|
+
})
|
|
327
|
+
]
|
|
328
|
+
})
|
|
329
|
+
}),
|
|
330
|
+
description && /* @__PURE__ */ jsx("span", {
|
|
331
|
+
id: descriptionId,
|
|
332
|
+
className: "puzzle-color-picker__description",
|
|
333
|
+
children: description
|
|
334
|
+
})
|
|
335
|
+
]
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
export { ColorPicker };
|
|
339
|
+
|
|
340
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/forms/color-picker/index.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n} from \"react\";\n\nimport { clamp, cn, isColorDark } from \"@puzzle-ui/core\";\n\nimport { Popout } from \"../../overlays/popout\";\n\nimport {\n DEFAULT_HSV,\n hsvToFormat,\n parseColorToHsvInBrowser,\n resolveCssColor,\n type HSVColor,\n} from \"./color-picker.utils\";\n\nimport type {\n ColorPickerFormat,\n ColorPickerProps,\n ColorPickerSwatch,\n} from \"./color-picker.types\";\n\nimport \"./color-picker.css\";\n\nconst getSwatchValue = (swatch: ColorPickerSwatch): string =>\n typeof swatch === \"string\" ? swatch : swatch.value;\n\nconst getSwatchLabel = (swatch: ColorPickerSwatch): string =>\n typeof swatch === \"string\" ? swatch : (swatch.label ?? swatch.value);\n\nconst ColorPicker = (props: ColorPickerProps) => {\n const {\n value,\n defaultValue,\n onChange,\n label,\n description,\n placeholder = \"Select color\",\n colors = [],\n format = \"hexa\",\n clearable = true,\n clearLabel = \"Clear color\",\n open,\n defaultOpen = false,\n onOpenChange,\n position = \"bottom\",\n align = \"start\",\n disabled = false,\n className,\n style,\n rootClassName,\n popoverClassName,\n id,\n ref,\n ...triggerProps\n } = props;\n\n const generatedId = useId();\n\n const triggerId = id ?? generatedId;\n const labelId = `${generatedId}-label`;\n const descriptionId = `${generatedId}-description`;\n const panelId = `${generatedId}-panel`;\n const areaId = `${generatedId}-area`;\n\n const [internalValue, setInternalValue] = useState<string | undefined>(\n defaultValue,\n );\n\n const isControlled = Object.prototype.hasOwnProperty.call(props, \"value\");\n\n const selectedColor = isControlled ? value : internalValue;\n\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isOpen = open ?? internalOpen;\n\n const [hsv, setHsv] = useState<HSVColor>(\n () =>\n (selectedColor ? parseColorToHsvInBrowser(selectedColor) : null) ??\n DEFAULT_HSV,\n );\n\n const [inputValue, setInputValue] = useState(selectedColor ?? \"\");\n const [inputError, setInputError] = useState(false);\n\n const areaRef = useRef<HTMLDivElement>(null);\n\n const changeOpen = useCallback(\n (nextOpen: boolean) => {\n if (open === undefined) setInternalOpen(nextOpen);\n\n onOpenChange?.(nextOpen);\n },\n [open, onOpenChange],\n );\n\n const commitColor = useCallback(\n (nextColor: string | undefined) => {\n if (!isControlled) {\n setInternalValue(nextColor);\n }\n\n onChange?.(nextColor);\n\n setInputValue(nextColor ?? \"\");\n setInputError(false);\n },\n [isControlled, onChange],\n );\n\n const updateHsv = useCallback(\n (next: HSVColor) => {\n const normalized: HSVColor = {\n h: ((next.h % 360) + 360) % 360,\n s: clamp(next.s, 0, 100),\n v: clamp(next.v, 0, 100),\n a: clamp(next.a, 0, 1),\n };\n\n setHsv(normalized);\n commitColor(hsvToFormat(normalized, format));\n },\n [commitColor, format],\n );\n\n useEffect(() => {\n if (!selectedColor) {\n setHsv(DEFAULT_HSV);\n return;\n }\n\n const parsed = parseColorToHsvInBrowser(selectedColor);\n\n if (parsed) setHsv(parsed);\n }, [selectedColor]);\n\n useEffect(() => {\n if (!isOpen) {\n setInputValue(selectedColor ?? \"\");\n setInputError(false);\n }\n }, [isOpen, selectedColor]);\n\n const updateArea = (event: PointerEvent<HTMLDivElement>) => {\n if (event.type === \"pointermove\" && event.buttons !== 1) return;\n\n const rect = event.currentTarget.getBoundingClientRect();\n\n if (rect.width <= 0 || rect.height <= 0) return;\n\n const saturation = clamp(\n ((event.clientX - rect.left) / rect.width) * 100,\n 0,\n 100,\n );\n\n const brightness = clamp(\n (1 - (event.clientY - rect.top) / rect.height) * 100,\n 0,\n 100,\n );\n\n updateHsv({\n ...hsv,\n s: saturation,\n v: brightness,\n });\n };\n\n const handleAreaKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const step = event.shiftKey ? 10 : 1;\n\n let saturation = hsv.s;\n let brightness = hsv.v;\n\n switch (event.key) {\n case \"ArrowLeft\":\n saturation -= step;\n break;\n case \"ArrowRight\":\n saturation += step;\n break;\n case \"ArrowUp\":\n brightness += step;\n break;\n case \"ArrowDown\":\n brightness -= step;\n break;\n case \"Home\":\n saturation = 0;\n break;\n case \"End\":\n saturation = 100;\n break;\n default:\n return;\n }\n\n event.preventDefault();\n\n updateHsv({\n ...hsv,\n s: saturation,\n v: brightness,\n });\n };\n\n const selectSwatch = (color: string) => {\n commitColor(color);\n\n const parsed = parseColorToHsvInBrowser(color);\n\n if (parsed) setHsv(parsed);\n };\n\n const applyInput = () => {\n const color = inputValue.trim();\n\n const parsed = parseColorToHsvInBrowser(color);\n\n if (!parsed) {\n setInputError(true);\n return;\n }\n\n commitColor(color);\n setHsv(parsed);\n };\n\n const hueColor = `hsl(${hsv.h}, 100%, 50%)`;\n\n const colorAreaStyle = {\n \"--puzzle-color-picker-hue\": hueColor,\n } as CSSProperties;\n\n const currentColor = selectedColor\n ? (resolveCssColor(selectedColor) ?? selectedColor)\n : undefined;\n\n const triggerSwatchStyle = {\n background: currentColor,\n } as CSSProperties;\n\n const clearColor = () => {\n commitColor(undefined);\n setHsv(DEFAULT_HSV);\n };\n\n return (\n <div\n className={cn(\"puzzle-color-picker\", rootClassName)}\n data-disabled={disabled || undefined}\n >\n {label && (\n <label\n id={labelId}\n className=\"puzzle-color-picker__label\"\n htmlFor={triggerId}\n >\n {label}\n </label>\n )}\n\n <Popout\n position={position}\n align={align}\n action=\"click\"\n open={isOpen}\n onOpenChange={changeOpen}\n closeOnOutsideClick\n closeOnEscape\n contentClassName={cn(\"puzzle-color-picker__popover\", popoverClassName)}\n trigger={\n <button\n {...triggerProps}\n ref={ref}\n id={triggerId}\n type=\"button\"\n className={cn(\"puzzle-color-picker__trigger\", className)}\n style={style}\n disabled={disabled}\n aria-label={label ? undefined : \"Choose color\"}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={description ? descriptionId : undefined}\n aria-haspopup=\"dialog\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n >\n <span\n className=\"puzzle-color-picker__trigger-swatch\"\n style={triggerSwatchStyle}\n aria-hidden=\"true\"\n />\n\n <span className=\"puzzle-color-picker__trigger-value\">\n {selectedColor ?? placeholder}\n </span>\n\n <span\n className=\"puzzle-color-picker__trigger-chevron\"\n aria-hidden=\"true\"\n >\n ▾\n </span>\n </button>\n }\n >\n <div\n id={panelId}\n className=\"puzzle-color-picker__panel\"\n role=\"dialog\"\n aria-label={label ? `Choose ${label}` : \"Choose color\"}\n >\n <div\n ref={areaRef}\n id={areaId}\n className=\"puzzle-color-picker__area\"\n style={colorAreaStyle}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n updateArea(event);\n }}\n onPointerMove={updateArea}\n onKeyDown={handleAreaKeyDown}\n role=\"group\"\n aria-label=\"Color saturation and brightness\"\n tabIndex={0}\n >\n <span\n className=\"puzzle-color-picker__area-saturation\"\n aria-hidden=\"true\"\n />\n\n <span\n className=\"puzzle-color-picker__area-brightness\"\n aria-hidden=\"true\"\n />\n\n <span\n className=\"puzzle-color-picker__area-indicator\"\n style={{\n left: `${hsv.s}%`,\n top: `${100 - hsv.v}%`,\n }}\n aria-hidden=\"true\"\n />\n </div>\n\n <div className=\"puzzle-color-picker__sliders\">\n <label className=\"puzzle-color-picker__slider-row\">\n <span>Hue</span>\n\n <input\n type=\"range\"\n min={0}\n max={359}\n value={Math.round(hsv.h)}\n aria-label=\"Hue\"\n onChange={(event) =>\n updateHsv({\n ...hsv,\n h: Number(event.currentTarget.value),\n })\n }\n className=\"puzzle-color-picker__hue-slider\"\n />\n </label>\n\n <label className=\"puzzle-color-picker__slider-row\">\n <span>Opacity</span>\n\n <input\n type=\"range\"\n min={0}\n max={100}\n value={Math.round(hsv.a * 100)}\n aria-label=\"Opacity\"\n onChange={(event) =>\n updateHsv({\n ...hsv,\n a: Number(event.currentTarget.value) / 100,\n })\n }\n className=\"puzzle-color-picker__opacity-slider\"\n style={\n {\n \"--puzzle-color-picker-hue\": hueColor,\n } as CSSProperties\n }\n />\n </label>\n </div>\n\n <div className=\"puzzle-color-picker__input-section\">\n <label\n htmlFor={`${generatedId}-input`}\n className=\"puzzle-color-picker__input-label\"\n >\n Color value\n </label>\n\n <div className=\"puzzle-color-picker__input-row\">\n <input\n id={`${generatedId}-input`}\n type=\"text\"\n value={inputValue}\n spellCheck={false}\n autoComplete=\"off\"\n aria-label=\"Color value\"\n aria-invalid={inputError || undefined}\n placeholder=\"#RRGGBB\"\n onChange={(event) => {\n setInputValue(event.currentTarget.value);\n setInputError(false);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n applyInput();\n }\n }}\n />\n\n <button\n type=\"button\"\n className=\"puzzle-color-picker__apply\"\n onClick={applyInput}\n >\n Apply\n </button>\n </div>\n\n {inputError && (\n <p className=\"puzzle-color-picker__error\" role=\"alert\">\n Enter a valid CSS color.\n </p>\n )}\n </div>\n\n {(clearable || colors.length > 0) && (\n <div className=\"puzzle-color-picker__swatches-section\">\n <span className=\"puzzle-color-picker__section-label\">\n Presets\n </span>\n\n <div\n className=\"puzzle-color-picker__swatches\"\n role=\"group\"\n aria-label=\"Preset colors\"\n >\n {clearable && (\n <button\n type=\"button\"\n className=\"puzzle-color-picker__swatch puzzle-color-picker__clear\"\n aria-label={clearLabel}\n aria-pressed={selectedColor === undefined}\n title={clearLabel}\n onClick={clearColor}\n >\n <span aria-hidden=\"true\" />\n </button>\n )}\n\n {colors.map((swatch, index) => {\n const color = getSwatchValue(swatch);\n const swatchLabel = getSwatchLabel(swatch);\n\n return (\n <button\n key={`${color}-${index}`}\n type=\"button\"\n className=\"puzzle-color-picker__swatch\"\n style={{\n background: resolveCssColor(color) ?? color,\n }}\n aria-label={swatchLabel}\n aria-pressed={selectedColor === color}\n title={swatchLabel}\n data-selected={selectedColor === color || undefined}\n data-dark={isColorDark(color) || undefined}\n onClick={() => selectSwatch(color)}\n />\n );\n })}\n </div>\n </div>\n )}\n </div>\n </Popout>\n\n {description && (\n <span id={descriptionId} className=\"puzzle-color-picker__description\">\n {description}\n </span>\n )}\n </div>\n );\n};\n\nexport {\n ColorPicker,\n type ColorPickerProps,\n type ColorPickerFormat,\n type ColorPickerSwatch,\n};\n"],"mappings":";;;;;;;;AAiCA,MAAM,kBAAkB,WACtB,OAAO,WAAW,WAAW,SAAS,OAAO;AAE/C,MAAM,kBAAkB,WACtB,OAAO,WAAW,WAAW,SAAU,OAAO,SAAS,OAAO;AAEhE,MAAM,eAAe,UAA4B;CAC/C,MAAM,EACJ,OACA,cACA,UACA,OACA,aACA,cAAc,gBACd,SAAS,CAAC,GACV,SAAS,QACT,YAAY,MACZ,aAAa,eACb,MACA,cAAc,OACd,cACA,WAAW,UACX,QAAQ,SACR,WAAW,OACX,WACA,OACA,eACA,kBACA,IACA,KACA,GAAG,iBACD;CAEJ,MAAM,cAAc,MAAM;CAE1B,MAAM,YAAY,MAAM;CACxB,MAAM,UAAU,GAAG,YAAY;CAC/B,MAAM,gBAAgB,GAAG,YAAY;CACrC,MAAM,UAAU,GAAG,YAAY;CAC/B,MAAM,SAAS,GAAG,YAAY;CAE9B,MAAM,CAAC,eAAe,oBAAoB,SACxC,YACF;CAEA,MAAM,eAAe,OAAO,UAAU,eAAe,KAAK,OAAO,OAAO;CAExE,MAAM,gBAAgB,eAAe,QAAQ;CAE7C,MAAM,CAAC,cAAc,mBAAmB,SAAS,WAAW;CAC5D,MAAM,SAAS,QAAQ;CAEvB,MAAM,CAAC,KAAK,UAAU,gBAEjB,gBAAgB,yBAAyB,aAAa,IAAI,SAC3D,WACJ;CAEA,MAAM,CAAC,YAAY,iBAAiB,SAAS,iBAAiB,EAAE;CAChE,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAElD,MAAM,UAAU,OAAuB,IAAI;CAE3C,MAAM,aAAa,aAChB,aAAsB;EACrB,IAAI,SAAS,KAAA,GAAW,gBAAgB,QAAQ;EAEhD,eAAe,QAAQ;CACzB,GACA,CAAC,MAAM,YAAY,CACrB;CAEA,MAAM,cAAc,aACjB,cAAkC;EACjC,IAAI,CAAC,cACH,iBAAiB,SAAS;EAG5B,WAAW,SAAS;EAEpB,cAAc,aAAa,EAAE;EAC7B,cAAc,KAAK;CACrB,GACA,CAAC,cAAc,QAAQ,CACzB;CAEA,MAAM,YAAY,aACf,SAAmB;EAClB,MAAM,aAAuB;GAC3B,IAAK,KAAK,IAAI,MAAO,OAAO;GAC5B,GAAG,MAAM,KAAK,GAAG,GAAG,GAAG;GACvB,GAAG,MAAM,KAAK,GAAG,GAAG,GAAG;GACvB,GAAG,MAAM,KAAK,GAAG,GAAG,CAAC;EACvB;EAEA,OAAO,UAAU;EACjB,YAAY,YAAY,YAAY,MAAM,CAAC;CAC7C,GACA,CAAC,aAAa,MAAM,CACtB;CAEA,gBAAgB;EACd,IAAI,CAAC,eAAe;GAClB,OAAO,WAAW;GAClB;EACF;EAEA,MAAM,SAAS,yBAAyB,aAAa;EAErD,IAAI,QAAQ,OAAO,MAAM;CAC3B,GAAG,CAAC,aAAa,CAAC;CAElB,gBAAgB;EACd,IAAI,CAAC,QAAQ;GACX,cAAc,iBAAiB,EAAE;GACjC,cAAc,KAAK;EACrB;CACF,GAAG,CAAC,QAAQ,aAAa,CAAC;CAE1B,MAAM,cAAc,UAAwC;EAC1D,IAAI,MAAM,SAAS,iBAAiB,MAAM,YAAY,GAAG;EAEzD,MAAM,OAAO,MAAM,cAAc,sBAAsB;EAEvD,IAAI,KAAK,SAAS,KAAK,KAAK,UAAU,GAAG;EAEzC,MAAM,aAAa,OACf,MAAM,UAAU,KAAK,QAAQ,KAAK,QAAS,KAC7C,GACA,GACF;EAEA,MAAM,aAAa,OAChB,KAAK,MAAM,UAAU,KAAK,OAAO,KAAK,UAAU,KACjD,GACA,GACF;EAEA,UAAU;GACR,GAAG;GACH,GAAG;GACH,GAAG;EACL,CAAC;CACH;CAEA,MAAM,qBAAqB,UAAyC;EAClE,MAAM,OAAO,MAAM,WAAW,KAAK;EAEnC,IAAI,aAAa,IAAI;EACrB,IAAI,aAAa,IAAI;EAErB,QAAQ,MAAM,KAAd;GACE,KAAK;IACH,cAAc;IACd;GACF,KAAK;IACH,cAAc;IACd;GACF,KAAK;IACH,cAAc;IACd;GACF,KAAK;IACH,cAAc;IACd;GACF,KAAK;IACH,aAAa;IACb;GACF,KAAK;IACH,aAAa;IACb;GACF,SACE;EACJ;EAEA,MAAM,eAAe;EAErB,UAAU;GACR,GAAG;GACH,GAAG;GACH,GAAG;EACL,CAAC;CACH;CAEA,MAAM,gBAAgB,UAAkB;EACtC,YAAY,KAAK;EAEjB,MAAM,SAAS,yBAAyB,KAAK;EAE7C,IAAI,QAAQ,OAAO,MAAM;CAC3B;CAEA,MAAM,mBAAmB;EACvB,MAAM,QAAQ,WAAW,KAAK;EAE9B,MAAM,SAAS,yBAAyB,KAAK;EAE7C,IAAI,CAAC,QAAQ;GACX,cAAc,IAAI;GAClB;EACF;EAEA,YAAY,KAAK;EACjB,OAAO,MAAM;CACf;CAEA,MAAM,WAAW,OAAO,IAAI,EAAE;CAE9B,MAAM,iBAAiB,EACrB,6BAA6B,SAC/B;CAMA,MAAM,qBAAqB,EACzB,YALmB,gBAChB,gBAAgB,aAAa,KAAK,gBACnC,KAAA,EAIJ;CAEA,MAAM,mBAAmB;EACvB,YAAY,KAAA,CAAS;EACrB,OAAO,WAAW;CACpB;CAEA,OACE,qBAAC,OAAD;EACE,WAAW,GAAG,uBAAuB,aAAa;EAClD,iBAAe,YAAY,KAAA;EAF7B,UAAA;GAIG,SACC,oBAAC,SAAD;IACE,IAAI;IACJ,WAAU;IACV,SAAS;IAER,UAAA;GACI,CAAA;GAGT,oBAAC,QAAD;IACY;IACH;IACP,QAAO;IACP,MAAM;IACN,cAAc;IACd,qBAAA;IACA,eAAA;IACA,kBAAkB,GAAG,gCAAgC,gBAAgB;IACrE,SACE,qBAAC,UAAD;KACE,GAAI;KACC;KACL,IAAI;KACJ,MAAK;KACL,WAAW,GAAG,gCAAgC,SAAS;KAChD;KACG;KACV,cAAY,QAAQ,KAAA,IAAY;KAChC,mBAAiB,QAAQ,UAAU,KAAA;KACnC,oBAAkB,cAAc,gBAAgB,KAAA;KAChD,iBAAc;KACd,iBAAe;KACf,iBAAe,SAAS,UAAU,KAAA;KAbpC,UAAA;MAeE,oBAAC,QAAD;OACE,WAAU;OACV,OAAO;OACP,eAAY;MACb,CAAA;MAED,oBAAC,QAAD;OAAM,WAAU;OACb,UAAA,iBAAiB;MACd,CAAA;MAEN,oBAAC,QAAD;OACE,WAAU;OACV,eAAY;OACb,UAAA;MAEK,CAAA;KACA;;IAGV,UAAA,qBAAC,OAAD;KACE,IAAI;KACJ,WAAU;KACV,MAAK;KACL,cAAY,QAAQ,UAAU,UAAU;KAJ1C,UAAA;MAME,qBAAC,OAAD;OACE,KAAK;OACL,IAAI;OACJ,WAAU;OACV,OAAO;OACP,gBAAgB,UAAU;QACxB,MAAM,cAAc,kBAAkB,MAAM,SAAS;QACrD,WAAW,KAAK;OAClB;OACA,eAAe;OACf,WAAW;OACX,MAAK;OACL,cAAW;OACX,UAAU;OAbZ,UAAA;QAeE,oBAAC,QAAD;SACE,WAAU;SACV,eAAY;QACb,CAAA;QAED,oBAAC,QAAD;SACE,WAAU;SACV,eAAY;QACb,CAAA;QAED,oBAAC,QAAD;SACE,WAAU;SACV,OAAO;UACL,MAAM,GAAG,IAAI,EAAE;UACf,KAAK,GAAG,MAAM,IAAI,EAAE;SACtB;SACA,eAAY;QACb,CAAA;OACE;;MAEL,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,qBAAC,SAAD;QAAO,WAAU;QAAjB,UAAA,CACE,oBAAC,QAAD,EAAA,UAAM,MAAS,CAAA,GAEf,oBAAC,SAAD;SACE,MAAK;SACL,KAAK;SACL,KAAK;SACL,OAAO,KAAK,MAAM,IAAI,CAAC;SACvB,cAAW;SACX,WAAW,UACT,UAAU;UACR,GAAG;UACH,GAAG,OAAO,MAAM,cAAc,KAAK;SACrC,CAAC;SAEH,WAAU;QACX,CAAA,CACI;OAEP,CAAA,GAAA,qBAAC,SAAD;QAAO,WAAU;QAAjB,UAAA,CACE,oBAAC,QAAD,EAAA,UAAM,UAAa,CAAA,GAEnB,oBAAC,SAAD;SACE,MAAK;SACL,KAAK;SACL,KAAK;SACL,OAAO,KAAK,MAAM,IAAI,IAAI,GAAG;SAC7B,cAAW;SACX,WAAW,UACT,UAAU;UACR,GAAG;UACH,GAAG,OAAO,MAAM,cAAc,KAAK,IAAI;SACzC,CAAC;SAEH,WAAU;SACV,OACE,EACE,6BAA6B,SAC/B;QAEH,CAAA,CACI;OACJ,CAAA,CAAA;;MAEL,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACE,oBAAC,SAAD;SACE,SAAS,GAAG,YAAY;SACxB,WAAU;SACX,UAAA;QAEM,CAAA;QAEP,qBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CACE,oBAAC,SAAD;UACE,IAAI,GAAG,YAAY;UACnB,MAAK;UACL,OAAO;UACP,YAAY;UACZ,cAAa;UACb,cAAW;UACX,gBAAc,cAAc,KAAA;UAC5B,aAAY;UACZ,WAAW,UAAU;WACnB,cAAc,MAAM,cAAc,KAAK;WACvC,cAAc,KAAK;UACrB;UACA,YAAY,UAAU;WACpB,IAAI,MAAM,QAAQ,SAAS;YACzB,MAAM,eAAe;YACrB,WAAW;WACb;UACF;SACD,CAAA,GAED,oBAAC,UAAD;UACE,MAAK;UACL,WAAU;UACV,SAAS;UACV,UAAA;SAEO,CAAA,CACL;;QAEJ,cACC,oBAAC,KAAD;SAAG,WAAU;SAA6B,MAAK;SAAQ,UAAA;QAEpD,CAAA;OAEF;;OAEH,aAAa,OAAO,SAAS,MAC7B,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,QAAD;QAAM,WAAU;QAAqC,UAAA;OAE/C,CAAA,GAEN,qBAAC,OAAD;QACE,WAAU;QACV,MAAK;QACL,cAAW;QAHb,UAAA,CAKG,aACC,oBAAC,UAAD;SACE,MAAK;SACL,WAAU;SACV,cAAY;SACZ,gBAAc,kBAAkB,KAAA;SAChC,OAAO;SACP,SAAS;SAET,UAAA,oBAAC,QAAD,EAAM,eAAY,OAAQ,CAAA;QACpB,CAAA,GAGT,OAAO,KAAK,QAAQ,UAAU;SAC7B,MAAM,QAAQ,eAAe,MAAM;SACnC,MAAM,cAAc,eAAe,MAAM;SAEzC,OACE,oBAAC,UAAD;UAEE,MAAK;UACL,WAAU;UACV,OAAO,EACL,YAAY,gBAAgB,KAAK,KAAK,MACxC;UACA,cAAY;UACZ,gBAAc,kBAAkB;UAChC,OAAO;UACP,iBAAe,kBAAkB,SAAS,KAAA;UAC1C,aAAW,YAAY,KAAK,KAAK,KAAA;UACjC,eAAe,aAAa,KAAK;SAClC,GAZM,GAAG,MAAM,GAAG,OAYlB;QAEL,CAAC,CACE;OACF,CAAA,CAAA;;KAEJ;;GACC,CAAA;GAEP,eACC,oBAAC,QAAD;IAAM,IAAI;IAAe,WAAU;IAChC,UAAA;GACG,CAAA;EAEL;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.utils.cjs","names":[],"sources":["../../../../src/components/forms/file-upload/file-upload.utils.ts"],"sourcesContent":["import type {\n FileUploadRejection,\n FileUploadRejectionCode,\n} from \"./file-upload.types\";\n\ntype FileValidationOptions = {\n accept?: readonly string[];\n maxFileSize?: number;\n maxTotalSize?: number;\n maxFiles?: number;\n multiple?: boolean;\n};\n\ntype FileValidationResult = {\n accepted: File[];\n rejected: FileUploadRejection[];\n};\n\nconst formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n\n if (!Number.isFinite(bytes) || bytes < 0) return \"0 B\";\n\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\n const index = Math.min(\n Math.floor(Math.log(bytes) / Math.log(1024)),\n units.length - 1,\n );\n\n const value = bytes / 1024 ** index;\n\n return `${value >= 10 || index === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[index]}`;\n};\n\nconst matchesMimeType = (\n fileType: string,\n acceptedTypes: readonly string[],\n): boolean => {\n const normalizedType = fileType.split(\";\")[0]
|
|
1
|
+
{"version":3,"file":"file-upload.utils.cjs","names":[],"sources":["../../../../src/components/forms/file-upload/file-upload.utils.ts"],"sourcesContent":["import type {\n FileUploadRejection,\n FileUploadRejectionCode,\n} from \"./file-upload.types\";\n\ntype FileValidationOptions = {\n accept?: readonly string[];\n maxFileSize?: number;\n maxTotalSize?: number;\n maxFiles?: number;\n multiple?: boolean;\n};\n\ntype FileValidationResult = {\n accepted: File[];\n rejected: FileUploadRejection[];\n};\n\nconst formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n\n if (!Number.isFinite(bytes) || bytes < 0) return \"0 B\";\n\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\n const index = Math.min(\n Math.floor(Math.log(bytes) / Math.log(1024)),\n units.length - 1,\n );\n\n const value = bytes / 1024 ** index;\n\n return `${value >= 10 || index === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[index]}`;\n};\n\nconst matchesMimeType = (\n fileType: string,\n acceptedTypes: readonly string[],\n): boolean => {\n const normalizedType = fileType.split(\";\")[0]!.trim().toLowerCase();\n\n if (!normalizedType) return false;\n\n return acceptedTypes.some((acceptedType) => {\n const accepted = acceptedType.trim().toLowerCase();\n\n if (!accepted) return false;\n\n if (accepted.endsWith(\"/*\")) {\n return normalizedType.startsWith(accepted.slice(0, -1));\n }\n\n return normalizedType === accepted;\n });\n};\n\nconst createRejection = (\n file: File,\n code: FileUploadRejectionCode,\n message: string,\n): FileUploadRejection => ({\n file,\n code,\n message,\n});\n\nconst validateFile = (\n file: File,\n options: Pick<FileValidationOptions, \"accept\" | \"maxFileSize\">,\n): FileUploadRejection | undefined => {\n const { accept = [], maxFileSize } = options;\n\n if (accept.length > 0 && !matchesMimeType(file.type, accept)) {\n return createRejection(file, \"file-type\", \"This file type is not allowed.\");\n }\n\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n return createRejection(\n file,\n \"file-too-large\",\n `File exceeds the maximum size of ${formatFileSize(maxFileSize)}.`,\n );\n }\n\n return undefined;\n};\n\nconst validateFiles = (\n incomingFiles: readonly File[],\n existingFiles: readonly File[],\n options: FileValidationOptions = {},\n): FileValidationResult => {\n const { multiple = false, maxFiles, maxTotalSize } = options;\n\n const accepted: File[] = [];\n const rejected: FileUploadRejection[] = [];\n\n const currentFiles = multiple ? [...existingFiles] : [];\n\n let totalSize = currentFiles.reduce((total, file) => total + file.size, 0);\n\n let fileCount = currentFiles.length;\n\n incomingFiles.forEach((file) => {\n const validationError = validateFile(file, options);\n\n if (validationError) {\n rejected.push(validationError);\n return;\n }\n\n if (!multiple && accepted.length > 0) {\n rejected.push(\n createRejection(\n file,\n \"too-many-files\",\n \"Only one file can be selected.\",\n ),\n );\n return;\n }\n\n if (multiple && maxFiles !== undefined && fileCount >= maxFiles) {\n rejected.push(\n createRejection(\n file,\n \"too-many-files\",\n `You can select a maximum of ${maxFiles} files.`,\n ),\n );\n return;\n }\n\n if (maxTotalSize !== undefined && totalSize + file.size > maxTotalSize) {\n rejected.push(\n createRejection(\n file,\n \"total-too-large\",\n `The combined file size exceeds ${formatFileSize(maxTotalSize)}.`,\n ),\n );\n return;\n }\n\n accepted.push(file);\n\n totalSize += file.size;\n fileCount++;\n });\n\n return { accepted, rejected };\n};\n\nexport {\n formatFileSize,\n matchesMimeType,\n createRejection,\n validateFile,\n validateFiles,\n};\n\nexport type { FileValidationOptions, FileValidationResult };\n"],"mappings":";AAkBA,MAAM,kBAAkB,UAA0B;CAChD,IAAI,UAAU,GAAG,OAAO;CAExB,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG,OAAO;CAEjD,MAAM,QAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;CAAI;CAE1C,MAAM,QAAQ,KAAK,IACjB,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,GAC3C,MAAM,SAAS,CACjB;CAEA,MAAM,QAAQ,QAAQ,QAAQ;CAE9B,OAAO,GAAG,SAAS,MAAM,UAAU,IAAI,MAAM,QAAQ,CAAC,IAAI,MAAM,QAAQ,CAAC,EAAE,GAAG,MAAM;AACtF;AAEA,MAAM,mBACJ,UACA,kBACY;CACZ,MAAM,iBAAiB,SAAS,MAAM,GAAG,CAAC,CAAC,EAAE,CAAE,KAAK,CAAC,CAAC,YAAY;CAElE,IAAI,CAAC,gBAAgB,OAAO;CAE5B,OAAO,cAAc,MAAM,iBAAiB;EAC1C,MAAM,WAAW,aAAa,KAAK,CAAC,CAAC,YAAY;EAEjD,IAAI,CAAC,UAAU,OAAO;EAEtB,IAAI,SAAS,SAAS,IAAI,GACxB,OAAO,eAAe,WAAW,SAAS,MAAM,GAAG,EAAE,CAAC;EAGxD,OAAO,mBAAmB;CAC5B,CAAC;AACH;AAEA,MAAM,mBACJ,MACA,MACA,aACyB;CACzB;CACA;CACA;AACF;AAEA,MAAM,gBACJ,MACA,YACoC;CACpC,MAAM,EAAE,SAAS,CAAC,GAAG,gBAAgB;CAErC,IAAI,OAAO,SAAS,KAAK,CAAC,gBAAgB,KAAK,MAAM,MAAM,GACzD,OAAO,gBAAgB,MAAM,aAAa,gCAAgC;CAG5E,IAAI,gBAAgB,KAAA,KAAa,KAAK,OAAO,aAC3C,OAAO,gBACL,MACA,kBACA,oCAAoC,eAAe,WAAW,EAAE,EAClE;AAIJ;AAEA,MAAM,iBACJ,eACA,eACA,UAAiC,CAAC,MACT;CACzB,MAAM,EAAE,WAAW,OAAO,UAAU,iBAAiB;CAErD,MAAM,WAAmB,CAAC;CAC1B,MAAM,WAAkC,CAAC;CAEzC,MAAM,eAAe,WAAW,CAAC,GAAG,aAAa,IAAI,CAAC;CAEtD,IAAI,YAAY,aAAa,QAAQ,OAAO,SAAS,QAAQ,KAAK,MAAM,CAAC;CAEzE,IAAI,YAAY,aAAa;CAE7B,cAAc,SAAS,SAAS;EAC9B,MAAM,kBAAkB,aAAa,MAAM,OAAO;EAElD,IAAI,iBAAiB;GACnB,SAAS,KAAK,eAAe;GAC7B;EACF;EAEA,IAAI,CAAC,YAAY,SAAS,SAAS,GAAG;GACpC,SAAS,KACP,gBACE,MACA,kBACA,gCACF,CACF;GACA;EACF;EAEA,IAAI,YAAY,aAAa,KAAA,KAAa,aAAa,UAAU;GAC/D,SAAS,KACP,gBACE,MACA,kBACA,+BAA+B,SAAS,QAC1C,CACF;GACA;EACF;EAEA,IAAI,iBAAiB,KAAA,KAAa,YAAY,KAAK,OAAO,cAAc;GACtE,SAAS,KACP,gBACE,MACA,mBACA,kCAAkC,eAAe,YAAY,EAAE,EACjE,CACF;GACA;EACF;EAEA,SAAS,KAAK,IAAI;EAElB,aAAa,KAAK;EAClB;CACF,CAAC;CAED,OAAO;EAAE;EAAU;CAAS;AAC9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.utils.js","names":[],"sources":["../../../../src/components/forms/file-upload/file-upload.utils.ts"],"sourcesContent":["import type {\n FileUploadRejection,\n FileUploadRejectionCode,\n} from \"./file-upload.types\";\n\ntype FileValidationOptions = {\n accept?: readonly string[];\n maxFileSize?: number;\n maxTotalSize?: number;\n maxFiles?: number;\n multiple?: boolean;\n};\n\ntype FileValidationResult = {\n accepted: File[];\n rejected: FileUploadRejection[];\n};\n\nconst formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n\n if (!Number.isFinite(bytes) || bytes < 0) return \"0 B\";\n\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\n const index = Math.min(\n Math.floor(Math.log(bytes) / Math.log(1024)),\n units.length - 1,\n );\n\n const value = bytes / 1024 ** index;\n\n return `${value >= 10 || index === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[index]}`;\n};\n\nconst matchesMimeType = (\n fileType: string,\n acceptedTypes: readonly string[],\n): boolean => {\n const normalizedType = fileType.split(\";\")[0]
|
|
1
|
+
{"version":3,"file":"file-upload.utils.js","names":[],"sources":["../../../../src/components/forms/file-upload/file-upload.utils.ts"],"sourcesContent":["import type {\n FileUploadRejection,\n FileUploadRejectionCode,\n} from \"./file-upload.types\";\n\ntype FileValidationOptions = {\n accept?: readonly string[];\n maxFileSize?: number;\n maxTotalSize?: number;\n maxFiles?: number;\n multiple?: boolean;\n};\n\ntype FileValidationResult = {\n accepted: File[];\n rejected: FileUploadRejection[];\n};\n\nconst formatFileSize = (bytes: number): string => {\n if (bytes === 0) return \"0 B\";\n\n if (!Number.isFinite(bytes) || bytes < 0) return \"0 B\";\n\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\n const index = Math.min(\n Math.floor(Math.log(bytes) / Math.log(1024)),\n units.length - 1,\n );\n\n const value = bytes / 1024 ** index;\n\n return `${value >= 10 || index === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[index]}`;\n};\n\nconst matchesMimeType = (\n fileType: string,\n acceptedTypes: readonly string[],\n): boolean => {\n const normalizedType = fileType.split(\";\")[0]!.trim().toLowerCase();\n\n if (!normalizedType) return false;\n\n return acceptedTypes.some((acceptedType) => {\n const accepted = acceptedType.trim().toLowerCase();\n\n if (!accepted) return false;\n\n if (accepted.endsWith(\"/*\")) {\n return normalizedType.startsWith(accepted.slice(0, -1));\n }\n\n return normalizedType === accepted;\n });\n};\n\nconst createRejection = (\n file: File,\n code: FileUploadRejectionCode,\n message: string,\n): FileUploadRejection => ({\n file,\n code,\n message,\n});\n\nconst validateFile = (\n file: File,\n options: Pick<FileValidationOptions, \"accept\" | \"maxFileSize\">,\n): FileUploadRejection | undefined => {\n const { accept = [], maxFileSize } = options;\n\n if (accept.length > 0 && !matchesMimeType(file.type, accept)) {\n return createRejection(file, \"file-type\", \"This file type is not allowed.\");\n }\n\n if (maxFileSize !== undefined && file.size > maxFileSize) {\n return createRejection(\n file,\n \"file-too-large\",\n `File exceeds the maximum size of ${formatFileSize(maxFileSize)}.`,\n );\n }\n\n return undefined;\n};\n\nconst validateFiles = (\n incomingFiles: readonly File[],\n existingFiles: readonly File[],\n options: FileValidationOptions = {},\n): FileValidationResult => {\n const { multiple = false, maxFiles, maxTotalSize } = options;\n\n const accepted: File[] = [];\n const rejected: FileUploadRejection[] = [];\n\n const currentFiles = multiple ? [...existingFiles] : [];\n\n let totalSize = currentFiles.reduce((total, file) => total + file.size, 0);\n\n let fileCount = currentFiles.length;\n\n incomingFiles.forEach((file) => {\n const validationError = validateFile(file, options);\n\n if (validationError) {\n rejected.push(validationError);\n return;\n }\n\n if (!multiple && accepted.length > 0) {\n rejected.push(\n createRejection(\n file,\n \"too-many-files\",\n \"Only one file can be selected.\",\n ),\n );\n return;\n }\n\n if (multiple && maxFiles !== undefined && fileCount >= maxFiles) {\n rejected.push(\n createRejection(\n file,\n \"too-many-files\",\n `You can select a maximum of ${maxFiles} files.`,\n ),\n );\n return;\n }\n\n if (maxTotalSize !== undefined && totalSize + file.size > maxTotalSize) {\n rejected.push(\n createRejection(\n file,\n \"total-too-large\",\n `The combined file size exceeds ${formatFileSize(maxTotalSize)}.`,\n ),\n );\n return;\n }\n\n accepted.push(file);\n\n totalSize += file.size;\n fileCount++;\n });\n\n return { accepted, rejected };\n};\n\nexport {\n formatFileSize,\n matchesMimeType,\n createRejection,\n validateFile,\n validateFiles,\n};\n\nexport type { FileValidationOptions, FileValidationResult };\n"],"mappings":";AAkBA,MAAM,kBAAkB,UAA0B;CAChD,IAAI,UAAU,GAAG,OAAO;CAExB,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAAG,OAAO;CAEjD,MAAM,QAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;CAAI;CAE1C,MAAM,QAAQ,KAAK,IACjB,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,GAC3C,MAAM,SAAS,CACjB;CAEA,MAAM,QAAQ,QAAQ,QAAQ;CAE9B,OAAO,GAAG,SAAS,MAAM,UAAU,IAAI,MAAM,QAAQ,CAAC,IAAI,MAAM,QAAQ,CAAC,EAAE,GAAG,MAAM;AACtF;AAEA,MAAM,mBACJ,UACA,kBACY;CACZ,MAAM,iBAAiB,SAAS,MAAM,GAAG,CAAC,CAAC,EAAE,CAAE,KAAK,CAAC,CAAC,YAAY;CAElE,IAAI,CAAC,gBAAgB,OAAO;CAE5B,OAAO,cAAc,MAAM,iBAAiB;EAC1C,MAAM,WAAW,aAAa,KAAK,CAAC,CAAC,YAAY;EAEjD,IAAI,CAAC,UAAU,OAAO;EAEtB,IAAI,SAAS,SAAS,IAAI,GACxB,OAAO,eAAe,WAAW,SAAS,MAAM,GAAG,EAAE,CAAC;EAGxD,OAAO,mBAAmB;CAC5B,CAAC;AACH;AAEA,MAAM,mBACJ,MACA,MACA,aACyB;CACzB;CACA;CACA;AACF;AAEA,MAAM,gBACJ,MACA,YACoC;CACpC,MAAM,EAAE,SAAS,CAAC,GAAG,gBAAgB;CAErC,IAAI,OAAO,SAAS,KAAK,CAAC,gBAAgB,KAAK,MAAM,MAAM,GACzD,OAAO,gBAAgB,MAAM,aAAa,gCAAgC;CAG5E,IAAI,gBAAgB,KAAA,KAAa,KAAK,OAAO,aAC3C,OAAO,gBACL,MACA,kBACA,oCAAoC,eAAe,WAAW,EAAE,EAClE;AAIJ;AAEA,MAAM,iBACJ,eACA,eACA,UAAiC,CAAC,MACT;CACzB,MAAM,EAAE,WAAW,OAAO,UAAU,iBAAiB;CAErD,MAAM,WAAmB,CAAC;CAC1B,MAAM,WAAkC,CAAC;CAEzC,MAAM,eAAe,WAAW,CAAC,GAAG,aAAa,IAAI,CAAC;CAEtD,IAAI,YAAY,aAAa,QAAQ,OAAO,SAAS,QAAQ,KAAK,MAAM,CAAC;CAEzE,IAAI,YAAY,aAAa;CAE7B,cAAc,SAAS,SAAS;EAC9B,MAAM,kBAAkB,aAAa,MAAM,OAAO;EAElD,IAAI,iBAAiB;GACnB,SAAS,KAAK,eAAe;GAC7B;EACF;EAEA,IAAI,CAAC,YAAY,SAAS,SAAS,GAAG;GACpC,SAAS,KACP,gBACE,MACA,kBACA,gCACF,CACF;GACA;EACF;EAEA,IAAI,YAAY,aAAa,KAAA,KAAa,aAAa,UAAU;GAC/D,SAAS,KACP,gBACE,MACA,kBACA,+BAA+B,SAAS,QAC1C,CACF;GACA;EACF;EAEA,IAAI,iBAAiB,KAAA,KAAa,YAAY,KAAK,OAAO,cAAc;GACtE,SAAS,KACP,gBACE,MACA,mBACA,kCAAkC,eAAe,YAAY,EAAE,EACjE,CACF;GACA;EACF;EAEA,SAAS,KAAK,IAAI;EAElB,aAAa,KAAK;EAClB;CACF,CAAC;CAED,OAAO;EAAE;EAAU;CAAS;AAC9B"}
|
|
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { Icon } from "@puzzle-ui/icons";
|
|
7
7
|
// src/components/forms/input/number-input.tsx
|
|
8
|
-
const clamp = (value, min, max) => Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));
|
|
8
|
+
const clamp$1 = (value, min, max) => Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));
|
|
9
9
|
const getPrecision = (value) => {
|
|
10
10
|
const valueString = String(value);
|
|
11
11
|
if (valueString.includes("e-")) return Number(valueString.split("e-")[1]) || 0;
|
|
@@ -18,8 +18,8 @@ const NumberInput = ({ value, initialValue = 0, onChange, min, max, step = 1, la
|
|
|
18
18
|
const safeStep = Number.isFinite(step) && step > 0 ? step : 1;
|
|
19
19
|
const safeLargeStep = largeStep !== void 0 && Number.isFinite(largeStep) && largeStep > 0 ? largeStep : safeStep * 10;
|
|
20
20
|
const allowsNegative = min === void 0 || min < 0;
|
|
21
|
-
const [internalValue, setInternalValue] = useState(() => clamp(Number.isFinite(initialValue) ? initialValue : 0, min, max));
|
|
22
|
-
const currentValue = clamp(isControlled ? value : internalValue, min, max);
|
|
21
|
+
const [internalValue, setInternalValue] = useState(() => clamp$1(Number.isFinite(initialValue) ? initialValue : 0, min, max));
|
|
22
|
+
const currentValue = clamp$1(isControlled ? value : internalValue, min, max);
|
|
23
23
|
const [draft, setDraft] = useState(() => String(Number(currentValue.toFixed(digits))));
|
|
24
24
|
const currentValueRef = useRef(currentValue);
|
|
25
25
|
const focusedRef = useRef(false);
|
|
@@ -32,7 +32,7 @@ const NumberInput = ({ value, initialValue = 0, onChange, min, max, step = 1, la
|
|
|
32
32
|
if (!focusedRef.current) setDraft(String(Number(currentValue.toFixed(digits))));
|
|
33
33
|
}, [currentValue, digits]);
|
|
34
34
|
const commit = useCallback((nextValue) => {
|
|
35
|
-
const rounded = Math.round(clamp(nextValue, min, max) * factor) / factor;
|
|
35
|
+
const rounded = Math.round(clamp$1(nextValue, min, max) * factor) / factor;
|
|
36
36
|
if (!Number.isFinite(rounded) || rounded === currentValueRef.current) return;
|
|
37
37
|
currentValueRef.current = rounded;
|
|
38
38
|
if (!isControlled) setInternalValue(rounded);
|
|
@@ -119,7 +119,7 @@ const NumberInput = ({ value, initialValue = 0, onChange, min, max, step = 1, la
|
|
|
119
119
|
const handleBlur = (event) => {
|
|
120
120
|
focusedRef.current = false;
|
|
121
121
|
const parsed = Number(draft.replace(",", "."));
|
|
122
|
-
const nextValue = draft.trim() !== "" && Number.isFinite(parsed) ? clamp(Math.round(parsed * factor) / factor, min, max) : currentValueRef.current;
|
|
122
|
+
const nextValue = draft.trim() !== "" && Number.isFinite(parsed) ? clamp$1(Math.round(parsed * factor) / factor, min, max) : currentValueRef.current;
|
|
123
123
|
commit(nextValue);
|
|
124
124
|
setDraft(String(Number(nextValue.toFixed(digits))));
|
|
125
125
|
onBlur?.(event);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input.js","names":[],"sources":["../../../../src/components/forms/input/number-input.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type PointerEvent as ReactPointerEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n type ChangeEvent,\n type FocusEvent,\n} from \"react\";\n\nimport { cn } from \"@puzzle-ui/core\";\nimport { Icon } from \"@puzzle-ui/icons\";\n\nimport \"./input.css\";\n\ntype NumberInputProps = Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"type\" | \"value\" | \"defaultValue\" | \"onChange\" | \"step\" | \"min\" | \"max\"\n> & {\n value?: number;\n initialValue?: number;\n\n onChange?: (value: number) => void;\n\n min?: number;\n max?: number;\n step?: number;\n\n /** Amount applied by PageUp and PageDown. Defaults to ten times `step`. */\n largeStep?: number;\n\n fractionDigits?: number;\n\n longPressDelay?: number;\n repeatInterval?: number;\n\n /** Accessible label of the decrement button. */\n decrementLabel?: string;\n\n /** Accessible label of the increment button. */\n incrementLabel?: string;\n};\n\ntype Direction = -1 | 1;\n\nconst clamp = (value: number, min?: number, max?: number) =>\n Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));\n\nconst getPrecision = (value: number) => {\n const valueString = String(value);\n\n if (valueString.includes(\"e-\")) {\n return Number(valueString.split(\"e-\")[1]) || 0;\n }\n\n return valueString.split(\".\")[1]?.length ?? 0;\n};\n\nconst NumberInput = ({\n value,\n initialValue = 0,\n onChange,\n\n min,\n max,\n step = 1,\n largeStep,\n\n fractionDigits = getPrecision(step),\n\n longPressDelay = 450,\n repeatInterval = 120,\n\n decrementLabel = \"Decrease value\",\n incrementLabel = \"Increase value\",\n\n disabled,\n readOnly,\n className,\n\n onBlur,\n onFocus,\n onKeyDown,\n\n ...inputProps\n}: NumberInputProps) => {\n const isControlled = value !== undefined;\n\n const digits = Math.min(12, Math.max(0, Math.trunc(fractionDigits)));\n\n const factor = 10 ** digits;\n\n const safeStep = Number.isFinite(step) && step > 0 ? step : 1;\n\n const safeLargeStep =\n largeStep !== undefined && Number.isFinite(largeStep) && largeStep > 0\n ? largeStep\n : safeStep * 10;\n\n const allowsNegative = min === undefined || min < 0;\n\n const [internalValue, setInternalValue] = useState(() =>\n clamp(Number.isFinite(initialValue) ? initialValue : 0, min, max),\n );\n\n const currentValue = clamp(isControlled ? value : internalValue, min, max);\n\n const [draft, setDraft] = useState(() =>\n String(Number(currentValue.toFixed(digits))),\n );\n\n const currentValueRef = useRef(currentValue);\n const focusedRef = useRef(false);\n\n const holdTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const repeatTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const holdStartedAtRef = useRef(0);\n const holdDirectionRef = useRef<Direction>(1);\n\n currentValueRef.current = currentValue;\n\n useEffect(() => {\n if (!focusedRef.current) {\n setDraft(String(Number(currentValue.toFixed(digits))));\n }\n }, [currentValue, digits]);\n\n const commit = useCallback(\n (nextValue: number) => {\n const rounded = Math.round(clamp(nextValue, min, max) * factor) / factor;\n\n if (!Number.isFinite(rounded) || rounded === currentValueRef.current) {\n return;\n }\n\n currentValueRef.current = rounded;\n\n if (!isControlled) {\n setInternalValue(rounded);\n }\n\n setDraft(String(rounded));\n\n onChange?.(rounded);\n },\n [factor, isControlled, max, min, onChange],\n );\n\n const changeBy = useCallback(\n (direction: Direction, amount = safeStep) => {\n const next =\n Math.round((currentValueRef.current + direction * amount) * factor) /\n factor;\n\n commit(next);\n },\n [commit, factor, safeStep],\n );\n\n const stopHold = useCallback(() => {\n if (holdTimerRef.current) {\n clearTimeout(holdTimerRef.current);\n }\n\n if (repeatTimerRef.current) {\n clearTimeout(repeatTimerRef.current);\n }\n\n holdTimerRef.current = null;\n repeatTimerRef.current = null;\n }, []);\n\n const scheduleRepeat = useCallback(() => {\n const elapsed = Date.now() - holdStartedAtRef.current;\n\n const interval = Math.max(\n 45,\n repeatInterval - Math.floor(elapsed / 1800) * 20,\n );\n\n repeatTimerRef.current = setTimeout(() => {\n changeBy(holdDirectionRef.current);\n scheduleRepeat();\n }, interval);\n }, [changeBy, repeatInterval]);\n\n const startHold =\n (direction: Direction) => (event: ReactPointerEvent<HTMLButtonElement>) => {\n if (disabled || readOnly || event.button !== 0) {\n return;\n }\n\n event.preventDefault();\n\n stopHold();\n\n holdDirectionRef.current = direction;\n holdStartedAtRef.current = Date.now();\n\n changeBy(direction);\n\n holdTimerRef.current = setTimeout(scheduleRepeat, longPressDelay);\n };\n\n const handleStepperKeyDown =\n (direction: Direction) =>\n (event: ReactKeyboardEvent<HTMLButtonElement>) => {\n if (event.key !== \" \" && event.key !== \"Enter\") {\n return;\n }\n\n event.preventDefault();\n changeBy(direction);\n };\n\n const handleInputKeyDown = (event: ReactKeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n\n if (event.defaultPrevented || disabled || readOnly) {\n return;\n }\n\n switch (event.key) {\n case \"ArrowUp\":\n changeBy(1);\n break;\n case \"ArrowDown\":\n changeBy(-1);\n break;\n case \"PageUp\":\n changeBy(1, safeLargeStep);\n break;\n case \"PageDown\":\n changeBy(-1, safeLargeStep);\n break;\n case \"Home\":\n if (min === undefined) return;\n commit(min);\n break;\n case \"End\":\n if (max === undefined) return;\n commit(max);\n break;\n default:\n return;\n }\n\n event.preventDefault();\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const nextDraft = event.target.value;\n\n setDraft(nextDraft);\n\n if (\n nextDraft.trim() === \"\" ||\n nextDraft === \"-\" ||\n nextDraft === \".\" ||\n nextDraft === \"-.\"\n ) {\n return;\n }\n\n const parsed = Number(nextDraft.replace(\",\", \".\"));\n\n if (Number.isFinite(parsed)) {\n commit(parsed);\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n focusedRef.current = false;\n\n const parsed = Number(draft.replace(\",\", \".\"));\n\n const nextValue =\n draft.trim() !== \"\" && Number.isFinite(parsed)\n ? clamp(Math.round(parsed * factor) / factor, min, max)\n : currentValueRef.current;\n\n commit(nextValue);\n\n setDraft(String(Number(nextValue.toFixed(digits))));\n\n onBlur?.(event);\n };\n\n useEffect(() => stopHold, [stopHold]);\n\n const atMinimum = min !== undefined && currentValue <= min;\n\n const atMaximum = max !== undefined && currentValue >= max;\n\n const trimmedDraft = draft.trim();\n const draftIsIncomplete =\n trimmedDraft === \"\" ||\n trimmedDraft === \"-\" ||\n trimmedDraft === \".\" ||\n trimmedDraft === \"-.\";\n const draftValue = Number(trimmedDraft.replace(\",\", \".\"));\n\n const draftIsInvalid =\n !draftIsIncomplete &&\n (!Number.isFinite(draftValue) ||\n (min !== undefined && draftValue < min) ||\n (max !== undefined && draftValue > max));\n\n const stepperDisabled = disabled || readOnly;\n\n return (\n <div\n className={cn(\"puzzle-input\", \"puzzle-input--number\", className)}\n data-disabled={disabled || undefined}\n >\n <button\n type=\"button\"\n className=\"puzzle-input__stepper\"\n aria-label={decrementLabel}\n tabIndex={-1}\n disabled={stepperDisabled || atMinimum}\n onPointerDown={startHold(-1)}\n onPointerUp={stopHold}\n onPointerLeave={stopHold}\n onPointerCancel={stopHold}\n onKeyDown={handleStepperKeyDown(-1)}\n >\n <Icon name=\"lucide:minus\" />\n </button>\n\n <input\n {...inputProps}\n type=\"text\"\n role=\"spinbutton\"\n aria-valuenow={currentValue}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-invalid={draftIsInvalid || inputProps[\"aria-invalid\"]}\n inputMode={allowsNegative ? \"text\" : digits > 0 ? \"decimal\" : \"numeric\"}\n pattern={`${allowsNegative ? \"-?\" : \"\"}[0-9]*${digits > 0 ? \"[.,]?[0-9]*\" : \"\"}`}\n disabled={disabled}\n readOnly={readOnly}\n value={draft}\n className=\"puzzle-input__control\"\n onFocus={(event) => {\n focusedRef.current = true;\n onFocus?.(event);\n }}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n onBlur={handleBlur}\n />\n\n <button\n type=\"button\"\n className=\"puzzle-input__stepper\"\n aria-label={incrementLabel}\n tabIndex={-1}\n disabled={stepperDisabled || atMaximum}\n onPointerDown={startHold(1)}\n onPointerUp={stopHold}\n onPointerLeave={stopHold}\n onPointerCancel={stopHold}\n onKeyDown={handleStepperKeyDown(1)}\n >\n <Icon name=\"lucide:plus\" />\n </button>\n </div>\n );\n};\n\nexport { NumberInput, type NumberInputProps };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"number-input.js","names":["clamp"],"sources":["../../../../src/components/forms/input/number-input.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type PointerEvent as ReactPointerEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n type ChangeEvent,\n type FocusEvent,\n} from \"react\";\n\nimport { cn } from \"@puzzle-ui/core\";\nimport { Icon } from \"@puzzle-ui/icons\";\n\nimport \"./input.css\";\n\ntype NumberInputProps = Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"type\" | \"value\" | \"defaultValue\" | \"onChange\" | \"step\" | \"min\" | \"max\"\n> & {\n value?: number;\n initialValue?: number;\n\n onChange?: (value: number) => void;\n\n min?: number;\n max?: number;\n step?: number;\n\n /** Amount applied by PageUp and PageDown. Defaults to ten times `step`. */\n largeStep?: number;\n\n fractionDigits?: number;\n\n longPressDelay?: number;\n repeatInterval?: number;\n\n /** Accessible label of the decrement button. */\n decrementLabel?: string;\n\n /** Accessible label of the increment button. */\n incrementLabel?: string;\n};\n\ntype Direction = -1 | 1;\n\nconst clamp = (value: number, min?: number, max?: number) =>\n Math.min(max ?? Infinity, Math.max(min ?? -Infinity, value));\n\nconst getPrecision = (value: number) => {\n const valueString = String(value);\n\n if (valueString.includes(\"e-\")) {\n return Number(valueString.split(\"e-\")[1]) || 0;\n }\n\n return valueString.split(\".\")[1]?.length ?? 0;\n};\n\nconst NumberInput = ({\n value,\n initialValue = 0,\n onChange,\n\n min,\n max,\n step = 1,\n largeStep,\n\n fractionDigits = getPrecision(step),\n\n longPressDelay = 450,\n repeatInterval = 120,\n\n decrementLabel = \"Decrease value\",\n incrementLabel = \"Increase value\",\n\n disabled,\n readOnly,\n className,\n\n onBlur,\n onFocus,\n onKeyDown,\n\n ...inputProps\n}: NumberInputProps) => {\n const isControlled = value !== undefined;\n\n const digits = Math.min(12, Math.max(0, Math.trunc(fractionDigits)));\n\n const factor = 10 ** digits;\n\n const safeStep = Number.isFinite(step) && step > 0 ? step : 1;\n\n const safeLargeStep =\n largeStep !== undefined && Number.isFinite(largeStep) && largeStep > 0\n ? largeStep\n : safeStep * 10;\n\n const allowsNegative = min === undefined || min < 0;\n\n const [internalValue, setInternalValue] = useState(() =>\n clamp(Number.isFinite(initialValue) ? initialValue : 0, min, max),\n );\n\n const currentValue = clamp(isControlled ? value : internalValue, min, max);\n\n const [draft, setDraft] = useState(() =>\n String(Number(currentValue.toFixed(digits))),\n );\n\n const currentValueRef = useRef(currentValue);\n const focusedRef = useRef(false);\n\n const holdTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const repeatTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const holdStartedAtRef = useRef(0);\n const holdDirectionRef = useRef<Direction>(1);\n\n currentValueRef.current = currentValue;\n\n useEffect(() => {\n if (!focusedRef.current) {\n setDraft(String(Number(currentValue.toFixed(digits))));\n }\n }, [currentValue, digits]);\n\n const commit = useCallback(\n (nextValue: number) => {\n const rounded = Math.round(clamp(nextValue, min, max) * factor) / factor;\n\n if (!Number.isFinite(rounded) || rounded === currentValueRef.current) {\n return;\n }\n\n currentValueRef.current = rounded;\n\n if (!isControlled) {\n setInternalValue(rounded);\n }\n\n setDraft(String(rounded));\n\n onChange?.(rounded);\n },\n [factor, isControlled, max, min, onChange],\n );\n\n const changeBy = useCallback(\n (direction: Direction, amount = safeStep) => {\n const next =\n Math.round((currentValueRef.current + direction * amount) * factor) /\n factor;\n\n commit(next);\n },\n [commit, factor, safeStep],\n );\n\n const stopHold = useCallback(() => {\n if (holdTimerRef.current) {\n clearTimeout(holdTimerRef.current);\n }\n\n if (repeatTimerRef.current) {\n clearTimeout(repeatTimerRef.current);\n }\n\n holdTimerRef.current = null;\n repeatTimerRef.current = null;\n }, []);\n\n const scheduleRepeat = useCallback(() => {\n const elapsed = Date.now() - holdStartedAtRef.current;\n\n const interval = Math.max(\n 45,\n repeatInterval - Math.floor(elapsed / 1800) * 20,\n );\n\n repeatTimerRef.current = setTimeout(() => {\n changeBy(holdDirectionRef.current);\n scheduleRepeat();\n }, interval);\n }, [changeBy, repeatInterval]);\n\n const startHold =\n (direction: Direction) => (event: ReactPointerEvent<HTMLButtonElement>) => {\n if (disabled || readOnly || event.button !== 0) {\n return;\n }\n\n event.preventDefault();\n\n stopHold();\n\n holdDirectionRef.current = direction;\n holdStartedAtRef.current = Date.now();\n\n changeBy(direction);\n\n holdTimerRef.current = setTimeout(scheduleRepeat, longPressDelay);\n };\n\n const handleStepperKeyDown =\n (direction: Direction) =>\n (event: ReactKeyboardEvent<HTMLButtonElement>) => {\n if (event.key !== \" \" && event.key !== \"Enter\") {\n return;\n }\n\n event.preventDefault();\n changeBy(direction);\n };\n\n const handleInputKeyDown = (event: ReactKeyboardEvent<HTMLInputElement>) => {\n onKeyDown?.(event);\n\n if (event.defaultPrevented || disabled || readOnly) {\n return;\n }\n\n switch (event.key) {\n case \"ArrowUp\":\n changeBy(1);\n break;\n case \"ArrowDown\":\n changeBy(-1);\n break;\n case \"PageUp\":\n changeBy(1, safeLargeStep);\n break;\n case \"PageDown\":\n changeBy(-1, safeLargeStep);\n break;\n case \"Home\":\n if (min === undefined) return;\n commit(min);\n break;\n case \"End\":\n if (max === undefined) return;\n commit(max);\n break;\n default:\n return;\n }\n\n event.preventDefault();\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n const nextDraft = event.target.value;\n\n setDraft(nextDraft);\n\n if (\n nextDraft.trim() === \"\" ||\n nextDraft === \"-\" ||\n nextDraft === \".\" ||\n nextDraft === \"-.\"\n ) {\n return;\n }\n\n const parsed = Number(nextDraft.replace(\",\", \".\"));\n\n if (Number.isFinite(parsed)) {\n commit(parsed);\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n focusedRef.current = false;\n\n const parsed = Number(draft.replace(\",\", \".\"));\n\n const nextValue =\n draft.trim() !== \"\" && Number.isFinite(parsed)\n ? clamp(Math.round(parsed * factor) / factor, min, max)\n : currentValueRef.current;\n\n commit(nextValue);\n\n setDraft(String(Number(nextValue.toFixed(digits))));\n\n onBlur?.(event);\n };\n\n useEffect(() => stopHold, [stopHold]);\n\n const atMinimum = min !== undefined && currentValue <= min;\n\n const atMaximum = max !== undefined && currentValue >= max;\n\n const trimmedDraft = draft.trim();\n const draftIsIncomplete =\n trimmedDraft === \"\" ||\n trimmedDraft === \"-\" ||\n trimmedDraft === \".\" ||\n trimmedDraft === \"-.\";\n const draftValue = Number(trimmedDraft.replace(\",\", \".\"));\n\n const draftIsInvalid =\n !draftIsIncomplete &&\n (!Number.isFinite(draftValue) ||\n (min !== undefined && draftValue < min) ||\n (max !== undefined && draftValue > max));\n\n const stepperDisabled = disabled || readOnly;\n\n return (\n <div\n className={cn(\"puzzle-input\", \"puzzle-input--number\", className)}\n data-disabled={disabled || undefined}\n >\n <button\n type=\"button\"\n className=\"puzzle-input__stepper\"\n aria-label={decrementLabel}\n tabIndex={-1}\n disabled={stepperDisabled || atMinimum}\n onPointerDown={startHold(-1)}\n onPointerUp={stopHold}\n onPointerLeave={stopHold}\n onPointerCancel={stopHold}\n onKeyDown={handleStepperKeyDown(-1)}\n >\n <Icon name=\"lucide:minus\" />\n </button>\n\n <input\n {...inputProps}\n type=\"text\"\n role=\"spinbutton\"\n aria-valuenow={currentValue}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-invalid={draftIsInvalid || inputProps[\"aria-invalid\"]}\n inputMode={allowsNegative ? \"text\" : digits > 0 ? \"decimal\" : \"numeric\"}\n pattern={`${allowsNegative ? \"-?\" : \"\"}[0-9]*${digits > 0 ? \"[.,]?[0-9]*\" : \"\"}`}\n disabled={disabled}\n readOnly={readOnly}\n value={draft}\n className=\"puzzle-input__control\"\n onFocus={(event) => {\n focusedRef.current = true;\n onFocus?.(event);\n }}\n onChange={handleInputChange}\n onKeyDown={handleInputKeyDown}\n onBlur={handleBlur}\n />\n\n <button\n type=\"button\"\n className=\"puzzle-input__stepper\"\n aria-label={incrementLabel}\n tabIndex={-1}\n disabled={stepperDisabled || atMaximum}\n onPointerDown={startHold(1)}\n onPointerUp={stopHold}\n onPointerLeave={stopHold}\n onPointerCancel={stopHold}\n onKeyDown={handleStepperKeyDown(1)}\n >\n <Icon name=\"lucide:plus\" />\n </button>\n </div>\n );\n};\n\nexport { NumberInput, type NumberInputProps };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const require_input_group_utils = require("./input-group.utils.cjs");
|
|
2
|
+
;/* empty css */
|
|
3
|
+
let _puzzle_ui_core = require("@puzzle-ui/core");
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
// src/components/forms/input-group/input-group.tsx
|
|
6
|
+
const InputGroupAddon = ({ align, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7
|
+
...props,
|
|
8
|
+
className: (0, _puzzle_ui_core.cn)("puzzle-input-group__addon", className),
|
|
9
|
+
"data-align": require_input_group_utils.resolveInputGroupAddonAlign(align)
|
|
10
|
+
});
|
|
11
|
+
const InputGroupRoot = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12
|
+
...props,
|
|
13
|
+
className: (0, _puzzle_ui_core.cn)("puzzle-input-group", className)
|
|
14
|
+
});
|
|
15
|
+
const InputGroup = Object.assign(InputGroupRoot, { Addon: InputGroupAddon });
|
|
16
|
+
exports.InputGroup = InputGroup;
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=input-group.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-group.cjs","names":["cn","resolveInputGroupAddonAlign"],"sources":["../../../../src/components/forms/input-group/input-group.tsx"],"sourcesContent":["import { cn } from \"@puzzle-ui/core\";\n\nimport { resolveInputGroupAddonAlign } from \"./input-group.utils\";\nimport type {\n InputGroupAddonProps,\n InputGroupProps,\n} from \"./input-group.types\";\n\nimport \"./input-group.css\";\n\nconst InputGroupAddon = ({\n align,\n className,\n ...props\n}: InputGroupAddonProps) => (\n <div\n {...props}\n className={cn(\"puzzle-input-group__addon\", className)}\n data-align={resolveInputGroupAddonAlign(align)}\n />\n);\n\nconst InputGroupRoot = ({ className, ...props }: InputGroupProps) => (\n <div {...props} className={cn(\"puzzle-input-group\", className)} />\n);\n\nconst InputGroup = Object.assign(InputGroupRoot, {\n Addon: InputGroupAddon,\n});\n\nexport { InputGroup };\n"],"mappings":";;;;;AAUA,MAAM,mBAAmB,EACvB,OACA,WACA,GAAG,YAEH,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;CACE,GAAI;CACJ,YAAA,GAAWA,gBAAAA,GAAAA,CAAG,6BAA6B,SAAS;CACpD,cAAYC,0BAAAA,4BAA4B,KAAK;AAC9C,CAAA;AAGH,MAAM,kBAAkB,EAAE,WAAW,GAAG,YACtC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;CAAK,GAAI;CAAO,YAAA,GAAWD,gBAAAA,GAAAA,CAAG,sBAAsB,SAAS;AAAI,CAAA;AAGnE,MAAM,aAAa,OAAO,OAAO,gBAAgB,EAC/C,OAAO,gBACT,CAAC"}
|