@k8o/arte-odyssey 8.0.3 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/buttons/icon-button/icon-button.mjs +5 -16
- package/dist/components/data-display/accordion/context.d.mts +1 -1
- package/dist/components/data-display/accordion/context.mjs +3 -12
- package/dist/components/data-display/code/code.mjs +1 -1
- package/dist/{helpers/color → components/data-display/code}/find-all-colors.d.mts +1 -1
- package/dist/{helpers/color → components/data-display/code}/find-all-colors.mjs +1 -1
- package/dist/components/feedback/progress/progress.mjs +1 -1
- package/dist/components/feedback/toast/context.d.mts +2 -2
- package/dist/components/feedback/toast/context.mjs +6 -7
- package/dist/components/form/autocomplete/autocomplete.mjs +14 -13
- package/dist/components/form/checkbox/checkbox.mjs +7 -4
- package/dist/components/form/checkbox-card/checkbox-card.mjs +8 -7
- package/dist/components/form/checkbox-group/index.d.mts +3 -3
- package/dist/components/form/file-field/file-field.mjs +4 -10
- package/dist/{helpers/number → components/form/number-field}/cast.d.mts +1 -1
- package/dist/{helpers/number → components/form/number-field}/cast.mjs +2 -2
- package/dist/components/form/number-field/number-field.mjs +20 -19
- package/dist/components/form/radio/radio.mjs +6 -4
- package/dist/components/form/radio-card/radio-card.mjs +7 -5
- package/dist/components/form/switch/switch.mjs +7 -4
- package/dist/components/icons/index.d.mts +3 -2
- package/dist/components/icons/index.mjs +3 -2
- package/dist/components/icons/logo.mjs +3 -3
- package/dist/components/icons/lucide.d.mts +2 -1
- package/dist/components/icons/lucide.mjs +6 -2
- package/dist/components/icons/qiita.mjs +4 -4
- package/dist/components/icons/twitter.mjs +1 -1
- package/dist/components/icons/vertical-writing.d.mts +7 -0
- package/dist/components/icons/vertical-writing.mjs +25 -0
- package/dist/components/index.d.mts +3 -2
- package/dist/components/index.mjs +3 -2
- package/dist/components/navigation/anchor/anchor.mjs +1 -2
- package/dist/components/navigation/tabs/tabs.mjs +4 -13
- package/dist/components/overlays/dialog/dialog.mjs +3 -7
- package/dist/components/overlays/dropdown-menu/hooks.d.mts +2 -3
- package/dist/components/overlays/dropdown-menu/hooks.mjs +4 -9
- package/dist/components/overlays/list-box/hooks.d.mts +0 -1
- package/dist/components/overlays/list-box/hooks.mjs +3 -8
- package/dist/components/overlays/popover/hooks.d.mts +1 -3
- package/dist/components/overlays/popover/hooks.mjs +3 -8
- package/dist/components/overlays/tooltip/tooltip.mjs +19 -6
- package/dist/helpers/chain.d.mts +5 -0
- package/dist/helpers/chain.mjs +29 -0
- package/dist/helpers/create-safe-context.d.mts +7 -0
- package/dist/helpers/create-safe-context.mjs +13 -0
- package/dist/helpers/index.d.mts +5 -8
- package/dist/helpers/index.mjs +5 -8
- package/dist/helpers/merge-props.d.mts +6 -0
- package/dist/helpers/merge-props.mjs +56 -0
- package/dist/hooks/click-away/index.mjs +1 -1
- package/dist/index.d.mts +7 -9
- package/dist/index.mjs +7 -9
- package/dist/internal/clamp.d.mts +4 -0
- package/dist/internal/clamp.mjs +15 -0
- package/dist/{helpers/number → internal}/to-precision.d.mts +1 -1
- package/dist/{helpers/number → internal}/to-precision.mjs +1 -1
- package/package.json +1 -1
- package/dist/helpers/is-internal-route.d.mts +0 -4
- package/dist/helpers/is-internal-route.mjs +0 -12
- package/dist/helpers/number/between.d.mts +0 -4
- package/dist/helpers/number/between.mjs +0 -15
- package/dist/helpers/number/commalize.d.mts +0 -4
- package/dist/helpers/number/commalize.mjs +0 -20
- package/dist/helpers/number/index.d.mts +0 -5
- package/dist/helpers/number/index.mjs +0 -5
- package/dist/helpers/uuid-v4.d.mts +0 -4
- package/dist/helpers/uuid-v4.mjs +0 -28
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { Tooltip } from "../../overlays/tooltip/tooltip.mjs";
|
|
4
|
+
import { chain } from "../../../helpers/chain.mjs";
|
|
4
5
|
import { mergeRefs } from "../../../helpers/merge-refs.mjs";
|
|
5
6
|
import { useTransition } from "react";
|
|
6
7
|
import { useFormStatus } from "react-dom";
|
|
@@ -66,23 +67,11 @@ const IconButton = ({ ref, size = "md", bg = "transparent", label, tooltipPlacem
|
|
|
66
67
|
"aria-label": label,
|
|
67
68
|
className,
|
|
68
69
|
disabled: isDisabled,
|
|
69
|
-
onBlur: (
|
|
70
|
-
triggerProps.onBlur(e);
|
|
71
|
-
onBlur?.(e);
|
|
72
|
-
},
|
|
70
|
+
onBlur: chain(triggerProps.onBlur, onBlur),
|
|
73
71
|
onClick: handleClick,
|
|
74
|
-
onFocus: (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
78
|
-
onMouseEnter: (e) => {
|
|
79
|
-
triggerProps.onMouseEnter(e);
|
|
80
|
-
onMouseEnter?.(e);
|
|
81
|
-
},
|
|
82
|
-
onMouseLeave: (e) => {
|
|
83
|
-
triggerProps.onMouseLeave(e);
|
|
84
|
-
onMouseLeave?.(e);
|
|
85
|
-
},
|
|
72
|
+
onFocus: chain(triggerProps.onFocus, onFocus),
|
|
73
|
+
onMouseEnter: chain(triggerProps.onMouseEnter, onMouseEnter),
|
|
74
|
+
onMouseLeave: chain(triggerProps.onMouseLeave, onMouseLeave),
|
|
86
75
|
ref: mergeRefs(ref, triggerProps.ref),
|
|
87
76
|
type: "button",
|
|
88
77
|
children
|
|
@@ -2,9 +2,9 @@ import { FC, PropsWithChildren } from "react";
|
|
|
2
2
|
|
|
3
3
|
//#region src/components/data-display/accordion/context.d.ts
|
|
4
4
|
type ToggleOpen = () => void;
|
|
5
|
-
declare const useOpen: () => boolean;
|
|
6
5
|
declare const useToggleOpen: () => ToggleOpen;
|
|
7
6
|
declare const useItemId: () => string;
|
|
7
|
+
declare const useOpen: () => boolean;
|
|
8
8
|
declare const AccordionItemProvider: FC<PropsWithChildren<{
|
|
9
9
|
defaultOpen?: boolean;
|
|
10
10
|
id: string;
|
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useDisclosure } from "../../../hooks/disclosure/index.mjs";
|
|
3
|
+
import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
|
|
3
4
|
import { createContext, use } from "react";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
5
6
|
//#region src/components/data-display/accordion/context.tsx
|
|
6
7
|
const OpenContext = createContext(false);
|
|
7
|
-
const ToggleOpenContext =
|
|
8
|
-
const ItemIdContext =
|
|
8
|
+
const [ToggleOpenContext, useToggleOpen] = createSafeContext("useToggleOpen must be used within AccordionProvider");
|
|
9
|
+
const [ItemIdContext, useItemId] = createSafeContext("useItemId must be used within AccordionProvider");
|
|
9
10
|
const useOpen = () => use(OpenContext);
|
|
10
|
-
const useToggleOpen = () => {
|
|
11
|
-
const toggleOpen = use(ToggleOpenContext);
|
|
12
|
-
if (!toggleOpen) throw new Error("useToggleOpen must be used within AccordionProvider");
|
|
13
|
-
return toggleOpen;
|
|
14
|
-
};
|
|
15
|
-
const useItemId = () => {
|
|
16
|
-
const id = use(ItemIdContext);
|
|
17
|
-
if (id === void 0 || id === "") throw new Error("useItemId must be used within AccordionProvider");
|
|
18
|
-
return id;
|
|
19
|
-
};
|
|
20
11
|
const AccordionItemProvider = ({ defaultOpen = false, id, children }) => {
|
|
21
12
|
const { isOpen, toggle } = useDisclosure(defaultOpen);
|
|
22
13
|
return /* @__PURE__ */ jsx(OpenContext, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../../helpers/cn.mjs";
|
|
2
|
-
import { findAllColors } from "
|
|
2
|
+
import { findAllColors } from "./find-all-colors.mjs";
|
|
3
3
|
import { Fragment } from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/data-display/code/code.tsx
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "../../../helpers/cn.mjs";
|
|
2
|
-
import { toPrecision } from "../../../
|
|
2
|
+
import { toPrecision } from "../../../internal/to-precision.mjs";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region src/components/feedback/progress/progress.tsx
|
|
5
5
|
const Progress = ({ progress, maxProgress, minProgress = 0, label, className, ...rest }) => /* @__PURE__ */ jsx("div", {
|
|
@@ -8,11 +8,11 @@ type ToastType = {
|
|
|
8
8
|
status: Status;
|
|
9
9
|
message: string;
|
|
10
10
|
};
|
|
11
|
-
declare const SetToastContext: _$react.Context<Dispatch<SetStateAction<ToastType[]>> |
|
|
11
|
+
declare const SetToastContext: _$react.Context<Dispatch<SetStateAction<ToastType[]>> | null>, useSetToast: () => Dispatch<SetStateAction<ToastType[]>>;
|
|
12
12
|
declare const useToast: () => {
|
|
13
13
|
onOpen: (status: Status, message: string) => void;
|
|
14
14
|
onClose: (id: string) => void;
|
|
15
15
|
onCloseAll: () => void;
|
|
16
16
|
};
|
|
17
17
|
//#endregion
|
|
18
|
-
export { SetToastContext, ToastType, useToast };
|
|
18
|
+
export { SetToastContext, ToastType, useSetToast, useToast };
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
|
|
3
|
+
import { useCallback } from "react";
|
|
4
4
|
//#region src/components/feedback/toast/context.ts
|
|
5
5
|
const MAX_TOAST_COUNT = 5;
|
|
6
|
-
const SetToastContext =
|
|
6
|
+
const [SetToastContext, useSetToast] = createSafeContext("useToast must be used within a ToastProvider");
|
|
7
7
|
const useToast = () => {
|
|
8
|
-
const setToasts =
|
|
9
|
-
if (!setToasts) throw new Error("useToast must be used within a ToastProvider");
|
|
8
|
+
const setToasts = useSetToast();
|
|
10
9
|
return {
|
|
11
10
|
onOpen: useCallback((status, message) => {
|
|
12
11
|
setToasts((prev) => {
|
|
13
12
|
return [...prev, {
|
|
14
|
-
id:
|
|
13
|
+
id: crypto.randomUUID(),
|
|
15
14
|
status,
|
|
16
15
|
message
|
|
17
16
|
}].slice(-MAX_TOAST_COUNT);
|
|
@@ -26,4 +25,4 @@ const useToast = () => {
|
|
|
26
25
|
};
|
|
27
26
|
};
|
|
28
27
|
//#endregion
|
|
29
|
-
export { SetToastContext, useToast };
|
|
28
|
+
export { SetToastContext, useSetToast, useToast };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
|
+
import { useDisclosure } from "../../../hooks/disclosure/index.mjs";
|
|
3
4
|
import { CloseIcon } from "../../icons/lucide.mjs";
|
|
4
5
|
import { IconButton } from "../../buttons/icon-button/icon-button.mjs";
|
|
5
6
|
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
@@ -15,7 +16,7 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
15
16
|
onChange
|
|
16
17
|
});
|
|
17
18
|
const ref = useRef(null);
|
|
18
|
-
const
|
|
19
|
+
const { isOpen, open, close } = useDisclosure();
|
|
19
20
|
const [text, setText] = useState("");
|
|
20
21
|
const [selectIndex, setSelectIndex] = useState();
|
|
21
22
|
const [deferredText, isPending] = useDeferredDebounce(text);
|
|
@@ -24,9 +25,9 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
24
25
|
const disabledResolved = disabled || formPending;
|
|
25
26
|
const reset = useCallback(() => {
|
|
26
27
|
setText("");
|
|
27
|
-
|
|
28
|
+
close();
|
|
28
29
|
setSelectIndex(void 0);
|
|
29
|
-
}, []);
|
|
30
|
+
}, [close]);
|
|
30
31
|
useEffect(() => {
|
|
31
32
|
const handleClick = (e) => {
|
|
32
33
|
if (e.target instanceof Node && ref.current?.contains(e.target) === true) return;
|
|
@@ -69,8 +70,8 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
69
70
|
}), /* @__PURE__ */ jsx("input", {
|
|
70
71
|
...rest,
|
|
71
72
|
"aria-autocomplete": "list",
|
|
72
|
-
"aria-controls":
|
|
73
|
-
"aria-expanded":
|
|
73
|
+
"aria-controls": isOpen ? `${id}_listbox` : void 0,
|
|
74
|
+
"aria-expanded": isOpen,
|
|
74
75
|
"aria-invalid": invalid,
|
|
75
76
|
"aria-required": required,
|
|
76
77
|
autoComplete: "off",
|
|
@@ -79,19 +80,19 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
79
80
|
id,
|
|
80
81
|
onBlur: (e) => {
|
|
81
82
|
if (e.relatedTarget?.id.startsWith(`${id}_option_`) === true) return;
|
|
82
|
-
|
|
83
|
+
close();
|
|
83
84
|
},
|
|
84
85
|
onChange: (e) => {
|
|
85
|
-
|
|
86
|
+
open();
|
|
86
87
|
setText(e.target.value);
|
|
87
88
|
setSelectIndex(void 0);
|
|
88
89
|
},
|
|
89
90
|
onClick: () => {
|
|
90
|
-
if (
|
|
91
|
-
|
|
91
|
+
if (isOpen && text.length === 0) {
|
|
92
|
+
close();
|
|
92
93
|
return;
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
+
open();
|
|
95
96
|
setSelectIndex(void 0);
|
|
96
97
|
},
|
|
97
98
|
onKeyDown: (e) => {
|
|
@@ -101,7 +102,7 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
103
104
|
if (e.key === "ArrowDown") {
|
|
104
|
-
|
|
105
|
+
open();
|
|
105
106
|
setSelectIndex((prev) => {
|
|
106
107
|
if (prev === void 0) return 0;
|
|
107
108
|
return Math.min(prev + 1, options.length - 1);
|
|
@@ -109,7 +110,7 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
109
110
|
return;
|
|
110
111
|
}
|
|
111
112
|
if (e.key === "ArrowUp") {
|
|
112
|
-
|
|
113
|
+
open();
|
|
113
114
|
setSelectIndex((prev) => {
|
|
114
115
|
if (prev === void 0) return 0;
|
|
115
116
|
return Math.max(prev - 1, 0);
|
|
@@ -149,7 +150,7 @@ const Autocomplete = ({ id, name, invalid = false, disabled = false, required =
|
|
|
149
150
|
}),
|
|
150
151
|
/* @__PURE__ */ jsx("div", {
|
|
151
152
|
className: "relative w-full",
|
|
152
|
-
children:
|
|
153
|
+
children: isOpen && /* @__PURE__ */ jsx("div", {
|
|
153
154
|
className: "bg-bg-raised absolute top-1 z-10 w-full rounded-xl shadow-md",
|
|
154
155
|
role: "presentation",
|
|
155
156
|
children: /* @__PURE__ */ jsxs("ul", {
|
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { CheckIcon } from "../../icons/lucide.mjs";
|
|
4
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
4
5
|
import { useCheckboxGroupContext } from "../checkbox-group/checkbox-group.mjs";
|
|
5
|
-
import { useState } from "react";
|
|
6
6
|
import { useFormStatus } from "react-dom";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/form/checkbox/checkbox.tsx
|
|
9
9
|
const Checkbox = ({ name, itemValue, disabled = false, label, value, defaultChecked, onChange, ...rest }) => {
|
|
10
10
|
const groupContext = useCheckboxGroupContext();
|
|
11
11
|
const { pending } = useFormStatus();
|
|
12
|
-
const [internalChecked, setInternalChecked] =
|
|
12
|
+
const [internalChecked, setInternalChecked] = useControllableState({
|
|
13
|
+
value,
|
|
14
|
+
defaultValue: defaultChecked ?? false
|
|
15
|
+
});
|
|
13
16
|
const groupItemValue = itemValue ?? "";
|
|
14
17
|
if (groupContext && (itemValue === void 0 || itemValue === "")) throw new Error("Checkbox inside CheckboxGroup requires itemValue");
|
|
15
18
|
const isControlled = value !== void 0;
|
|
16
19
|
const disabledResolved = disabled || groupContext?.disabled === true || pending;
|
|
17
|
-
const checked = groupContext ? groupContext.currentValue.includes(groupItemValue) :
|
|
20
|
+
const checked = groupContext ? groupContext.currentValue.includes(groupItemValue) : internalChecked;
|
|
18
21
|
const setChecked = (nextChecked) => {
|
|
19
|
-
|
|
22
|
+
setInternalChecked(nextChecked);
|
|
20
23
|
onChange?.({ target: { checked: nextChecked } });
|
|
21
24
|
};
|
|
22
25
|
return /* @__PURE__ */ jsxs("label", {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { CheckIcon } from "../../icons/lucide.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
5
|
+
import { useId } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
//#region src/components/form/checkbox-card/checkbox-card.tsx
|
|
7
8
|
const CheckboxCard = ({ name, disabled = false, invalid = false, options, value, defaultValue, onChange, ...rest }) => {
|
|
8
9
|
const groupId = useId();
|
|
9
|
-
const [
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const [selectedValues, setSelectedValues] = useControllableState({
|
|
11
|
+
value,
|
|
12
|
+
defaultValue: defaultValue ?? [],
|
|
13
|
+
onChange
|
|
14
|
+
});
|
|
12
15
|
const handleToggle = (nextValue, checked) => {
|
|
13
|
-
|
|
14
|
-
if (!isControlled) setInternalValue(nextValues);
|
|
15
|
-
onChange?.(nextValues);
|
|
16
|
+
setSelectedValues(checked ? [...selectedValues, nextValue] : selectedValues.filter((item) => item !== nextValue));
|
|
16
17
|
};
|
|
17
18
|
return /* @__PURE__ */ jsx("fieldset", {
|
|
18
19
|
...rest,
|
|
@@ -5,7 +5,7 @@ declare const CheckboxGroup: _$react.FC<{
|
|
|
5
5
|
invalid?: boolean;
|
|
6
6
|
required?: boolean;
|
|
7
7
|
name: string;
|
|
8
|
-
} & Omit<_$react.FieldsetHTMLAttributes<HTMLFieldSetElement>, "
|
|
8
|
+
} & Omit<_$react.FieldsetHTMLAttributes<HTMLFieldSetElement>, "className" | "onChange" | "defaultValue" | "name"> & {
|
|
9
9
|
children?: _$react.ReactNode | undefined;
|
|
10
10
|
} & ({
|
|
11
11
|
value: string[];
|
|
@@ -20,7 +20,7 @@ declare const CheckboxGroup: _$react.FC<{
|
|
|
20
20
|
invalid?: boolean;
|
|
21
21
|
required?: boolean;
|
|
22
22
|
name: string;
|
|
23
|
-
} & Omit<_$react.FieldsetHTMLAttributes<HTMLFieldSetElement>, "
|
|
23
|
+
} & Omit<_$react.FieldsetHTMLAttributes<HTMLFieldSetElement>, "className" | "onChange" | "defaultValue" | "name"> & {
|
|
24
24
|
children?: _$react.ReactNode | undefined;
|
|
25
25
|
} & ({
|
|
26
26
|
value: string[];
|
|
@@ -35,7 +35,7 @@ declare const CheckboxGroup: _$react.FC<{
|
|
|
35
35
|
Item: _$react.FC<{
|
|
36
36
|
itemValue?: string;
|
|
37
37
|
label: string;
|
|
38
|
-
} & Omit<_$react.InputHTMLAttributes<HTMLInputElement>, "
|
|
38
|
+
} & Omit<_$react.InputHTMLAttributes<HTMLInputElement>, "type" | "className" | "value" | "onChange" | "children" | "checked" | "defaultChecked"> & ({
|
|
39
39
|
value: boolean;
|
|
40
40
|
onChange: _$react.ChangeEventHandler<HTMLInputElement>;
|
|
41
41
|
defaultChecked?: never;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
|
|
3
3
|
import { CloseIcon } from "../../icons/lucide.mjs";
|
|
4
4
|
import { IconButton } from "../../buttons/icon-button/icon-button.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { useCallback, useId, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { useFormStatus } from "react-dom";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/form/file-field/file-field.tsx
|
|
9
|
-
const
|
|
10
|
-
const FileFieldProvider = FileFieldContext;
|
|
11
|
-
const useFileFieldContext = () => {
|
|
12
|
-
const fileField = use(FileFieldContext);
|
|
13
|
-
if (!fileField) throw new Error("useFileFieldContext must be used within a FileField.Root");
|
|
14
|
-
return fileField;
|
|
15
|
-
};
|
|
9
|
+
const [FileFieldProvider, useFileFieldContext] = createSafeContext("useFileFieldContext must be used within a FileField.Root");
|
|
16
10
|
const Root = ({ children, disabled = false, invalid = false, required = false, multiple = false, maxFiles, onChange, webkitDirectory = false, ...rest }) => {
|
|
17
11
|
const generatedId = useId();
|
|
18
12
|
const inputRef = useRef(null);
|
|
@@ -23,7 +17,7 @@ const Root = ({ children, disabled = false, invalid = false, required = false, m
|
|
|
23
17
|
onChange?.(event);
|
|
24
18
|
const newFiles = Array.from(event.target.files ?? []).map((file) => ({
|
|
25
19
|
file,
|
|
26
|
-
id:
|
|
20
|
+
id: crypto.randomUUID()
|
|
27
21
|
}));
|
|
28
22
|
setAcceptedFiles(multiple || webkitDirectory ? [...acceptedFiles, ...newFiles].slice(0, maxFiles ?? Number.POSITIVE_INFINITY) : newFiles.slice(0, 1));
|
|
29
23
|
}, [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { toPrecision } from "
|
|
2
|
-
//#region src/
|
|
1
|
+
import { toPrecision } from "../../../internal/to-precision.mjs";
|
|
2
|
+
//#region src/components/form/number-field/cast.ts
|
|
3
3
|
const FLOATING_POINT_REGEX = /^[Ee0-9+\-.]$/;
|
|
4
4
|
const isInvalidCharacter = (value) => FLOATING_POINT_REGEX.test(value);
|
|
5
5
|
const sanitize = (value) => value.split("").filter((char) => isInvalidCharacter(char)).join("");
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { ChevronIcon } from "../../icons/lucide.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { toPrecision } from "../../../internal/to-precision.mjs";
|
|
5
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
6
|
+
import { clamp } from "../../../internal/clamp.mjs";
|
|
7
|
+
import { cast } from "./cast.mjs";
|
|
7
8
|
import { useState } from "react";
|
|
8
9
|
import { useFormStatus } from "react-dom";
|
|
9
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
//#region src/components/form/number-field/number-field.tsx
|
|
11
12
|
const NumberField = ({ invalid = false, disabled = false, required = false, value, defaultValue, onChange, step = 1, precision = 0, max = 9007199254740991, min = -9007199254740991, ...rest }) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const [currentValue, setCurrentValue] = useControllableState({
|
|
14
|
+
value,
|
|
15
|
+
defaultValue: defaultValue ?? 0,
|
|
16
|
+
onChange
|
|
17
|
+
});
|
|
18
|
+
const [displayValue, setDisplayValue] = useState(() => currentValue.toFixed(precision));
|
|
19
|
+
const [prevValue, setPrevValue] = useState(currentValue);
|
|
17
20
|
const { pending } = useFormStatus();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
setPrevValue(value);
|
|
21
|
+
if (currentValue !== prevValue) {
|
|
22
|
+
setDisplayValue(currentValue.toFixed(precision));
|
|
23
|
+
setPrevValue(currentValue);
|
|
22
24
|
}
|
|
23
25
|
const handleChange = (newValue) => {
|
|
24
|
-
|
|
25
|
-
onChange?.(newValue);
|
|
26
|
+
setCurrentValue(newValue);
|
|
26
27
|
};
|
|
27
28
|
return /* @__PURE__ */ jsxs("div", {
|
|
28
29
|
className: cn("relative flex h-12 w-full items-center justify-between gap-2 rounded-xl border border-border-base bg-bg-base", "focus-within:border-transparent focus-within:outline-hidden focus-within:ring-2 focus-within:ring-border-info", "has-aria-invalid:border-border-error", "has-disabled:cursor-not-allowed has-disabled:border-border-mute has-disabled:bg-bg-mute hover:has-disabled:has-hover:bg-bg-mute"),
|
|
@@ -40,7 +41,7 @@ const NumberField = ({ invalid = false, disabled = false, required = false, valu
|
|
|
40
41
|
disabled,
|
|
41
42
|
readOnly: pending || void 0,
|
|
42
43
|
onBlur: () => {
|
|
43
|
-
const newValue =
|
|
44
|
+
const newValue = clamp(cast(displayValue, precision), min, max);
|
|
44
45
|
handleChange(newValue);
|
|
45
46
|
setDisplayValue(newValue.toFixed(precision));
|
|
46
47
|
},
|
|
@@ -50,12 +51,12 @@ const NumberField = ({ invalid = false, disabled = false, required = false, valu
|
|
|
50
51
|
},
|
|
51
52
|
onKeyDown: (e) => {
|
|
52
53
|
if (e.key === "ArrowUp") {
|
|
53
|
-
const newValue =
|
|
54
|
+
const newValue = clamp(toPrecision(cast(displayValue, precision) + step, precision), min, max);
|
|
54
55
|
handleChange(newValue);
|
|
55
56
|
setDisplayValue(newValue.toFixed(precision));
|
|
56
57
|
}
|
|
57
58
|
if (e.key === "ArrowDown") {
|
|
58
|
-
const newValue =
|
|
59
|
+
const newValue = clamp(toPrecision(cast(displayValue, precision) - step, precision), min, max);
|
|
59
60
|
handleChange(newValue);
|
|
60
61
|
setDisplayValue(newValue.toFixed(precision));
|
|
61
62
|
}
|
|
@@ -71,7 +72,7 @@ const NumberField = ({ invalid = false, disabled = false, required = false, valu
|
|
|
71
72
|
className: cn("flex w-6 grow items-center justify-center rounded-md text-fg-mute transition-colors", "hover:bg-bg-mute hover:text-fg-base", "disabled:cursor-not-allowed disabled:text-fg-mute hover:disabled:bg-transparent"),
|
|
72
73
|
disabled: disabled || pending,
|
|
73
74
|
onClick: () => {
|
|
74
|
-
const newValue =
|
|
75
|
+
const newValue = clamp(toPrecision(cast(displayValue, precision) + step, precision), min, max);
|
|
75
76
|
handleChange(newValue);
|
|
76
77
|
setDisplayValue(newValue.toFixed(precision));
|
|
77
78
|
},
|
|
@@ -88,7 +89,7 @@ const NumberField = ({ invalid = false, disabled = false, required = false, valu
|
|
|
88
89
|
className: cn("flex w-6 grow items-center justify-center rounded-md text-fg-mute transition-colors", "hover:bg-bg-mute hover:text-fg-base", "disabled:cursor-not-allowed disabled:text-fg-mute hover:disabled:bg-transparent"),
|
|
89
90
|
disabled: disabled || pending,
|
|
90
91
|
onClick: () => {
|
|
91
|
-
const newValue =
|
|
92
|
+
const newValue = clamp(toPrecision(cast(displayValue, precision) - step, precision), min, max);
|
|
92
93
|
handleChange(newValue);
|
|
93
94
|
setDisplayValue(newValue.toFixed(precision));
|
|
94
95
|
},
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
4
4
|
import { useFormStatus } from "react-dom";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/form/radio/radio.tsx
|
|
7
7
|
const Radio = ({ "aria-labelledby": labelledbyId, name, disabled = false, value, defaultValue, onChange, options, ...rest }) => {
|
|
8
|
-
const [
|
|
8
|
+
const [selectedValue, setSelectedValue] = useControllableState({
|
|
9
|
+
value,
|
|
10
|
+
defaultValue
|
|
11
|
+
});
|
|
9
12
|
const { pending } = useFormStatus();
|
|
10
13
|
const isControlled = value !== void 0;
|
|
11
|
-
const selectedValue = isControlled ? value : internalValue;
|
|
12
14
|
const disabledResolved = disabled || pending;
|
|
13
15
|
const selectValue = (nextValue) => {
|
|
14
|
-
|
|
16
|
+
setSelectedValue(nextValue);
|
|
15
17
|
onChange?.({ target: { value: nextValue } });
|
|
16
18
|
};
|
|
17
19
|
return /* @__PURE__ */ jsx("div", {
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
4
|
+
import { useId, useRef } from "react";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
//#region src/components/form/radio-card/radio-card.tsx
|
|
6
7
|
const RadioCard = ({ "aria-labelledby": labelledbyId, name, disabled = false, invalid = false, options, value, defaultValue, onChange, ...rest }) => {
|
|
7
8
|
const groupId = useId();
|
|
8
9
|
const buttonRefs = useRef([]);
|
|
9
|
-
const [
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const [currentValue, setCurrentValue] = useControllableState({
|
|
11
|
+
value,
|
|
12
|
+
defaultValue: defaultValue ?? options[0]?.value
|
|
13
|
+
});
|
|
12
14
|
const selectValue = (nextValue) => {
|
|
13
|
-
|
|
15
|
+
setCurrentValue(nextValue);
|
|
14
16
|
onChange?.({ target: { value: nextValue } });
|
|
15
17
|
};
|
|
16
18
|
const focusIndex = (index) => {
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
4
|
+
import { useId } from "react";
|
|
4
5
|
import { useFormStatus } from "react-dom";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
//#region src/components/form/switch/switch.tsx
|
|
7
8
|
const Switch = ({ value, defaultChecked, id, disabled = false, invalid = false, required = false, label, onChange, ...rest }) => {
|
|
8
9
|
const generatedId = useId();
|
|
9
10
|
const inputId = id ?? generatedId;
|
|
10
|
-
const [
|
|
11
|
+
const [isSelected, setSelected] = useControllableState({
|
|
12
|
+
value,
|
|
13
|
+
defaultValue: defaultChecked ?? false
|
|
14
|
+
});
|
|
11
15
|
const { pending } = useFormStatus();
|
|
12
16
|
const isControlled = value !== void 0;
|
|
13
|
-
const isSelected = isControlled ? value : internalChecked;
|
|
14
17
|
const disabledResolved = disabled || pending;
|
|
15
18
|
return /* @__PURE__ */ jsxs("label", {
|
|
16
19
|
className: cn("inline-flex w-fit items-center gap-3", disabledResolved ? "cursor-not-allowed text-fg-mute" : "cursor-pointer"),
|
|
@@ -27,7 +30,7 @@ const Switch = ({ value, defaultChecked, id, disabled = false, invalid = false,
|
|
|
27
30
|
disabled: disabledResolved,
|
|
28
31
|
id: inputId,
|
|
29
32
|
onChange: (event) => {
|
|
30
|
-
|
|
33
|
+
setSelected(event.target.checked);
|
|
31
34
|
onChange?.(event);
|
|
32
35
|
},
|
|
33
36
|
required,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ArteOdyssey } from "./arte-odyssey.mjs";
|
|
2
2
|
import { GitHubIcon } from "./github-mark.mjs";
|
|
3
3
|
import { Logo, LogoIcon } from "./logo.mjs";
|
|
4
|
-
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./lucide.mjs";
|
|
4
|
+
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./lucide.mjs";
|
|
5
5
|
import { QiitaIcon } from "./qiita.mjs";
|
|
6
6
|
import { TwitterIcon } from "./twitter.mjs";
|
|
7
|
-
|
|
7
|
+
import { VerticalWritingIcon } from "./vertical-writing.mjs";
|
|
8
|
+
export { AIIcon, AccessibilityIcon, AlertIcon, ArteOdyssey, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GitHubIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, QiitaIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, TwitterIcon, UpdateDateIcon, VerticalWritingIcon, ViewIcon, ViewOffIcon };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ArteOdyssey } from "./arte-odyssey.mjs";
|
|
2
2
|
import { GitHubIcon } from "./github-mark.mjs";
|
|
3
3
|
import { Logo, LogoIcon } from "./logo.mjs";
|
|
4
|
-
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./lucide.mjs";
|
|
4
|
+
import { AIIcon, AccessibilityIcon, AlertIcon, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, UpdateDateIcon, ViewIcon, ViewOffIcon } from "./lucide.mjs";
|
|
5
5
|
import { QiitaIcon } from "./qiita.mjs";
|
|
6
6
|
import { TwitterIcon } from "./twitter.mjs";
|
|
7
|
-
|
|
7
|
+
import { VerticalWritingIcon } from "./vertical-writing.mjs";
|
|
8
|
+
export { AIIcon, AccessibilityIcon, AlertIcon, ArteOdyssey, AtomIcon, BadIcon, BlogIcon, BoringIcon, CheckIcon, ChevronIcon, CloseIcon, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, DifficultIcon, EasyIcon, ExternalLinkIcon, FormIcon, GitHubIcon, GoodIcon, HistoryIcon, HorizontalWritingIcon, InformativeIcon, InterestingIcon, LightModeIcon, LinkIcon, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, NavigationMenuIcon, NewsIcon, PaletteIcon, PlusIcon, PrepareIcon, PublishDateIcon, QiitaIcon, RSSIcon, SendIcon, ShallowIcon, ShieldCheckIcon, SlideIcon, SparklesIcon, SubscribeIcon, TableIcon, TagIcon, TwitterIcon, UpdateDateIcon, VerticalWritingIcon, ViewIcon, ViewOffIcon };
|