@k8o/arte-odyssey 4.2.0 → 5.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/button/button.mjs +1 -1
- package/dist/components/buttons/link-button/link-button.mjs +1 -1
- package/dist/components/data-display/accordion/context.mjs +5 -6
- package/dist/components/data-display/card/card.mjs +1 -1
- package/dist/components/data-display/card/interactive-card.mjs +1 -1
- package/dist/components/form/autocomplete/autocomplete.d.mts +1 -0
- package/dist/components/form/autocomplete/autocomplete.mjs +140 -133
- package/dist/components/form/checkbox/checkbox.d.mts +1 -0
- package/dist/components/form/checkbox/checkbox.mjs +2 -2
- package/dist/components/form/checkbox-card/checkbox-card.d.mts +1 -0
- package/dist/components/form/checkbox-card/checkbox-card.mjs +3 -2
- package/dist/components/form/checkbox-group/checkbox-group.mjs +8 -7
- package/dist/components/form/checkbox-group/index.d.mts +1 -0
- package/dist/components/form/file-field/file-field.mjs +1 -1
- package/dist/components/form/number-field/number-field.d.mts +1 -0
- package/dist/components/form/number-field/number-field.mjs +5 -4
- package/dist/components/form/password-input/password-input.mjs +4 -6
- package/dist/components/form/radio/radio.d.mts +1 -0
- package/dist/components/form/radio/radio.mjs +2 -2
- package/dist/components/form/radio-card/radio-card.d.mts +1 -0
- package/dist/components/form/radio-card/radio-card.mjs +9 -5
- package/dist/components/form/select/select.d.mts +1 -0
- package/dist/components/form/select/select.mjs +3 -2
- package/dist/components/form/slider/slider.mjs +7 -10
- package/dist/components/form/text-field/text-field.mjs +1 -1
- package/dist/components/form/textarea/textarea.mjs +1 -1
- package/dist/components/navigation/tabs/tabs.mjs +1 -1
- package/dist/components/overlays/modal/modal.mjs +1 -1
- package/dist/components/overlays/popover/hooks.mjs +3 -2
- package/dist/components/overlays/popover/popover.mjs +8 -16
- package/dist/hooks/breakpoint/index.d.mts +5 -0
- package/dist/hooks/breakpoint/index.mjs +24 -0
- package/dist/hooks/click-away/index.d.mts +1 -1
- package/dist/hooks/click-away/index.mjs +7 -5
- package/dist/hooks/controllable-state/index.d.mts +13 -0
- package/dist/hooks/controllable-state/index.mjs +21 -0
- package/dist/hooks/debounce/index.d.mts +6 -0
- package/dist/hooks/debounce/index.mjs +35 -0
- package/dist/hooks/disclosure/index.d.mts +10 -0
- package/dist/hooks/disclosure/index.mjs +14 -0
- package/dist/hooks/hover/index.d.mts +12 -0
- package/dist/hooks/hover/index.mjs +15 -0
- package/dist/hooks/index.d.mts +11 -1
- package/dist/hooks/index.mjs +11 -1
- package/dist/hooks/intersection-observer/index.d.mts +3 -0
- package/dist/hooks/intersection-observer/index.mjs +3 -0
- package/dist/hooks/intersection-observer/use-in-view.d.mts +12 -0
- package/dist/hooks/intersection-observer/use-in-view.mjs +17 -0
- package/dist/hooks/intersection-observer/use-intersection-observer.d.mts +12 -0
- package/dist/hooks/intersection-observer/use-intersection-observer.mjs +33 -0
- package/dist/hooks/local-storage/index.mjs +5 -4
- package/dist/hooks/resize/index.d.mts +1 -1
- package/dist/hooks/resize/index.mjs +2 -3
- package/dist/hooks/scroll-direction/index.mjs +47 -22
- package/dist/hooks/scroll-lock/index.d.mts +8 -0
- package/dist/hooks/scroll-lock/index.mjs +44 -0
- package/dist/hooks/session-storage/index.d.mts +4 -0
- package/dist/hooks/session-storage/index.mjs +46 -0
- package/dist/hooks/throttle/index.d.mts +6 -0
- package/dist/hooks/throttle/index.mjs +53 -0
- package/dist/hooks/window-size/index.mjs +26 -19
- package/dist/index.d.mts +11 -1
- package/dist/index.mjs +11 -1
- package/dist/styles/index.css +186 -137
- package/docs/GUIDE.md +52 -33
- package/docs/references/color.md +71 -36
- package/docs/references/components.md +555 -181
- package/docs/references/helpers.md +120 -0
- package/docs/references/hooks.md +295 -0
- package/docs/references/interaction-design.md +24 -6
- package/docs/references/spatial-design.md +69 -33
- package/docs/references/typography.md +31 -17
- package/package.json +18 -18
|
@@ -3,7 +3,7 @@ import { jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
//#region src/components/buttons/button/button.tsx
|
|
4
4
|
const Button = ({ ref, children, type = "button", size = "md", color = "primary", variant = "contained", disabled = false, fullWidth = false, onClick, startIcon, endIcon, ...rest }) => {
|
|
5
5
|
return /* @__PURE__ */ jsxs("button", {
|
|
6
|
-
className: cn("cursor-pointer rounded-
|
|
6
|
+
className: cn("cursor-pointer rounded-full border-2 text-center font-bold transition-colors", {
|
|
7
7
|
"border-transparent bg-primary-bg text-fg hover:bg-primary-bg/90 active:bg-primary-bg/80": variant === "contained" && color === "primary",
|
|
8
8
|
"border-transparent bg-bg-subtle text-fg-base hover:bg-bg-mute active:bg-bg-emphasize": variant === "contained" && color === "gray",
|
|
9
9
|
"cursor-not-allowed opacity-35 hover:bg-primary-bg active:bg-primary-bg": disabled && variant === "contained",
|
|
@@ -12,7 +12,7 @@ const LinkButton = ({ children, size = "md", color = "primary", variant = "conta
|
|
|
12
12
|
};
|
|
13
13
|
return renderAnchor({
|
|
14
14
|
href,
|
|
15
|
-
className: cn("rounded-
|
|
15
|
+
className: cn("rounded-full border-2 text-center font-bold transition-colors", {
|
|
16
16
|
"border-transparent bg-primary-bg text-fg hover:bg-primary-bg/90 active:bg-primary-bg/80": variant === "contained" && color === "primary",
|
|
17
17
|
"border-transparent bg-bg-subtle text-fg-base hover:bg-bg-mute active:bg-bg-emphasize": variant === "contained" && color === "gray",
|
|
18
18
|
"border-primary-border bg-bg-base text-primary-fg hover:bg-bg-subtle active:bg-bg-emphasize": variant === "outlined" && color === "primary",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { useDisclosure } from "../../../hooks/disclosure/index.mjs";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, use
|
|
4
|
+
import { createContext, use } from "react";
|
|
4
5
|
//#region src/components/data-display/accordion/context.tsx
|
|
5
6
|
const OpenContext = createContext(false);
|
|
6
7
|
const ToggleOpenContext = createContext(void 0);
|
|
@@ -17,13 +18,11 @@ const useItemId = () => {
|
|
|
17
18
|
return id;
|
|
18
19
|
};
|
|
19
20
|
const AccordionItemProvider = ({ defaultOpen = false, id, children }) => {
|
|
20
|
-
const
|
|
21
|
+
const { isOpen, toggle } = useDisclosure(defaultOpen);
|
|
21
22
|
return /* @__PURE__ */ jsx(OpenContext, {
|
|
22
|
-
value:
|
|
23
|
+
value: isOpen,
|
|
23
24
|
children: /* @__PURE__ */ jsx(ToggleOpenContext, {
|
|
24
|
-
value:
|
|
25
|
-
setOpen((open) => !open);
|
|
26
|
-
}, []),
|
|
25
|
+
value: toggle,
|
|
27
26
|
children: /* @__PURE__ */ jsx(ItemIdContext, {
|
|
28
27
|
value: id,
|
|
29
28
|
children
|
|
@@ -2,7 +2,7 @@ import { cn } from "../../../helpers/cn.mjs";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/data-display/card/card.tsx
|
|
4
4
|
const Card = ({ children, variant = "primary", width = "full", appearance = "shadow" }) => /* @__PURE__ */ jsx("div", {
|
|
5
|
-
className: cn("rounded-
|
|
5
|
+
className: cn("rounded-xl", appearance === "shadow" && "shadow-sm", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", variant === "primary" && "bg-bg-base", variant === "secondary" && "bg-bg-mute"),
|
|
6
6
|
children
|
|
7
7
|
});
|
|
8
8
|
//#endregion
|
|
@@ -2,7 +2,7 @@ import { cn } from "../../../helpers/cn.mjs";
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/data-display/card/interactive-card.tsx
|
|
4
4
|
const InteractiveCard = ({ children, variant = "primary", width = "full", appearance = "shadow" }) => /* @__PURE__ */ jsx("div", {
|
|
5
|
-
className: cn("rounded-
|
|
5
|
+
className: cn("rounded-xl transition-transform hover:scale-[1.02] active:scale-[0.98]", appearance === "shadow" && "shadow-sm", appearance === "bordered" && "border border-border-mute", width === "full" && "w-full", width === "fit" && "w-fit", variant === "primary" && "bg-bg-base", variant === "secondary" && "bg-bg-mute"),
|
|
6
6
|
children
|
|
7
7
|
});
|
|
8
8
|
//#endregion
|
|
@@ -2,21 +2,20 @@
|
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { IconButton } from "../../buttons/icon-button/icon-button.mjs";
|
|
4
4
|
import { CloseIcon } from "../../icons/lucide.mjs";
|
|
5
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
7
8
|
//#region src/components/form/autocomplete/autocomplete.tsx
|
|
8
|
-
const Autocomplete = ({ id, describedbyId, isInvalid, isDisabled, isRequired, options, value, defaultValue, onChange }) => {
|
|
9
|
-
const [
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const Autocomplete = ({ id, name, describedbyId, isInvalid, isDisabled, isRequired, options, value, defaultValue, onChange }) => {
|
|
10
|
+
const [currentValue, handleChange] = useControllableState({
|
|
11
|
+
value,
|
|
12
|
+
defaultValue: defaultValue || [],
|
|
13
|
+
onChange
|
|
14
|
+
});
|
|
12
15
|
const ref = useRef(null);
|
|
13
16
|
const [open, setOpen] = useState(false);
|
|
14
17
|
const [text, setText] = useState("");
|
|
15
18
|
const [selectIndex, setSelectIndex] = useState();
|
|
16
|
-
const handleChange = useCallback((newValue) => {
|
|
17
|
-
if (!isControlled) setInternalValue(newValue);
|
|
18
|
-
onChange?.(newValue);
|
|
19
|
-
}, [isControlled, onChange]);
|
|
20
19
|
const filteredOptions = options.filter((option) => option.label.includes(text));
|
|
21
20
|
const reset = useCallback(() => {
|
|
22
21
|
setText("");
|
|
@@ -34,143 +33,151 @@ const Autocomplete = ({ id, describedbyId, isInvalid, isDisabled, isRequired, op
|
|
|
34
33
|
};
|
|
35
34
|
}, [reset]);
|
|
36
35
|
return /* @__PURE__ */ jsxs("div", {
|
|
37
|
-
className: cn("relative w-full rounded-
|
|
36
|
+
className: cn("relative w-full 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 has-disabled:has-hover:hover:bg-bg-mute"),
|
|
38
37
|
ref,
|
|
39
|
-
children: [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
onClick: () => {
|
|
80
|
-
if (open && text.length === 0) {
|
|
38
|
+
children: [
|
|
39
|
+
name ? currentValue.map((selectedValue) => /* @__PURE__ */ jsx("input", {
|
|
40
|
+
name,
|
|
41
|
+
type: "hidden",
|
|
42
|
+
value: selectedValue
|
|
43
|
+
}, selectedValue)) : null,
|
|
44
|
+
/* @__PURE__ */ jsxs("div", {
|
|
45
|
+
className: "flex min-h-12 items-center justify-between gap-2 px-3 py-2",
|
|
46
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
47
|
+
className: "flex w-full flex-wrap gap-1",
|
|
48
|
+
children: [currentValue.map((text) => {
|
|
49
|
+
const label = options.find((option) => option.value === text)?.label;
|
|
50
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
51
|
+
className: "inline-flex items-center gap-2 rounded-full bg-bg-mute px-3 py-1 font-medium text-sm",
|
|
52
|
+
tabIndex: -1,
|
|
53
|
+
children: [label, /* @__PURE__ */ jsx(IconButton, {
|
|
54
|
+
label: "閉じる",
|
|
55
|
+
onClick: (e) => {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
reset();
|
|
58
|
+
handleChange(currentValue.filter((v) => v !== text));
|
|
59
|
+
},
|
|
60
|
+
size: "sm",
|
|
61
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { size: "sm" })
|
|
62
|
+
})]
|
|
63
|
+
}, text);
|
|
64
|
+
}), /* @__PURE__ */ jsx("input", {
|
|
65
|
+
"aria-autocomplete": "list",
|
|
66
|
+
"aria-controls": open ? `${id}_listbox` : void 0,
|
|
67
|
+
"aria-describedby": describedbyId,
|
|
68
|
+
"aria-expanded": open,
|
|
69
|
+
"aria-invalid": isInvalid,
|
|
70
|
+
"aria-required": isRequired,
|
|
71
|
+
autoComplete: "off",
|
|
72
|
+
className: cn("grow bg-transparent focus-visible:outline-hidden", "disabled:cursor-not-allowed"),
|
|
73
|
+
disabled: isDisabled,
|
|
74
|
+
id,
|
|
75
|
+
onBlur: (e) => {
|
|
76
|
+
if (e.relatedTarget?.id.startsWith(`${id}_option_`)) return;
|
|
81
77
|
setOpen(false);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
setOpen(true);
|
|
85
|
-
setSelectIndex(void 0);
|
|
86
|
-
},
|
|
87
|
-
onKeyDown: (e) => {
|
|
88
|
-
if (e.key === "Backspace" && text.length === 0) {
|
|
89
|
-
reset();
|
|
90
|
-
handleChange(currentValue.slice(0, -1));
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (e.key === "ArrowDown") {
|
|
78
|
+
},
|
|
79
|
+
onChange: (e) => {
|
|
94
80
|
setOpen(true);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
81
|
+
setText(e.target.value);
|
|
82
|
+
setSelectIndex(void 0);
|
|
83
|
+
},
|
|
84
|
+
onClick: () => {
|
|
85
|
+
if (open && text.length === 0) {
|
|
86
|
+
setOpen(false);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
102
89
|
setOpen(true);
|
|
103
|
-
setSelectIndex(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (e.key === "Enter" && selectIndex !== void 0 && selectIndex >= 0) {
|
|
110
|
-
const selected = filteredOptions[selectIndex];
|
|
111
|
-
if (!selected) return;
|
|
112
|
-
if (currentValue.includes(selected.value)) {
|
|
113
|
-
handleChange(currentValue.filter((v) => v !== selected.value));
|
|
90
|
+
setSelectIndex(void 0);
|
|
91
|
+
},
|
|
92
|
+
onKeyDown: (e) => {
|
|
93
|
+
if (e.key === "Backspace" && text.length === 0) {
|
|
114
94
|
reset();
|
|
95
|
+
handleChange(currentValue.slice(0, -1));
|
|
115
96
|
return;
|
|
116
97
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
className: "absolute top-1 z-10 w-full rounded-lg border border-border-mute bg-bg-base shadow-md",
|
|
140
|
-
role: "presentation",
|
|
141
|
-
children: /* @__PURE__ */ jsxs("ul", {
|
|
142
|
-
className: "max-h-96 py-2",
|
|
143
|
-
id: `${id}_listbox`,
|
|
144
|
-
children: [filteredOptions.length === 0 && /* @__PURE__ */ jsx("li", {
|
|
145
|
-
className: "px-3 py-2 text-fg-mute",
|
|
146
|
-
children: "該当なし"
|
|
147
|
-
}), filteredOptions.map((option, idx) => {
|
|
148
|
-
const selected = currentValue.includes(option.value);
|
|
149
|
-
return /* @__PURE__ */ jsx("li", {
|
|
150
|
-
className: cn("cursor-pointer px-3 py-2", selected && "bg-bg-mute", selectIndex === idx && !selected && "bg-bg-emphasize", selectIndex === idx && selected && "bg-bg-mute"),
|
|
151
|
-
id: `${id}_option_${option.value}`,
|
|
152
|
-
onClick: (e) => {
|
|
153
|
-
e.stopPropagation();
|
|
154
|
-
reset();
|
|
155
|
-
if (selected) {
|
|
156
|
-
handleChange(currentValue.filter((v) => v !== option.value));
|
|
98
|
+
if (e.key === "ArrowDown") {
|
|
99
|
+
setOpen(true);
|
|
100
|
+
setSelectIndex((prev) => {
|
|
101
|
+
if (prev === void 0) return 0;
|
|
102
|
+
return Math.min(prev + 1, options.length - 1);
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (e.key === "ArrowUp") {
|
|
107
|
+
setOpen(true);
|
|
108
|
+
setSelectIndex((prev) => {
|
|
109
|
+
if (prev === void 0) return 0;
|
|
110
|
+
return Math.max(prev - 1, 0);
|
|
111
|
+
});
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (e.key === "Enter" && selectIndex !== void 0 && selectIndex >= 0) {
|
|
115
|
+
const selected = filteredOptions[selectIndex];
|
|
116
|
+
if (!selected) return;
|
|
117
|
+
if (currentValue.includes(selected.value)) {
|
|
118
|
+
handleChange(currentValue.filter((v) => v !== selected.value));
|
|
119
|
+
reset();
|
|
157
120
|
return;
|
|
158
121
|
}
|
|
159
|
-
handleChange([...currentValue,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
children: option.label
|
|
169
|
-
}, option.value);
|
|
122
|
+
handleChange([...currentValue, selected.value]);
|
|
123
|
+
reset();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
placeholder: "入力して絞り込めます",
|
|
128
|
+
role: "combobox",
|
|
129
|
+
type: "text",
|
|
130
|
+
value: text
|
|
170
131
|
})]
|
|
132
|
+
}), currentValue.length > 0 && /* @__PURE__ */ jsx(IconButton, {
|
|
133
|
+
label: "すべて閉じる",
|
|
134
|
+
onClick: (e) => {
|
|
135
|
+
e.stopPropagation();
|
|
136
|
+
handleChange([]);
|
|
137
|
+
},
|
|
138
|
+
size: "sm",
|
|
139
|
+
children: /* @__PURE__ */ jsx(CloseIcon, { size: "sm" })
|
|
140
|
+
})]
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ jsx("div", {
|
|
143
|
+
className: "relative w-full",
|
|
144
|
+
children: open && /* @__PURE__ */ jsx("div", {
|
|
145
|
+
className: "absolute top-1 z-10 w-full rounded-xl border border-border-mute bg-bg-base shadow-md",
|
|
146
|
+
role: "presentation",
|
|
147
|
+
children: /* @__PURE__ */ jsxs("ul", {
|
|
148
|
+
className: "max-h-96 py-2",
|
|
149
|
+
id: `${id}_listbox`,
|
|
150
|
+
children: [filteredOptions.length === 0 && /* @__PURE__ */ jsx("li", {
|
|
151
|
+
className: "px-3 py-2 text-fg-mute",
|
|
152
|
+
children: "該当なし"
|
|
153
|
+
}), filteredOptions.map((option, idx) => {
|
|
154
|
+
const selected = currentValue.includes(option.value);
|
|
155
|
+
return /* @__PURE__ */ jsx("li", {
|
|
156
|
+
className: cn("cursor-pointer px-3 py-2", selected && "bg-bg-mute", selectIndex === idx && !selected && "bg-bg-emphasize", selectIndex === idx && selected && "bg-bg-mute"),
|
|
157
|
+
id: `${id}_option_${option.value}`,
|
|
158
|
+
onClick: (e) => {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
reset();
|
|
161
|
+
if (selected) {
|
|
162
|
+
handleChange(currentValue.filter((v) => v !== option.value));
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
handleChange([...currentValue, option.value]);
|
|
166
|
+
},
|
|
167
|
+
onKeyDown: (e) => {
|
|
168
|
+
e.preventDefault();
|
|
169
|
+
},
|
|
170
|
+
onMouseEnter: () => {
|
|
171
|
+
setSelectIndex(idx);
|
|
172
|
+
},
|
|
173
|
+
tabIndex: -1,
|
|
174
|
+
children: option.label
|
|
175
|
+
}, option.value);
|
|
176
|
+
})]
|
|
177
|
+
})
|
|
171
178
|
})
|
|
172
179
|
})
|
|
173
|
-
|
|
180
|
+
]
|
|
174
181
|
});
|
|
175
182
|
};
|
|
176
183
|
//#endregion
|
|
@@ -5,7 +5,7 @@ import { useCheckboxGroupContext } from "../checkbox-group/checkbox-group.mjs";
|
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
//#region src/components/form/checkbox/checkbox.tsx
|
|
8
|
-
const Checkbox = ({ itemValue, isDisabled = false, label, value, defaultChecked, onChange }) => {
|
|
8
|
+
const Checkbox = ({ name, itemValue, isDisabled = false, label, value, defaultChecked, onChange }) => {
|
|
9
9
|
const groupContext = useCheckboxGroupContext();
|
|
10
10
|
const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);
|
|
11
11
|
const groupItemValue = itemValue ?? "";
|
|
@@ -25,7 +25,7 @@ const Checkbox = ({ itemValue, isDisabled = false, label, value, defaultChecked,
|
|
|
25
25
|
className: "peer sr-only",
|
|
26
26
|
defaultChecked: groupContext || isControlled ? void 0 : defaultChecked,
|
|
27
27
|
disabled: isDisabledResolved,
|
|
28
|
-
name: groupContext?.name,
|
|
28
|
+
name: groupContext?.name ?? name,
|
|
29
29
|
onChange: (event) => {
|
|
30
30
|
if (groupContext) {
|
|
31
31
|
groupContext.toggleValue(groupItemValue);
|
|
@@ -4,7 +4,7 @@ import { CheckIcon } from "../../icons/lucide.mjs";
|
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { useId, useState } from "react";
|
|
6
6
|
//#region src/components/form/checkbox-card/checkbox-card.tsx
|
|
7
|
-
const CheckboxCard = ({ labelId, isDisabled, isInvalid = false, options, value, defaultValue, onChange }) => {
|
|
7
|
+
const CheckboxCard = ({ labelId, name, isDisabled, isInvalid = false, options, value, defaultValue, onChange }) => {
|
|
8
8
|
const groupId = useId();
|
|
9
9
|
const [internalValue, setInternalValue] = useState(defaultValue ?? []);
|
|
10
10
|
const isControlled = value !== void 0;
|
|
@@ -22,7 +22,7 @@ const CheckboxCard = ({ labelId, isDisabled, isInvalid = false, options, value,
|
|
|
22
22
|
const disabled = isDisabled || option.disabled;
|
|
23
23
|
const optionId = `${groupId}-${option.value}`;
|
|
24
24
|
return /* @__PURE__ */ jsxs("label", {
|
|
25
|
-
className: cn("flex w-full min-w-0 rounded-
|
|
25
|
+
className: cn("flex w-full min-w-0 rounded-xl border bg-bg-base p-4 text-left transition-colors", "has-[input:focus-visible]:outline-hidden has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-border-info", checked && "border-border-info bg-bg-subtle", isInvalid ? "border-border-error" : "border-border-mute hover:bg-bg-mute", disabled && "cursor-not-allowed border-border-mute bg-bg-subtle text-fg-mute"),
|
|
26
26
|
id: optionId,
|
|
27
27
|
children: [
|
|
28
28
|
/* @__PURE__ */ jsx("input", {
|
|
@@ -30,6 +30,7 @@ const CheckboxCard = ({ labelId, isDisabled, isInvalid = false, options, value,
|
|
|
30
30
|
checked,
|
|
31
31
|
className: "sr-only",
|
|
32
32
|
disabled,
|
|
33
|
+
name,
|
|
33
34
|
onChange: (event) => {
|
|
34
35
|
handleToggle(option.value, event.target.checked);
|
|
35
36
|
},
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
|
+
import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
import { createContext, use
|
|
5
|
+
import { createContext, use } from "react";
|
|
5
6
|
//#region src/components/form/checkbox-group/checkbox-group.tsx
|
|
6
7
|
const CheckboxGroupContext = createContext(void 0);
|
|
7
8
|
const useCheckboxGroupContext = () => use(CheckboxGroupContext);
|
|
8
9
|
const Root = ({ children, describedbyId, defaultValue, isDisabled = false, isInvalid = false, isRequired = false, labelId, name, onChange, value }) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const [currentValue, setCurrentValue] = useControllableState({
|
|
11
|
+
value,
|
|
12
|
+
defaultValue: defaultValue ?? [],
|
|
13
|
+
onChange
|
|
14
|
+
});
|
|
12
15
|
const toggleValue = (targetValue) => {
|
|
13
|
-
|
|
14
|
-
if (!isControlled) setInternalValue(nextValue);
|
|
15
|
-
onChange?.(nextValue);
|
|
16
|
+
setCurrentValue(currentValue.includes(targetValue) ? currentValue.filter((item) => item !== targetValue) : [...currentValue, targetValue]);
|
|
16
17
|
};
|
|
17
18
|
return /* @__PURE__ */ jsx("fieldset", {
|
|
18
19
|
"aria-describedby": describedbyId,
|
|
@@ -100,7 +100,7 @@ const ItemList = ({ showWebkitRelativePath, clearable }) => {
|
|
|
100
100
|
const onDelete = () => onFileDelete(id);
|
|
101
101
|
const sizeInKB = (file.size / 1024).toFixed(2);
|
|
102
102
|
return /* @__PURE__ */ jsxs("li", {
|
|
103
|
-
className: "flex items-center justify-between rounded-
|
|
103
|
+
className: "flex items-center justify-between rounded-xl border border-border-base bg-bg-base px-3 py-2",
|
|
104
104
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
105
105
|
className: "flex flex-col gap-1",
|
|
106
106
|
children: [/* @__PURE__ */ jsx("span", {
|
|
@@ -7,7 +7,7 @@ import { cast } from "../../../helpers/number/cast.mjs";
|
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { useState } from "react";
|
|
9
9
|
//#region src/components/form/number-field/number-field.tsx
|
|
10
|
-
const NumberField = ({ id, describedbyId, isInvalid, isDisabled, isRequired, value, defaultValue, onChange, step = 1, precision = 0, max = 9007199254740991, min = -9007199254740991, placeholder }) => {
|
|
10
|
+
const NumberField = ({ id, name, describedbyId, isInvalid, isDisabled, isRequired, value, defaultValue, onChange, step = 1, precision = 0, max = 9007199254740991, min = -9007199254740991, placeholder }) => {
|
|
11
11
|
const isControlled = value !== void 0;
|
|
12
12
|
const initialValue = defaultValue ?? value ?? 0;
|
|
13
13
|
const [internalValue, setInternalValue] = useState(initialValue);
|
|
@@ -23,7 +23,7 @@ const NumberField = ({ id, describedbyId, isInvalid, isDisabled, isRequired, val
|
|
|
23
23
|
onChange?.(newValue);
|
|
24
24
|
};
|
|
25
25
|
return /* @__PURE__ */ jsxs("div", {
|
|
26
|
-
className: cn("relative flex h-12 w-full items-center justify-between gap-2 rounded-
|
|
26
|
+
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 has-disabled:has-hover:hover:bg-bg-mute"),
|
|
27
27
|
children: [/* @__PURE__ */ jsx("input", {
|
|
28
28
|
"aria-describedby": describedbyId,
|
|
29
29
|
"aria-invalid": isInvalid,
|
|
@@ -37,6 +37,7 @@ const NumberField = ({ id, describedbyId, isInvalid, isDisabled, isRequired, val
|
|
|
37
37
|
disabled: isDisabled,
|
|
38
38
|
id,
|
|
39
39
|
inputMode: "decimal",
|
|
40
|
+
name,
|
|
40
41
|
onBlur: () => {
|
|
41
42
|
const newValue = between(cast(displayValue, precision), min, max);
|
|
42
43
|
handleChange(newValue);
|
|
@@ -67,7 +68,7 @@ const NumberField = ({ id, describedbyId, isInvalid, isDisabled, isRequired, val
|
|
|
67
68
|
"aria-hidden": "true",
|
|
68
69
|
className: "absolute right-0 flex h-full flex-col",
|
|
69
70
|
children: [/* @__PURE__ */ jsxs("button", {
|
|
70
|
-
className: cn("flex w-6 grow items-center justify-center rounded-tr-
|
|
71
|
+
className: cn("flex w-6 grow items-center justify-center rounded-tr-xl border-border-base border-b border-l bg-bg-mute", "disabled:cursor-not-allowed"),
|
|
71
72
|
disabled: isDisabled,
|
|
72
73
|
onClick: () => {
|
|
73
74
|
const newValue = between(toPrecision(cast(displayValue, precision) + step, precision), min, max);
|
|
@@ -81,7 +82,7 @@ const NumberField = ({ id, describedbyId, isInvalid, isDisabled, isRequired, val
|
|
|
81
82
|
children: "増やす"
|
|
82
83
|
}), /* @__PURE__ */ jsx(PlusIcon, { size: "sm" })]
|
|
83
84
|
}), /* @__PURE__ */ jsxs("button", {
|
|
84
|
-
className: cn("flex w-6 grow items-center justify-center rounded-br-
|
|
85
|
+
className: cn("flex w-6 grow items-center justify-center rounded-br-xl border-border-base border-l bg-bg-mute", "disabled:cursor-not-allowed"),
|
|
85
86
|
disabled: isDisabled,
|
|
86
87
|
onClick: () => {
|
|
87
88
|
const newValue = between(toPrecision(cast(displayValue, precision) - step, precision), min, max);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../helpers/cn.mjs";
|
|
3
3
|
import { ViewIcon, ViewOffIcon } from "../../icons/lucide.mjs";
|
|
4
|
+
import { useDisclosure } from "../../../hooks/disclosure/index.mjs";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { useState } from "react";
|
|
6
6
|
//#region src/components/form/password-input/password-input.tsx
|
|
7
7
|
const PasswordInput = ({ id, name, describedbyId, isInvalid, isDisabled, isRequired, placeholder, autoComplete = "current-password", showLabel = "Show password", hideLabel = "Hide password", defaultValue, value, onChange }) => {
|
|
8
|
-
const
|
|
8
|
+
const { isOpen: isVisible, toggle: toggleVisible } = useDisclosure();
|
|
9
9
|
return /* @__PURE__ */ jsxs("div", {
|
|
10
10
|
className: "relative w-full",
|
|
11
11
|
children: [/* @__PURE__ */ jsx("input", {
|
|
@@ -13,7 +13,7 @@ const PasswordInput = ({ id, name, describedbyId, isInvalid, isDisabled, isRequi
|
|
|
13
13
|
"aria-invalid": isInvalid,
|
|
14
14
|
"aria-required": isRequired,
|
|
15
15
|
autoComplete,
|
|
16
|
-
className: cn("w-full rounded-
|
|
16
|
+
className: cn("w-full rounded-xl border border-border-base bg-bg-base px-3 py-2 pr-12", "aria-invalid:border-border-error", "disabled:cursor-not-allowed disabled:border-border-mute disabled:bg-bg-mute disabled:hover:bg-bg-mute", "focus-visible:border-transparent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info"),
|
|
17
17
|
defaultValue,
|
|
18
18
|
disabled: isDisabled,
|
|
19
19
|
id,
|
|
@@ -27,9 +27,7 @@ const PasswordInput = ({ id, name, describedbyId, isInvalid, isDisabled, isRequi
|
|
|
27
27
|
"aria-label": isVisible ? hideLabel : showLabel,
|
|
28
28
|
className: cn("absolute top-1/2 right-2 inline-flex -translate-y-1/2 items-center justify-center rounded-md p-1 text-fg-mute transition-colors", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info", !isDisabled && "hover:bg-bg-mute hover:text-fg-base", isDisabled && "cursor-not-allowed text-fg-mute/70"),
|
|
29
29
|
disabled: isDisabled,
|
|
30
|
-
onClick:
|
|
31
|
-
setIsVisible((current) => !current);
|
|
32
|
-
},
|
|
30
|
+
onClick: toggleVisible,
|
|
33
31
|
type: "button",
|
|
34
32
|
children: isVisible ? /* @__PURE__ */ jsx(ViewOffIcon, { size: "sm" }) : /* @__PURE__ */ jsx(ViewIcon, { size: "sm" })
|
|
35
33
|
})]
|
|
@@ -3,7 +3,7 @@ import { cn } from "../../../helpers/cn.mjs";
|
|
|
3
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
//#region src/components/form/radio/radio.tsx
|
|
6
|
-
const Radio = ({ labelId, isDisabled, value, defaultValue, onChange, options }) => {
|
|
6
|
+
const Radio = ({ labelId, name, isDisabled, value, defaultValue, onChange, options }) => {
|
|
7
7
|
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
8
8
|
const isControlled = value !== void 0;
|
|
9
9
|
const selectedValue = isControlled ? value : internalValue;
|
|
@@ -23,7 +23,7 @@ const Radio = ({ labelId, isDisabled, value, defaultValue, onChange, options })
|
|
|
23
23
|
className: "peer sr-only",
|
|
24
24
|
defaultChecked: isControlled ? void 0 : defaultValue === option.value,
|
|
25
25
|
disabled: isDisabled,
|
|
26
|
-
name: labelId,
|
|
26
|
+
name: name ?? labelId,
|
|
27
27
|
onChange: () => {
|
|
28
28
|
selectValue(option.value);
|
|
29
29
|
},
|