@inzumer/ui-library 1.0.2 → 1.2.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/{chunk-HCLY7B4H.js → chunk-2YBZCUME.js} +39 -6
- package/dist/chunk-2YBZCUME.js.map +1 -0
- package/dist/{chunk-PVDRNAYK.js → chunk-3YRDRHO3.js} +33 -22
- package/dist/chunk-3YRDRHO3.js.map +1 -0
- package/dist/chunk-53YMHM24.js +20 -0
- package/dist/chunk-53YMHM24.js.map +1 -0
- package/dist/{chunk-LK2EJ4H6.js → chunk-A26UWAU4.js} +12 -6
- package/dist/chunk-A26UWAU4.js.map +1 -0
- package/dist/chunk-CX3GARWU.js +142 -0
- package/dist/chunk-CX3GARWU.js.map +1 -0
- package/dist/chunk-DP274HDM.js +34 -0
- package/dist/chunk-DP274HDM.js.map +1 -0
- package/dist/chunk-FFKHEBQ7.js +41 -0
- package/dist/chunk-FFKHEBQ7.js.map +1 -0
- package/dist/chunk-GQMA2AQI.js +3 -0
- package/dist/chunk-GQMA2AQI.js.map +1 -0
- package/dist/{chunk-KWSZ2S34.js → chunk-KL6I2JFC.js} +44 -13
- package/dist/chunk-KL6I2JFC.js.map +1 -0
- package/dist/chunk-QT62VC36.js +50 -0
- package/dist/chunk-QT62VC36.js.map +1 -0
- package/dist/{chunk-K35XIA25.js → chunk-RRIE5LFQ.js} +12 -6
- package/dist/chunk-RRIE5LFQ.js.map +1 -0
- package/dist/chunk-WUEVXL76.js +91 -0
- package/dist/chunk-WUEVXL76.js.map +1 -0
- package/dist/components/atoms/Button/index.d.ts +9 -1
- package/dist/components/atoms/Button/index.js +3 -1
- package/dist/components/atoms/Image/index.d.ts +2 -2
- package/dist/components/atoms/Input/index.d.ts +2 -2
- package/dist/components/atoms/Input/index.js +2 -1
- package/dist/components/atoms/RichText/index.d.ts +2 -2
- package/dist/components/atoms/Select/index.d.ts +29 -0
- package/dist/components/atoms/Select/index.js +6 -0
- package/dist/components/atoms/Select/index.js.map +1 -0
- package/dist/components/atoms/Switch/index.d.ts +1 -1
- package/dist/components/atoms/Textarea/index.d.ts +28 -0
- package/dist/components/atoms/Textarea/index.js +6 -0
- package/dist/components/atoms/Textarea/index.js.map +1 -0
- package/dist/components/molecules/BottomSheet/index.js +4 -2
- package/dist/components/molecules/Drawer/index.d.ts +44 -0
- package/dist/components/molecules/Drawer/index.js +11 -0
- package/dist/components/molecules/Drawer/index.js.map +1 -0
- package/dist/components/molecules/Language/index.d.ts +5 -0
- package/dist/components/molecules/Language/index.js +1 -1
- package/dist/components/molecules/Modal/index.js +4 -2
- package/dist/hooks/useFocusTrap/index.d.ts +9 -0
- package/dist/hooks/useFocusTrap/index.js +3 -0
- package/dist/hooks/useFocusTrap/index.js.map +1 -0
- package/dist/hooks/useScrollLock/index.d.ts +4 -0
- package/dist/hooks/useScrollLock/index.js +3 -0
- package/dist/hooks/useScrollLock/index.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +16 -9
- package/package.json +23 -3
- package/dist/chunk-HCLY7B4H.js.map +0 -1
- package/dist/chunk-K35XIA25.js.map +0 -1
- package/dist/chunk-KWSZ2S34.js.map +0 -1
- package/dist/chunk-LK2EJ4H6.js.map +0 -1
- package/dist/chunk-PVDRNAYK.js.map +0 -1
|
@@ -19,10 +19,14 @@ var languageOptionStyles = cva(
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
);
|
|
22
|
+
var NEXT_KEYS = /* @__PURE__ */ new Set(["ArrowRight", "ArrowDown"]);
|
|
23
|
+
var PREVIOUS_KEYS = /* @__PURE__ */ new Set(["ArrowLeft", "ArrowUp"]);
|
|
22
24
|
var Language = forwardRef(
|
|
23
25
|
({ options, value, onChange, className, ...props }, ref) => {
|
|
24
26
|
const buttonRefs = useRef(/* @__PURE__ */ new Map());
|
|
25
27
|
const [indicator, setIndicator] = useState(null);
|
|
28
|
+
const selectedIndex = options.findIndex((option) => option.value === value);
|
|
29
|
+
const focusableIndex = selectedIndex === -1 ? 0 : selectedIndex;
|
|
26
30
|
useLayoutEffect(() => {
|
|
27
31
|
const activeButton = buttonRefs.current.get(value);
|
|
28
32
|
if (!activeButton) {
|
|
@@ -35,11 +39,38 @@ var Language = forwardRef(
|
|
|
35
39
|
height: activeButton.offsetHeight
|
|
36
40
|
});
|
|
37
41
|
}, [value, options]);
|
|
42
|
+
const select = (index) => {
|
|
43
|
+
const option = options[index];
|
|
44
|
+
if (!option) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
buttonRefs.current.get(option.value)?.focus();
|
|
48
|
+
if (option.value !== value) {
|
|
49
|
+
onChange(option.value);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const handleKeyDown = (event) => {
|
|
53
|
+
const last = options.length - 1;
|
|
54
|
+
let target = null;
|
|
55
|
+
if (NEXT_KEYS.has(event.key)) {
|
|
56
|
+
target = focusableIndex === last ? 0 : focusableIndex + 1;
|
|
57
|
+
} else if (PREVIOUS_KEYS.has(event.key)) {
|
|
58
|
+
target = focusableIndex === 0 ? last : focusableIndex - 1;
|
|
59
|
+
} else if (event.key === "Home") {
|
|
60
|
+
target = 0;
|
|
61
|
+
} else if (event.key === "End") {
|
|
62
|
+
target = last;
|
|
63
|
+
}
|
|
64
|
+
if (target !== null) {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
select(target);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
38
69
|
return /* @__PURE__ */ jsxs(
|
|
39
70
|
"div",
|
|
40
71
|
{
|
|
41
72
|
ref,
|
|
42
|
-
role: "
|
|
73
|
+
role: "radiogroup",
|
|
43
74
|
"aria-label": "Language selector",
|
|
44
75
|
className: cn(languageStyles, className),
|
|
45
76
|
...props,
|
|
@@ -56,7 +87,7 @@ var Language = forwardRef(
|
|
|
56
87
|
}
|
|
57
88
|
}
|
|
58
89
|
),
|
|
59
|
-
options.map((option) => {
|
|
90
|
+
options.map((option, index) => {
|
|
60
91
|
const selected = option.value === value;
|
|
61
92
|
return /* @__PURE__ */ jsx(
|
|
62
93
|
"button",
|
|
@@ -69,9 +100,11 @@ var Language = forwardRef(
|
|
|
69
100
|
}
|
|
70
101
|
},
|
|
71
102
|
type: "button",
|
|
72
|
-
role: "
|
|
73
|
-
"aria-
|
|
103
|
+
role: "radio",
|
|
104
|
+
"aria-checked": selected,
|
|
105
|
+
tabIndex: index === focusableIndex ? 0 : -1,
|
|
74
106
|
onClick: () => onChange(option.value),
|
|
107
|
+
onKeyDown: handleKeyDown,
|
|
75
108
|
className: languageOptionStyles({ selected }),
|
|
76
109
|
children: option.label
|
|
77
110
|
},
|
|
@@ -86,5 +119,5 @@ var Language = forwardRef(
|
|
|
86
119
|
Language.displayName = "Language";
|
|
87
120
|
|
|
88
121
|
export { Language };
|
|
89
|
-
//# sourceMappingURL=chunk-
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
122
|
+
//# sourceMappingURL=chunk-2YBZCUME.js.map
|
|
123
|
+
//# sourceMappingURL=chunk-2YBZCUME.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/molecules/Language/Language.styles.ts","../src/components/molecules/Language/Language.tsx"],"names":[],"mappings":"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","file":"chunk-2YBZCUME.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const languageStyles =\n 'relative inline-flex items-center gap-1 rounded-md border border-[var(--border-default)] bg-[var(--surface-secondary)] p-1';\n\nexport const languageIndicatorStyles =\n 'absolute left-0 top-0 rounded bg-[var(--btn-primary-bg)] transition-[transform,width,height] duration-200 ease-out';\n\nexport const languageOptionStyles = cva(\n 'relative z-10 rounded px-2.5 py-1 text-xs font-semibold uppercase transition-colors duration-200 ease-out',\n {\n variants: {\n selected: {\n true: 'text-[var(--btn-primary-text)]',\n false: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)]',\n },\n },\n defaultVariants: {\n selected: false,\n },\n },\n);\n","import { cn } from '@utils';\nimport {\n forwardRef,\n useLayoutEffect,\n useRef,\n useState,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react';\nimport { languageIndicatorStyles, languageOptionStyles, languageStyles } from './Language.styles';\n\nexport interface LanguageOption {\n value: string;\n label: string;\n}\n\nexport type LanguageProps = Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> & {\n options: LanguageOption[];\n value: string;\n onChange: (value: string) => void;\n};\n\ntype IndicatorRect = { left: number; top: number; width: number; height: number };\n\nconst NEXT_KEYS = new Set(['ArrowRight', 'ArrowDown']);\nconst PREVIOUS_KEYS = new Set(['ArrowLeft', 'ArrowUp']);\n\n/**\n * Single-choice segmented switch, following the WAI-ARIA radio group pattern: one Tab stop,\n * arrow keys (and Home/End) move the selection. Name it with `aria-label` (defaults to\n * \"Language selector\") or `aria-labelledby`.\n */\nexport const Language = forwardRef<HTMLDivElement, LanguageProps>(\n ({ options, value, onChange, className, ...props }, ref) => {\n const buttonRefs = useRef(new Map<string, HTMLButtonElement>());\n const [indicator, setIndicator] = useState<IndicatorRect | null>(null);\n const selectedIndex = options.findIndex((option) => option.value === value);\n const focusableIndex = selectedIndex === -1 ? 0 : selectedIndex;\n\n useLayoutEffect(() => {\n const activeButton = buttonRefs.current.get(value);\n if (!activeButton) {\n return;\n }\n\n setIndicator({\n left: activeButton.offsetLeft,\n top: activeButton.offsetTop,\n width: activeButton.offsetWidth,\n height: activeButton.offsetHeight,\n });\n }, [value, options]);\n\n const select = (index: number) => {\n const option = options[index];\n if (!option) {\n return;\n }\n buttonRefs.current.get(option.value)?.focus();\n if (option.value !== value) {\n onChange(option.value);\n }\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n const last = options.length - 1;\n let target: number | null = null;\n if (NEXT_KEYS.has(event.key)) {\n target = focusableIndex === last ? 0 : focusableIndex + 1;\n } else if (PREVIOUS_KEYS.has(event.key)) {\n target = focusableIndex === 0 ? last : focusableIndex - 1;\n } else if (event.key === 'Home') {\n target = 0;\n } else if (event.key === 'End') {\n target = last;\n }\n if (target !== null) {\n event.preventDefault();\n select(target);\n }\n };\n\n return (\n <div\n ref={ref}\n role=\"radiogroup\"\n aria-label=\"Language selector\"\n className={cn(languageStyles, className)}\n {...props}\n >\n {indicator && (\n <span\n aria-hidden\n className={languageIndicatorStyles}\n style={{\n width: indicator.width,\n height: indicator.height,\n transform: `translate(${indicator.left}px, ${indicator.top}px)`,\n }}\n />\n )}\n {options.map((option, index) => {\n const selected = option.value === value;\n\n return (\n <button\n key={option.value}\n ref={(node) => {\n if (node) {\n buttonRefs.current.set(option.value, node);\n } else {\n buttonRefs.current.delete(option.value);\n }\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n tabIndex={index === focusableIndex ? 0 : -1}\n onClick={() => onChange(option.value)}\n onKeyDown={handleKeyDown}\n className={languageOptionStyles({ selected })}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n },\n);\n\nLanguage.displayName = 'Language';\n"]}
|
|
@@ -1,21 +1,20 @@
|
|
|
1
|
+
import { inputLabelStyles, inputErrorStyles, inputHintStyles } from './chunk-FFKHEBQ7.js';
|
|
1
2
|
import { RichText } from './chunk-P4CV2EPR.js';
|
|
2
3
|
import { cn } from './chunk-6LLGTBM6.js';
|
|
3
4
|
import { forwardRef, useId } from 'react';
|
|
4
5
|
import { cva } from 'class-variance-authority';
|
|
5
6
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
|
-
var
|
|
8
|
+
var textareaStyles = cva(
|
|
8
9
|
[
|
|
9
|
-
"flex w-full rounded-md px-3 py-2",
|
|
10
|
-
"text-
|
|
11
|
-
"bg-[var(--input-bg)]",
|
|
10
|
+
"flex min-h-24 w-full rounded-md px-3 py-2",
|
|
11
|
+
"text-[var(--input-text)] bg-[var(--input-bg)]",
|
|
12
12
|
"border border-[var(--input-border)]",
|
|
13
13
|
"placeholder:text-[var(--input-placeholder)]",
|
|
14
14
|
"transition-colors duration-150 ease-in-out",
|
|
15
15
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-0",
|
|
16
16
|
"focus-visible:border-[var(--input-border-focus)]",
|
|
17
|
-
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
18
|
-
"file:border-0 file:bg-transparent file:text-sm file:font-medium"
|
|
17
|
+
"disabled:cursor-not-allowed disabled:opacity-50"
|
|
19
18
|
],
|
|
20
19
|
{
|
|
21
20
|
variants: {
|
|
@@ -24,45 +23,57 @@ var inputStyles = cva(
|
|
|
24
23
|
error: "border-[var(--input-border-error)] focus-visible:ring-[var(--border-error)]"
|
|
25
24
|
},
|
|
26
25
|
inputSize: {
|
|
27
|
-
sm: "
|
|
28
|
-
md: "
|
|
29
|
-
lg: "
|
|
26
|
+
sm: "text-xs",
|
|
27
|
+
md: "text-sm",
|
|
28
|
+
lg: "text-base"
|
|
29
|
+
},
|
|
30
|
+
resize: {
|
|
31
|
+
vertical: "resize-y",
|
|
32
|
+
none: "resize-none"
|
|
30
33
|
}
|
|
31
34
|
},
|
|
32
35
|
defaultVariants: {
|
|
33
36
|
state: "default",
|
|
34
|
-
inputSize: "md"
|
|
37
|
+
inputSize: "md",
|
|
38
|
+
resize: "vertical"
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
);
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
var inputHintStyles = "text-xs text-[var(--text-secondary)]";
|
|
41
|
-
var Input = forwardRef(
|
|
42
|
-
({ className, state, inputSize, label, hint, error, id: idProp, ...props }, ref) => {
|
|
42
|
+
var Textarea = forwardRef(
|
|
43
|
+
({ className, state, inputSize, resize, label, hint, error, id: idProp, ...props }, ref) => {
|
|
43
44
|
const generatedId = useId();
|
|
44
45
|
const id = idProp ?? generatedId;
|
|
45
46
|
const resolvedState = error ? "error" : state;
|
|
46
47
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
47
48
|
label && /* @__PURE__ */ jsx("label", { htmlFor: id, children: /* @__PURE__ */ jsx(RichText, { as: "span", variant: "p3", className: inputLabelStyles, children: label }) }),
|
|
48
49
|
/* @__PURE__ */ jsx(
|
|
49
|
-
"
|
|
50
|
+
"textarea",
|
|
50
51
|
{
|
|
51
52
|
ref,
|
|
52
53
|
id,
|
|
53
54
|
"aria-describedby": error ? `${id}-error` : hint ? `${id}-hint` : void 0,
|
|
54
55
|
"aria-invalid": error ? "true" : void 0,
|
|
55
|
-
className: cn(
|
|
56
|
+
className: cn(textareaStyles({ state: resolvedState, inputSize, resize }), className),
|
|
56
57
|
...props
|
|
57
58
|
}
|
|
58
59
|
),
|
|
59
|
-
error && /* @__PURE__ */ jsx(
|
|
60
|
+
error && /* @__PURE__ */ jsx(
|
|
61
|
+
RichText,
|
|
62
|
+
{
|
|
63
|
+
as: "p",
|
|
64
|
+
id: `${id}-error`,
|
|
65
|
+
role: "alert",
|
|
66
|
+
variant: "p4",
|
|
67
|
+
className: inputErrorStyles,
|
|
68
|
+
children: error
|
|
69
|
+
}
|
|
70
|
+
),
|
|
60
71
|
!error && hint && /* @__PURE__ */ jsx(RichText, { as: "p", id: `${id}-hint`, variant: "p4", className: inputHintStyles, children: hint })
|
|
61
72
|
] });
|
|
62
73
|
}
|
|
63
74
|
);
|
|
64
|
-
|
|
75
|
+
Textarea.displayName = "Textarea";
|
|
65
76
|
|
|
66
|
-
export {
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
68
|
-
//# sourceMappingURL=chunk-
|
|
77
|
+
export { Textarea };
|
|
78
|
+
//# sourceMappingURL=chunk-3YRDRHO3.js.map
|
|
79
|
+
//# sourceMappingURL=chunk-3YRDRHO3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/atoms/Textarea/Textarea.styles.ts","../src/components/atoms/Textarea/Textarea.tsx"],"names":[],"mappings":";;;;;;;AAEO,IAAM,cAAA,GAAiB,GAAA;AAAA,EAC5B;AAAA,IACE,2CAAA;AAAA,IACA,+CAAA;AAAA,IACA,qCAAA;AAAA,IACA,6CAAA;AAAA,IACA,4CAAA;AAAA,IACA,sHAAA;AAAA,IACA,kDAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,EAAA;AAAA,QACT,KAAA,EAAO;AAAA,OACT;AAAA,MACA,SAAA,EAAW;AAAA,QACT,EAAA,EAAI,SAAA;AAAA,QACJ,EAAA,EAAI,SAAA;AAAA,QACJ,EAAA,EAAI;AAAA,OACN;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,QAAA,EAAU,UAAA;AAAA,QACV,IAAA,EAAM;AAAA;AACR,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,KAAA,EAAO,SAAA;AAAA,MACP,SAAA,EAAW,IAAA;AAAA,MACX,MAAA,EAAQ;AAAA;AACV;AAEJ,CAAA;AChBO,IAAM,QAAA,GAAW,UAAA;AAAA,EACtB,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,WAAW,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,GAAG,KAAA,IAAS,GAAA,KAAQ;AAC1F,IAAA,MAAM,cAAc,KAAA,EAAM;AAC1B,IAAA,MAAM,KAAK,MAAA,IAAU,WAAA;AACrB,IAAA,MAAM,aAAA,GAAgB,QAAQ,OAAA,GAAU,KAAA;AAExC,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,KAAA,oBACC,GAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAS,EAAA,EACd,QAAA,kBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,EAAA,EAAG,MAAA,EAAO,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,gBAAA,EACzC,iBACH,CAAA,EACF,CAAA;AAAA,sBAEF,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,EAAA;AAAA,UACA,kBAAA,EAAkB,QAAQ,CAAA,EAAG,EAAE,WAAW,IAAA,GAAO,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,GAAU,MAAA;AAAA,UAChE,cAAA,EAAc,QAAQ,MAAA,GAAS,MAAA;AAAA,UAC/B,SAAA,EAAW,EAAA,CAAG,cAAA,CAAe,EAAE,KAAA,EAAO,eAAe,SAAA,EAAW,MAAA,EAAQ,CAAA,EAAG,SAAS,CAAA;AAAA,UACnF,GAAG;AAAA;AAAA,OACN;AAAA,MACC,KAAA,oBACC,GAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,EAAA,EAAG,GAAA;AAAA,UACH,EAAA,EAAI,GAAG,EAAE,CAAA,MAAA,CAAA;AAAA,UACT,IAAA,EAAK,OAAA;AAAA,UACL,OAAA,EAAQ,IAAA;AAAA,UACR,SAAA,EAAW,gBAAA;AAAA,UAEV,QAAA,EAAA;AAAA;AAAA,OACH;AAAA,MAED,CAAC,KAAA,IAAS,IAAA,oBACT,GAAA,CAAC,YAAS,EAAA,EAAG,GAAA,EAAI,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,iBACxD,QAAA,EAAA,IAAA,EACH;AAAA,KAAA,EAEJ,CAAA;AAAA,EAEJ;AACF;AAEA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-3YRDRHO3.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const textareaStyles = cva(\n [\n 'flex min-h-24 w-full rounded-md px-3 py-2',\n 'text-[var(--input-text)] bg-[var(--input-bg)]',\n 'border border-[var(--input-border)]',\n 'placeholder:text-[var(--input-placeholder)]',\n 'transition-colors duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-0',\n 'focus-visible:border-[var(--input-border-focus)]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n ],\n {\n variants: {\n state: {\n default: '',\n error: 'border-[var(--input-border-error)] focus-visible:ring-[var(--border-error)]',\n },\n inputSize: {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n },\n resize: {\n vertical: 'resize-y',\n none: 'resize-none',\n },\n },\n defaultVariants: {\n state: 'default',\n inputSize: 'md',\n resize: 'vertical',\n },\n },\n);\n","import { RichText } from '@components';\nimport { cn } from '@utils';\nimport type { VariantProps } from 'class-variance-authority';\nimport { forwardRef, useId, type TextareaHTMLAttributes } from 'react';\nimport {\n inputErrorStyles,\n inputHintStyles,\n inputLabelStyles,\n} from '@components/atoms/Input/Input.styles';\nimport { textareaStyles } from './Textarea.styles';\n\nexport type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement> &\n VariantProps<typeof textareaStyles> & {\n label?: string;\n hint?: string;\n error?: string;\n };\n\n/** Multi-line text entry with the same label / hint / error contract and look as `Input`. */\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, state, inputSize, resize, label, hint, error, id: idProp, ...props }, ref) => {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const resolvedState = error ? 'error' : state;\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <label htmlFor={id}>\n <RichText as=\"span\" variant=\"p3\" className={inputLabelStyles}>\n {label}\n </RichText>\n </label>\n )}\n <textarea\n ref={ref}\n id={id}\n aria-describedby={error ? `${id}-error` : hint ? `${id}-hint` : undefined}\n aria-invalid={error ? 'true' : undefined}\n className={cn(textareaStyles({ state: resolvedState, inputSize, resize }), className)}\n {...props}\n />\n {error && (\n <RichText\n as=\"p\"\n id={`${id}-error`}\n role=\"alert\"\n variant=\"p4\"\n className={inputErrorStyles}\n >\n {error}\n </RichText>\n )}\n {!error && hint && (\n <RichText as=\"p\" id={`${id}-hint`} variant=\"p4\" className={inputHintStyles}>\n {hint}\n </RichText>\n )}\n </div>\n );\n },\n);\n\nTextarea.displayName = 'Textarea';\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/hooks/useScrollLock/useScrollLock.ts
|
|
4
|
+
var useScrollLock = (active) => {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (!active) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const { style } = document.body;
|
|
10
|
+
const previous = style.overflow;
|
|
11
|
+
style.overflow = "hidden";
|
|
12
|
+
return () => {
|
|
13
|
+
style.overflow = previous;
|
|
14
|
+
};
|
|
15
|
+
}, [active]);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { useScrollLock };
|
|
19
|
+
//# sourceMappingURL=chunk-53YMHM24.js.map
|
|
20
|
+
//# sourceMappingURL=chunk-53YMHM24.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useScrollLock/useScrollLock.ts"],"names":[],"mappings":";;;AAGO,IAAM,aAAA,GAAgB,CAAC,MAAA,KAA0B;AACtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA;AAAA,IACF;AACA,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,QAAA,CAAS,IAAA;AAC3B,IAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,IAAA,KAAA,CAAM,QAAA,GAAW,QAAA;AACjB,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,QAAA,GAAW,QAAA;AAAA,IACnB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb","file":"chunk-53YMHM24.js","sourcesContent":["import { useEffect } from 'react';\n\n/** Prevents the page behind an open overlay from scrolling; restores the previous value on release. */\nexport const useScrollLock = (active: boolean): void => {\n useEffect(() => {\n if (!active) {\n return;\n }\n const { style } = document.body;\n const previous = style.overflow;\n style.overflow = 'hidden';\n return () => {\n style.overflow = previous;\n };\n }, [active]);\n};\n"]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { useDelayedUnmount } from './chunk-BNEEI7S5.js';
|
|
1
2
|
import { useDismissableLayer } from './chunk-JCJP427C.js';
|
|
3
|
+
import { useFocusTrap } from './chunk-QT62VC36.js';
|
|
4
|
+
import { useScrollLock } from './chunk-53YMHM24.js';
|
|
2
5
|
import { useMergedRef } from './chunk-P4Z7HH66.js';
|
|
3
|
-
import { useDelayedUnmount } from './chunk-BNEEI7S5.js';
|
|
4
6
|
import { RichText } from './chunk-P4CV2EPR.js';
|
|
5
7
|
import { cn } from './chunk-6LLGTBM6.js';
|
|
6
|
-
import { forwardRef, useRef } from 'react';
|
|
8
|
+
import { forwardRef, useRef, useId } from 'react';
|
|
7
9
|
import { cva } from 'class-variance-authority';
|
|
8
10
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
11
|
|
|
@@ -48,8 +50,11 @@ var Modal = forwardRef(
|
|
|
48
50
|
({ open, onClose, title, footer, closeOnBackdropClick = true, className, children, ...props }, ref) => {
|
|
49
51
|
const panelRef = useRef(null);
|
|
50
52
|
const setPanelRef = useMergedRef(ref, panelRef);
|
|
53
|
+
const titleId = useId();
|
|
51
54
|
const { mounted, visible } = useDelayedUnmount(open, EXIT_DURATION_MS);
|
|
52
55
|
useDismissableLayer(open, onClose, panelRef, closeOnBackdropClick);
|
|
56
|
+
useFocusTrap(open && mounted, panelRef);
|
|
57
|
+
useScrollLock(open);
|
|
53
58
|
if (!mounted) {
|
|
54
59
|
return null;
|
|
55
60
|
}
|
|
@@ -59,11 +64,12 @@ var Modal = forwardRef(
|
|
|
59
64
|
ref: setPanelRef,
|
|
60
65
|
role: "dialog",
|
|
61
66
|
"aria-modal": "true",
|
|
62
|
-
"aria-labelledby": title ?
|
|
67
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
68
|
+
tabIndex: -1,
|
|
63
69
|
className: cn(modalPanelStyles({ visible }), className),
|
|
64
70
|
...props,
|
|
65
71
|
children: [
|
|
66
|
-
title && /* @__PURE__ */ jsx(RichText, { as: "h2", id:
|
|
72
|
+
title && /* @__PURE__ */ jsx(RichText, { as: "h2", id: titleId, variant: "s1", className: modalTitleStyles, children: title }),
|
|
67
73
|
children,
|
|
68
74
|
footer && /* @__PURE__ */ jsx("div", { className: modalFooterStyles, children: footer })
|
|
69
75
|
]
|
|
@@ -74,5 +80,5 @@ var Modal = forwardRef(
|
|
|
74
80
|
Modal.displayName = "Modal";
|
|
75
81
|
|
|
76
82
|
export { Modal };
|
|
77
|
-
//# sourceMappingURL=chunk-
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
83
|
+
//# sourceMappingURL=chunk-A26UWAU4.js.map
|
|
84
|
+
//# sourceMappingURL=chunk-A26UWAU4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/molecules/Modal/Modal.styles.ts","../src/components/molecules/Modal/Modal.tsx"],"names":[],"mappings":";;;;;;;;;;;AAEO,IAAM,kBAAA,GAAqB,GAAA;AAAA,EAChC;AAAA,IACE,qFAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,aAAA;AAAA,QACN,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS;AAAA;AACX;AAEJ,CAAA;AAEO,IAAM,gBAAA,GAAmB,GAAA;AAAA,EAC9B;AAAA,IACE,8GAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,uBAAA;AAAA,QACN,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS;AAAA;AACX;AAEJ,CAAA;AAEO,IAAM,gBAAA,GAAmB,uDAAA;AAEzB,IAAM,iBAAA,GAAoB,0CAAA;ACvBjC,IAAM,gBAAA,GAAmB,GAAA;AAUlB,IAAM,KAAA,GAAQ,UAAA;AAAA,EACnB,CACE,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,MAAA,EAAQ,oBAAA,GAAuB,IAAA,EAAM,SAAA,EAAW,QAAA,EAAU,GAAG,KAAA,IACrF,GAAA,KACG;AACH,IAAA,MAAM,QAAA,GAAW,OAA8B,IAAI,CAAA;AACnD,IAAA,MAAM,WAAA,GAAc,YAAA,CAAa,GAAA,EAAK,QAAQ,CAAA;AAC9C,IAAA,MAAM,UAAU,KAAA,EAAM;AACtB,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,iBAAA,CAAkB,MAAM,gBAAgB,CAAA;AAErE,IAAA,mBAAA,CAAoB,IAAA,EAAM,OAAA,EAAS,QAAA,EAAU,oBAAoB,CAAA;AAEjE,IAAA,YAAA,CAAa,IAAA,IAAQ,SAAS,QAAQ,CAAA;AACtC,IAAA,aAAA,CAAc,IAAI,CAAA;AAElB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,2BACG,KAAA,EAAA,EAAI,SAAA,EAAW,mBAAmB,EAAE,OAAA,EAAS,CAAA,EAC5C,QAAA,kBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,WAAA;AAAA,QACL,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,MAAA;AAAA,QACX,iBAAA,EAAiB,QAAQ,OAAA,GAAU,MAAA;AAAA,QACnC,QAAA,EAAU,EAAA;AAAA,QACV,WAAW,EAAA,CAAG,gBAAA,CAAiB,EAAE,OAAA,EAAS,GAAG,SAAS,CAAA;AAAA,QACrD,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,KAAA,oBACC,GAAA,CAAC,QAAA,EAAA,EAAS,EAAA,EAAG,IAAA,EAAK,EAAA,EAAI,SAAS,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,gBAAA,EACpD,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAED,QAAA;AAAA,UACA,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,mBAAoB,QAAA,EAAA,MAAA,EAAO;AAAA;AAAA;AAAA,KACxD,EACF,CAAA;AAAA,EAEJ;AACF;AAEA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"chunk-A26UWAU4.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const modalOverlayStyles = cva(\n [\n 'fixed inset-0 z-50 flex items-center justify-center bg-[var(--surface-overlay)] p-4',\n 'transition-opacity duration-200 ease-out',\n ],\n {\n variants: {\n visible: {\n true: 'opacity-100',\n false: 'opacity-0',\n },\n },\n defaultVariants: {\n visible: false,\n },\n },\n);\n\nexport const modalPanelStyles = cva(\n [\n 'w-full max-w-md rounded-xl border border-[var(--border-default)] bg-[var(--surface-secondary)] p-6 shadow-lg',\n 'transition-all duration-200 ease-out',\n ],\n {\n variants: {\n visible: {\n true: 'scale-100 opacity-100',\n false: 'scale-95 opacity-0',\n },\n },\n defaultVariants: {\n visible: false,\n },\n },\n);\n\nexport const modalTitleStyles = 'mb-4 text-lg font-semibold text-[var(--text-primary)]';\n\nexport const modalFooterStyles = 'mt-6 flex items-center justify-end gap-2';\n","import { forwardRef, useId, useRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { RichText } from '@components';\nimport {\n useDelayedUnmount,\n useDismissableLayer,\n useFocusTrap,\n useMergedRef,\n useScrollLock,\n} from '@hooks';\nimport { cn } from '@utils';\nimport {\n modalFooterStyles,\n modalOverlayStyles,\n modalPanelStyles,\n modalTitleStyles,\n} from './Modal.styles';\n\nconst EXIT_DURATION_MS = 200;\n\nexport type ModalProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n footer?: ReactNode;\n closeOnBackdropClick?: boolean;\n};\n\nexport const Modal = forwardRef<HTMLDivElement, ModalProps>(\n (\n { open, onClose, title, footer, closeOnBackdropClick = true, className, children, ...props },\n ref,\n ) => {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const setPanelRef = useMergedRef(ref, panelRef);\n const titleId = useId();\n const { mounted, visible } = useDelayedUnmount(open, EXIT_DURATION_MS);\n\n useDismissableLayer(open, onClose, panelRef, closeOnBackdropClick);\n // The panel mounts one render after `open` flips, so the trap starts once it exists.\n useFocusTrap(open && mounted, panelRef);\n useScrollLock(open);\n\n if (!mounted) {\n return null;\n }\n\n return (\n <div className={modalOverlayStyles({ visible })}>\n <div\n ref={setPanelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n tabIndex={-1}\n className={cn(modalPanelStyles({ visible }), className)}\n {...props}\n >\n {title && (\n <RichText as=\"h2\" id={titleId} variant=\"s1\" className={modalTitleStyles}>\n {title}\n </RichText>\n )}\n {children}\n {footer && <div className={modalFooterStyles}>{footer}</div>}\n </div>\n </div>\n );\n },\n);\n\nModal.displayName = 'Modal';\n"]}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { useDelayedUnmount } from './chunk-BNEEI7S5.js';
|
|
2
|
+
import { useDismissableLayer } from './chunk-JCJP427C.js';
|
|
3
|
+
import { useFocusTrap } from './chunk-QT62VC36.js';
|
|
4
|
+
import { useScrollLock } from './chunk-53YMHM24.js';
|
|
5
|
+
import { Button } from './chunk-KL6I2JFC.js';
|
|
6
|
+
import { useMergedRef } from './chunk-P4Z7HH66.js';
|
|
7
|
+
import { RichText } from './chunk-P4CV2EPR.js';
|
|
8
|
+
import { cn } from './chunk-6LLGTBM6.js';
|
|
9
|
+
import { forwardRef, useRef, useId } from 'react';
|
|
10
|
+
import { cva } from 'class-variance-authority';
|
|
11
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
var drawerOverlayStyles = cva(
|
|
14
|
+
"absolute inset-0 bg-[var(--surface-overlay)] transition-opacity duration-200 ease-out",
|
|
15
|
+
{
|
|
16
|
+
variants: {
|
|
17
|
+
visible: {
|
|
18
|
+
true: "opacity-100",
|
|
19
|
+
false: "opacity-0"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
visible: false
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
var drawerPanelStyles = cva(
|
|
28
|
+
[
|
|
29
|
+
"absolute inset-y-0 flex w-full max-w-80 flex-col gap-6 overflow-y-auto",
|
|
30
|
+
"border-[var(--border-default)] bg-[var(--surface-primary)] p-6 shadow-xl",
|
|
31
|
+
"transition-transform duration-200 ease-out focus:outline-none"
|
|
32
|
+
],
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
side: {
|
|
36
|
+
left: "left-0 border-r",
|
|
37
|
+
right: "right-0 border-l"
|
|
38
|
+
},
|
|
39
|
+
visible: {
|
|
40
|
+
true: "translate-x-0",
|
|
41
|
+
false: ""
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
compoundVariants: [
|
|
45
|
+
{ side: "left", visible: false, className: "-translate-x-full" },
|
|
46
|
+
{ side: "right", visible: false, className: "translate-x-full" }
|
|
47
|
+
],
|
|
48
|
+
defaultVariants: {
|
|
49
|
+
side: "right",
|
|
50
|
+
visible: false
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
var drawerHeaderStyles = "flex items-center justify-between gap-4";
|
|
55
|
+
var drawerTitleStyles = "text-lg font-semibold text-[var(--text-primary)]";
|
|
56
|
+
var drawerFooterStyles = "mt-auto flex flex-col gap-4";
|
|
57
|
+
var EXIT_DURATION_MS = 200;
|
|
58
|
+
var Drawer = forwardRef(
|
|
59
|
+
({
|
|
60
|
+
open,
|
|
61
|
+
onClose,
|
|
62
|
+
side,
|
|
63
|
+
title,
|
|
64
|
+
titleClassName,
|
|
65
|
+
closeLabel,
|
|
66
|
+
footer,
|
|
67
|
+
closeOnBackdropClick = true,
|
|
68
|
+
className,
|
|
69
|
+
children,
|
|
70
|
+
...props
|
|
71
|
+
}, ref) => {
|
|
72
|
+
const panelRef = useRef(null);
|
|
73
|
+
const setPanelRef = useMergedRef(ref, panelRef);
|
|
74
|
+
const titleId = useId();
|
|
75
|
+
const { mounted, visible } = useDelayedUnmount(open, EXIT_DURATION_MS);
|
|
76
|
+
useDismissableLayer(open, onClose, panelRef, closeOnBackdropClick);
|
|
77
|
+
useFocusTrap(open && mounted, panelRef);
|
|
78
|
+
useScrollLock(open);
|
|
79
|
+
if (!mounted) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50", children: [
|
|
83
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: drawerOverlayStyles({ visible }) }),
|
|
84
|
+
/* @__PURE__ */ jsxs(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
ref: setPanelRef,
|
|
88
|
+
role: "dialog",
|
|
89
|
+
"aria-modal": "true",
|
|
90
|
+
"aria-labelledby": title ? titleId : void 0,
|
|
91
|
+
tabIndex: -1,
|
|
92
|
+
className: cn(drawerPanelStyles({ side, visible }), className),
|
|
93
|
+
...props,
|
|
94
|
+
children: [
|
|
95
|
+
(title || closeLabel) && /* @__PURE__ */ jsxs("div", { className: drawerHeaderStyles, children: [
|
|
96
|
+
title && /* @__PURE__ */ jsx(
|
|
97
|
+
RichText,
|
|
98
|
+
{
|
|
99
|
+
as: "h2",
|
|
100
|
+
id: titleId,
|
|
101
|
+
variant: "s1",
|
|
102
|
+
className: cn(drawerTitleStyles, titleClassName),
|
|
103
|
+
children: title
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
closeLabel && /* @__PURE__ */ jsx(
|
|
107
|
+
Button,
|
|
108
|
+
{
|
|
109
|
+
variant: "ghost",
|
|
110
|
+
size: "icon",
|
|
111
|
+
"aria-label": closeLabel,
|
|
112
|
+
onClick: onClose,
|
|
113
|
+
className: "ml-auto size-11",
|
|
114
|
+
children: /* @__PURE__ */ jsx(
|
|
115
|
+
"svg",
|
|
116
|
+
{
|
|
117
|
+
"aria-hidden": true,
|
|
118
|
+
viewBox: "0 0 24 24",
|
|
119
|
+
fill: "none",
|
|
120
|
+
stroke: "currentColor",
|
|
121
|
+
strokeWidth: 2,
|
|
122
|
+
strokeLinecap: "round",
|
|
123
|
+
className: "size-6",
|
|
124
|
+
children: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M18 6L6 18" })
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] }),
|
|
130
|
+
children,
|
|
131
|
+
footer && /* @__PURE__ */ jsx("div", { className: drawerFooterStyles, children: footer })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
] });
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
Drawer.displayName = "Drawer";
|
|
139
|
+
|
|
140
|
+
export { Drawer };
|
|
141
|
+
//# sourceMappingURL=chunk-CX3GARWU.js.map
|
|
142
|
+
//# sourceMappingURL=chunk-CX3GARWU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/molecules/Drawer/Drawer.styles.ts","../src/components/molecules/Drawer/Drawer.tsx"],"names":[],"mappings":"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","file":"chunk-CX3GARWU.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const drawerOverlayStyles = cva(\n 'absolute inset-0 bg-[var(--surface-overlay)] transition-opacity duration-200 ease-out',\n {\n variants: {\n visible: {\n true: 'opacity-100',\n false: 'opacity-0',\n },\n },\n defaultVariants: {\n visible: false,\n },\n },\n);\n\nexport const drawerPanelStyles = cva(\n [\n 'absolute inset-y-0 flex w-full max-w-80 flex-col gap-6 overflow-y-auto',\n 'border-[var(--border-default)] bg-[var(--surface-primary)] p-6 shadow-xl',\n 'transition-transform duration-200 ease-out focus:outline-none',\n ],\n {\n variants: {\n side: {\n left: 'left-0 border-r',\n right: 'right-0 border-l',\n },\n visible: {\n true: 'translate-x-0',\n false: '',\n },\n },\n compoundVariants: [\n { side: 'left', visible: false, className: '-translate-x-full' },\n { side: 'right', visible: false, className: 'translate-x-full' },\n ],\n defaultVariants: {\n side: 'right',\n visible: false,\n },\n },\n);\n\nexport const drawerHeaderStyles = 'flex items-center justify-between gap-4';\n\nexport const drawerTitleStyles = 'text-lg font-semibold text-[var(--text-primary)]';\n\nexport const drawerFooterStyles = 'mt-auto flex flex-col gap-4';\n","import { Button, RichText } from '@components';\nimport {\n useDelayedUnmount,\n useDismissableLayer,\n useFocusTrap,\n useMergedRef,\n useScrollLock,\n} from '@hooks';\nimport { cn } from '@utils';\nimport type { VariantProps } from 'class-variance-authority';\nimport { forwardRef, useId, useRef, type HTMLAttributes, type ReactNode } from 'react';\nimport {\n drawerFooterStyles,\n drawerHeaderStyles,\n drawerOverlayStyles,\n drawerPanelStyles,\n drawerTitleStyles,\n} from './Drawer.styles';\n\nconst EXIT_DURATION_MS = 200;\n\nexport type DrawerProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> &\n Pick<VariantProps<typeof drawerPanelStyles>, 'side'> & {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n /** Extra classes for the title (e.g. a display font). */\n titleClassName?: string;\n /** Accessible name of the close button; the button is only rendered when this is set. */\n closeLabel?: string;\n /** Pinned to the bottom of the panel (preferences, actions). */\n footer?: ReactNode;\n closeOnBackdropClick?: boolean;\n };\n\n/**\n * A side panel (navigation menus, filters, settings) that slides in from the left or right.\n * Modal dialog semantics: focus moves inside and is trapped, Escape and backdrop clicks close it,\n * the page behind doesn't scroll, and focus returns to the trigger when it closes.\n */\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(\n (\n {\n open,\n onClose,\n side,\n title,\n titleClassName,\n closeLabel,\n footer,\n closeOnBackdropClick = true,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const panelRef = useRef<HTMLDivElement | null>(null);\n const setPanelRef = useMergedRef(ref, panelRef);\n const titleId = useId();\n const { mounted, visible } = useDelayedUnmount(open, EXIT_DURATION_MS);\n\n useDismissableLayer(open, onClose, panelRef, closeOnBackdropClick);\n // The panel mounts one render after `open` flips, so the trap starts once it exists.\n useFocusTrap(open && mounted, panelRef);\n useScrollLock(open);\n\n if (!mounted) {\n return null;\n }\n\n return (\n <div className=\"fixed inset-0 z-50\">\n <div aria-hidden=\"true\" className={drawerOverlayStyles({ visible })} />\n <div\n ref={setPanelRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n tabIndex={-1}\n className={cn(drawerPanelStyles({ side, visible }), className)}\n {...props}\n >\n {(title || closeLabel) && (\n <div className={drawerHeaderStyles}>\n {title && (\n <RichText\n as=\"h2\"\n id={titleId}\n variant=\"s1\"\n className={cn(drawerTitleStyles, titleClassName)}\n >\n {title}\n </RichText>\n )}\n {closeLabel && (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={closeLabel}\n onClick={onClose}\n className=\"ml-auto size-11\"\n >\n <svg\n aria-hidden\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n className=\"size-6\"\n >\n <path d=\"M6 6l12 12M18 6L6 18\" />\n </svg>\n </Button>\n )}\n </div>\n )}\n {children}\n {footer && <div className={drawerFooterStyles}>{footer}</div>}\n </div>\n </div>\n );\n },\n);\n\nDrawer.displayName = 'Drawer';\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { inputLabelStyles, inputStyles, inputErrorStyles, inputHintStyles } from './chunk-FFKHEBQ7.js';
|
|
2
|
+
import { RichText } from './chunk-P4CV2EPR.js';
|
|
3
|
+
import { cn } from './chunk-6LLGTBM6.js';
|
|
4
|
+
import { forwardRef, useId } from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var Input = forwardRef(
|
|
8
|
+
({ className, state, inputSize, label, hint, error, id: idProp, ...props }, ref) => {
|
|
9
|
+
const generatedId = useId();
|
|
10
|
+
const id = idProp ?? generatedId;
|
|
11
|
+
const resolvedState = error ? "error" : state;
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
13
|
+
label && /* @__PURE__ */ jsx("label", { htmlFor: id, children: /* @__PURE__ */ jsx(RichText, { as: "span", variant: "p3", className: inputLabelStyles, children: label }) }),
|
|
14
|
+
/* @__PURE__ */ jsx(
|
|
15
|
+
"input",
|
|
16
|
+
{
|
|
17
|
+
ref,
|
|
18
|
+
id,
|
|
19
|
+
"aria-describedby": error ? `${id}-error` : hint ? `${id}-hint` : void 0,
|
|
20
|
+
"aria-invalid": error ? "true" : void 0,
|
|
21
|
+
className: cn(inputStyles({ state: resolvedState, inputSize }), className),
|
|
22
|
+
...props
|
|
23
|
+
}
|
|
24
|
+
),
|
|
25
|
+
error && /* @__PURE__ */ jsx(RichText, { as: "p", id: `${id}-error`, role: "alert", variant: "p4", className: inputErrorStyles, children: error }),
|
|
26
|
+
!error && hint && /* @__PURE__ */ jsx(RichText, { as: "p", id: `${id}-hint`, variant: "p4", className: inputHintStyles, children: hint })
|
|
27
|
+
] });
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
Input.displayName = "Input";
|
|
31
|
+
|
|
32
|
+
export { Input };
|
|
33
|
+
//# sourceMappingURL=chunk-DP274HDM.js.map
|
|
34
|
+
//# sourceMappingURL=chunk-DP274HDM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/atoms/Input/Input.tsx"],"names":[],"mappings":";;;;;;AAkBO,IAAM,KAAA,GAAQ,UAAA;AAAA,EACnB,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,MAAA,EAAQ,GAAG,KAAA,IAAS,GAAA,KAAQ;AAClF,IAAA,MAAM,cAAc,KAAA,EAAM;AAC1B,IAAA,MAAM,KAAK,MAAA,IAAU,WAAA;AACrB,IAAA,MAAM,aAAA,GAAgB,QAAQ,OAAA,GAAU,KAAA;AAExC,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,KAAA,oBACC,GAAA,CAAC,OAAA,EAAA,EAAM,OAAA,EAAS,EAAA,EACd,QAAA,kBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,EAAA,EAAG,MAAA,EAAO,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,gBAAA,EACzC,iBACH,CAAA,EACF,CAAA;AAAA,sBAEF,GAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,EAAA;AAAA,UACA,kBAAA,EAAkB,QAAQ,CAAA,EAAG,EAAE,WAAW,IAAA,GAAO,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,GAAU,MAAA;AAAA,UAChE,cAAA,EAAc,QAAQ,MAAA,GAAS,MAAA;AAAA,UAC/B,SAAA,EAAW,GAAG,WAAA,CAAY,EAAE,OAAO,aAAA,EAAe,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA;AAAA,UACxE,GAAG;AAAA;AAAA,OACN;AAAA,MACC,KAAA,oBACC,GAAA,CAAC,QAAA,EAAA,EAAS,EAAA,EAAG,KAAI,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,MAAK,OAAA,EAAQ,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,kBACtE,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,MAED,CAAC,KAAA,IAAS,IAAA,oBACT,GAAA,CAAC,YAAS,EAAA,EAAG,GAAA,EAAI,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,OAAA,EAAQ,IAAA,EAAK,SAAA,EAAW,iBACxD,QAAA,EAAA,IAAA,EACH;AAAA,KAAA,EAEJ,CAAA;AAAA,EAEJ;AACF;AAEA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"chunk-DP274HDM.js","sourcesContent":["import type { VariantProps } from 'class-variance-authority';\nimport { forwardRef, useId, type InputHTMLAttributes } from 'react';\nimport { RichText } from '@components';\nimport { cn } from '@utils';\nimport {\n inputErrorStyles,\n inputHintStyles,\n inputLabelStyles,\n inputStyles,\n} from './Input.styles';\n\nexport type InputProps = InputHTMLAttributes<HTMLInputElement> &\n VariantProps<typeof inputStyles> & {\n label?: string;\n hint?: string;\n error?: string;\n };\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n ({ className, state, inputSize, label, hint, error, id: idProp, ...props }, ref) => {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const resolvedState = error ? 'error' : state;\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <label htmlFor={id}>\n <RichText as=\"span\" variant=\"p3\" className={inputLabelStyles}>\n {label}\n </RichText>\n </label>\n )}\n <input\n ref={ref}\n id={id}\n aria-describedby={error ? `${id}-error` : hint ? `${id}-hint` : undefined}\n aria-invalid={error ? 'true' : undefined}\n className={cn(inputStyles({ state: resolvedState, inputSize }), className)}\n {...props}\n />\n {error && (\n <RichText as=\"p\" id={`${id}-error`} role=\"alert\" variant=\"p4\" className={inputErrorStyles}>\n {error}\n </RichText>\n )}\n {!error && hint && (\n <RichText as=\"p\" id={`${id}-hint`} variant=\"p4\" className={inputHintStyles}>\n {hint}\n </RichText>\n )}\n </div>\n );\n },\n);\n\nInput.displayName = 'Input';\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
// src/components/atoms/Input/Input.styles.ts
|
|
4
|
+
var inputStyles = cva(
|
|
5
|
+
[
|
|
6
|
+
"flex w-full rounded-md px-3 py-2",
|
|
7
|
+
"text-sm text-[var(--input-text)]",
|
|
8
|
+
"bg-[var(--input-bg)]",
|
|
9
|
+
"border border-[var(--input-border)]",
|
|
10
|
+
"placeholder:text-[var(--input-placeholder)]",
|
|
11
|
+
"transition-colors duration-150 ease-in-out",
|
|
12
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-0",
|
|
13
|
+
"focus-visible:border-[var(--input-border-focus)]",
|
|
14
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
15
|
+
"file:border-0 file:bg-transparent file:text-sm file:font-medium"
|
|
16
|
+
],
|
|
17
|
+
{
|
|
18
|
+
variants: {
|
|
19
|
+
state: {
|
|
20
|
+
default: "",
|
|
21
|
+
error: "border-[var(--input-border-error)] focus-visible:ring-[var(--border-error)]"
|
|
22
|
+
},
|
|
23
|
+
inputSize: {
|
|
24
|
+
sm: "h-8 px-2 text-xs",
|
|
25
|
+
md: "h-10 px-3 text-sm",
|
|
26
|
+
lg: "h-12 px-4 text-base"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
state: "default",
|
|
31
|
+
inputSize: "md"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
var inputLabelStyles = "text-sm font-medium text-[var(--text-primary)]";
|
|
36
|
+
var inputErrorStyles = "text-xs text-[var(--border-error)]";
|
|
37
|
+
var inputHintStyles = "text-xs text-[var(--text-secondary)]";
|
|
38
|
+
|
|
39
|
+
export { inputErrorStyles, inputHintStyles, inputLabelStyles, inputStyles };
|
|
40
|
+
//# sourceMappingURL=chunk-FFKHEBQ7.js.map
|
|
41
|
+
//# sourceMappingURL=chunk-FFKHEBQ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/atoms/Input/Input.styles.ts"],"names":[],"mappings":";;;AAEO,IAAM,WAAA,GAAc,GAAA;AAAA,EACzB;AAAA,IACE,kCAAA;AAAA,IACA,kCAAA;AAAA,IACA,sBAAA;AAAA,IACA,qCAAA;AAAA,IACA,6CAAA;AAAA,IACA,4CAAA;AAAA,IACA,sHAAA;AAAA,IACA,kDAAA;AAAA,IACA,iDAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,EAAA;AAAA,QACT,KAAA,EAAO;AAAA,OACT;AAAA,MACA,SAAA,EAAW;AAAA,QACT,EAAA,EAAI,kBAAA;AAAA,QACJ,EAAA,EAAI,mBAAA;AAAA,QACJ,EAAA,EAAI;AAAA;AACN,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,KAAA,EAAO,SAAA;AAAA,MACP,SAAA,EAAW;AAAA;AACb;AAEJ;AAEO,IAAM,gBAAA,GAAmB;AACzB,IAAM,gBAAA,GAAmB;AACzB,IAAM,eAAA,GAAkB","file":"chunk-FFKHEBQ7.js","sourcesContent":["import { cva } from 'class-variance-authority';\n\nexport const inputStyles = cva(\n [\n 'flex w-full rounded-md px-3 py-2',\n 'text-sm text-[var(--input-text)]',\n 'bg-[var(--input-bg)]',\n 'border border-[var(--input-border)]',\n 'placeholder:text-[var(--input-placeholder)]',\n 'transition-colors duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--border-focus)] focus-visible:ring-offset-0',\n 'focus-visible:border-[var(--input-border-focus)]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n 'file:border-0 file:bg-transparent file:text-sm file:font-medium',\n ],\n {\n variants: {\n state: {\n default: '',\n error: 'border-[var(--input-border-error)] focus-visible:ring-[var(--border-error)]',\n },\n inputSize: {\n sm: 'h-8 px-2 text-xs',\n md: 'h-10 px-3 text-sm',\n lg: 'h-12 px-4 text-base',\n },\n },\n defaultVariants: {\n state: 'default',\n inputSize: 'md',\n },\n },\n);\n\nexport const inputLabelStyles = 'text-sm font-medium text-[var(--text-primary)]';\nexport const inputErrorStyles = 'text-xs text-[var(--border-error)]';\nexport const inputHintStyles = 'text-xs text-[var(--text-secondary)]';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-GQMA2AQI.js"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { useMergedRef } from './chunk-P4Z7HH66.js';
|
|
1
2
|
import { cn } from './chunk-6LLGTBM6.js';
|
|
2
|
-
import { forwardRef } from 'react';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { forwardRef, Children, isValidElement, cloneElement } from 'react';
|
|
4
5
|
import { jsx } from 'react/jsx-runtime';
|
|
5
6
|
|
|
6
7
|
var buttonStyles = cva(
|
|
@@ -57,20 +58,50 @@ var buttonStyles = cva(
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
);
|
|
61
|
+
var isHandler = (key, value) => /^on[A-Z]/.test(key) && typeof value === "function";
|
|
62
|
+
var mergeProps = (slotProps, childProps) => {
|
|
63
|
+
const merged = { ...slotProps, ...childProps };
|
|
64
|
+
for (const [key, slotValue] of Object.entries(slotProps)) {
|
|
65
|
+
const childValue = childProps[key];
|
|
66
|
+
if (isHandler(key, slotValue) && isHandler(key, childValue)) {
|
|
67
|
+
merged[key] = (...args) => {
|
|
68
|
+
childValue(...args);
|
|
69
|
+
slotValue(...args);
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
merged["className"] = cn(slotProps["className"], childProps["className"]);
|
|
74
|
+
merged["style"] = {
|
|
75
|
+
...slotProps["style"],
|
|
76
|
+
...childProps["style"]
|
|
77
|
+
};
|
|
78
|
+
return merged;
|
|
79
|
+
};
|
|
80
|
+
var Slot = forwardRef(
|
|
81
|
+
({ children, ...slotProps }, forwardedRef) => {
|
|
82
|
+
const child = Children.count(children) === 1 ? Children.toArray(children)[0] : null;
|
|
83
|
+
const childProps = isValidElement(child) ? child.props : {};
|
|
84
|
+
const childRef = childProps["ref"] ?? child?.ref;
|
|
85
|
+
const ref = useMergedRef(forwardedRef, childRef);
|
|
86
|
+
if (!isValidElement(child)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return cloneElement(child, { ...mergeProps(slotProps, childProps), ref });
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
Slot.displayName = "Slot";
|
|
60
93
|
var Button = forwardRef(
|
|
61
|
-
({ className, variant, size, fullWidth, ...props }, ref) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
);
|
|
94
|
+
({ className, variant, size, fullWidth, asChild = false, ...props }, ref) => {
|
|
95
|
+
const classes = cn(buttonStyles({ variant, size, fullWidth }), className);
|
|
96
|
+
if (asChild) {
|
|
97
|
+
const slotRef = ref;
|
|
98
|
+
return /* @__PURE__ */ jsx(Slot, { ref: slotRef, className: classes, ...props });
|
|
99
|
+
}
|
|
100
|
+
return /* @__PURE__ */ jsx("button", { ref, className: classes, ...props });
|
|
70
101
|
}
|
|
71
102
|
);
|
|
72
103
|
Button.displayName = "Button";
|
|
73
104
|
|
|
74
|
-
export { Button };
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
76
|
-
//# sourceMappingURL=chunk-
|
|
105
|
+
export { Button, buttonStyles };
|
|
106
|
+
//# sourceMappingURL=chunk-KL6I2JFC.js.map
|
|
107
|
+
//# sourceMappingURL=chunk-KL6I2JFC.js.map
|