@tribepad/themis 1.0.1 → 1.0.2
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/elements/Accordion/index.js +1 -335
- package/dist/elements/Accordion/index.js.map +1 -1
- package/dist/elements/Accordion/index.mjs +1 -317
- package/dist/elements/Accordion/index.mjs.map +1 -1
- package/dist/elements/AlertDialog/AlertDialog.d.ts +43 -0
- package/dist/elements/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/dist/elements/AlertDialog/AlertDialog.styles.d.ts +15 -0
- package/dist/elements/AlertDialog/AlertDialog.styles.d.ts.map +1 -0
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts +72 -0
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts.map +1 -0
- package/dist/elements/AlertDialog/index.d.ts +25 -0
- package/dist/elements/AlertDialog/index.d.ts.map +1 -0
- package/dist/elements/AlertDialog/index.js +3 -0
- package/dist/elements/AlertDialog/index.js.map +1 -0
- package/dist/elements/AlertDialog/index.mjs +3 -0
- package/dist/elements/AlertDialog/index.mjs.map +1 -0
- package/dist/elements/Avatar/index.js +1 -468
- package/dist/elements/Avatar/index.js.map +1 -1
- package/dist/elements/Avatar/index.mjs +1 -456
- package/dist/elements/Avatar/index.mjs.map +1 -1
- package/dist/elements/Badge/index.js +1 -243
- package/dist/elements/Badge/index.js.map +1 -1
- package/dist/elements/Badge/index.mjs +1 -234
- package/dist/elements/Badge/index.mjs.map +1 -1
- package/dist/elements/Breadcrumbs/index.js +1 -821
- package/dist/elements/Breadcrumbs/index.js.map +1 -1
- package/dist/elements/Breadcrumbs/index.mjs +1 -810
- package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
- package/dist/elements/Button/Button.d.ts +26 -81
- package/dist/elements/Button/Button.d.ts.map +1 -1
- package/dist/elements/Button/Button.styles.d.ts +35 -0
- package/dist/elements/Button/Button.styles.d.ts.map +1 -0
- package/dist/elements/Button/Button.types.d.ts +20 -8
- package/dist/elements/Button/Button.types.d.ts.map +1 -1
- package/dist/elements/Button/index.js +1 -288
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/Button/index.mjs +1 -283
- package/dist/elements/Button/index.mjs.map +1 -1
- package/dist/elements/ButtonGroup/index.js +1 -237
- package/dist/elements/ButtonGroup/index.js.map +1 -1
- package/dist/elements/ButtonGroup/index.mjs +1 -222
- package/dist/elements/ButtonGroup/index.mjs.map +1 -1
- package/dist/elements/Card/index.js +1 -579
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/Card/index.mjs +1 -560
- package/dist/elements/Card/index.mjs.map +1 -1
- package/dist/elements/Carousel/Carousel.d.ts +1 -11
- package/dist/elements/Carousel/Carousel.d.ts.map +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -1
- package/dist/elements/Carousel/index.js +1 -789
- package/dist/elements/Carousel/index.js.map +1 -1
- package/dist/elements/Carousel/index.mjs +1 -786
- package/dist/elements/Carousel/index.mjs.map +1 -1
- package/dist/elements/Chart/ChartContext.d.ts.map +1 -1
- package/dist/elements/Chart/index.js +1 -1842
- package/dist/elements/Chart/index.js.map +1 -1
- package/dist/elements/Chart/index.mjs +1 -1832
- package/dist/elements/Chart/index.mjs.map +1 -1
- package/dist/elements/Checkbox/index.js +1 -316
- package/dist/elements/Checkbox/index.js.map +1 -1
- package/dist/elements/Checkbox/index.mjs +1 -306
- package/dist/elements/Checkbox/index.mjs.map +1 -1
- package/dist/elements/CheckboxGroup/index.js +1 -455
- package/dist/elements/CheckboxGroup/index.js.map +1 -1
- package/dist/elements/CheckboxGroup/index.mjs +1 -439
- package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
- package/dist/elements/Combobox/Combobox.d.ts +56 -0
- package/dist/elements/Combobox/Combobox.d.ts.map +1 -0
- package/dist/elements/Combobox/Combobox.styles.d.ts +29 -0
- package/dist/elements/Combobox/Combobox.styles.d.ts.map +1 -0
- package/dist/elements/Combobox/Combobox.types.d.ts +67 -0
- package/dist/elements/Combobox/Combobox.types.d.ts.map +1 -0
- package/dist/elements/Combobox/index.d.ts +20 -0
- package/dist/elements/Combobox/index.d.ts.map +1 -0
- package/dist/elements/Combobox/index.js +3 -0
- package/dist/elements/Combobox/index.js.map +1 -0
- package/dist/elements/Combobox/index.mjs +3 -0
- package/dist/elements/Combobox/index.mjs.map +1 -0
- package/dist/elements/DatePicker/DatePicker.d.ts +1 -1
- package/dist/elements/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/elements/DatePicker/index.js +1 -903
- package/dist/elements/DatePicker/index.js.map +1 -1
- package/dist/elements/DatePicker/index.mjs +1 -853
- package/dist/elements/DatePicker/index.mjs.map +1 -1
- package/dist/elements/Dropdown/Dropdown.d.ts +7 -15
- package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/elements/Dropdown/Dropdown.styles.d.ts +22 -0
- package/dist/elements/Dropdown/Dropdown.styles.d.ts.map +1 -0
- package/dist/elements/Dropdown/index.d.ts +1 -0
- package/dist/elements/Dropdown/index.d.ts.map +1 -1
- package/dist/elements/Dropdown/index.js +1 -193
- package/dist/elements/Dropdown/index.js.map +1 -1
- package/dist/elements/Dropdown/index.mjs +1 -184
- package/dist/elements/Dropdown/index.mjs.map +1 -1
- package/dist/elements/FileField/index.js +1 -1539
- package/dist/elements/FileField/index.js.map +1 -1
- package/dist/elements/FileField/index.mjs +1 -1507
- package/dist/elements/FileField/index.mjs.map +1 -1
- package/dist/elements/FormLayout/index.js +1 -170
- package/dist/elements/FormLayout/index.js.map +1 -1
- package/dist/elements/FormLayout/index.mjs +1 -167
- package/dist/elements/FormLayout/index.mjs.map +1 -1
- package/dist/elements/Modal/Modal.d.ts +9 -14
- package/dist/elements/Modal/Modal.d.ts.map +1 -1
- package/dist/elements/Modal/Modal.styles.d.ts +29 -0
- package/dist/elements/Modal/Modal.styles.d.ts.map +1 -0
- package/dist/elements/Modal/index.d.ts +1 -0
- package/dist/elements/Modal/index.d.ts.map +1 -1
- package/dist/elements/Modal/index.js +1 -232
- package/dist/elements/Modal/index.js.map +1 -1
- package/dist/elements/Modal/index.mjs +1 -220
- package/dist/elements/Modal/index.mjs.map +1 -1
- package/dist/elements/NumberField/index.js +1 -666
- package/dist/elements/NumberField/index.js.map +1 -1
- package/dist/elements/NumberField/index.mjs +1 -654
- package/dist/elements/NumberField/index.mjs.map +1 -1
- package/dist/elements/OTPInput/OTPInput.d.ts.map +1 -1
- package/dist/elements/OTPInput/index.js +1 -734
- package/dist/elements/OTPInput/index.js.map +1 -1
- package/dist/elements/OTPInput/index.mjs +1 -732
- package/dist/elements/OTPInput/index.mjs.map +1 -1
- package/dist/elements/Pagination/Pagination.d.ts +45 -0
- package/dist/elements/Pagination/Pagination.d.ts.map +1 -0
- package/dist/elements/Pagination/Pagination.styles.d.ts +10 -0
- package/dist/elements/Pagination/Pagination.styles.d.ts.map +1 -0
- package/dist/elements/Pagination/Pagination.types.d.ts +55 -0
- package/dist/elements/Pagination/Pagination.types.d.ts.map +1 -0
- package/dist/elements/Pagination/index.d.ts +21 -0
- package/dist/elements/Pagination/index.d.ts.map +1 -0
- package/dist/elements/Pagination/index.js +3 -0
- package/dist/elements/Pagination/index.js.map +1 -0
- package/dist/elements/Pagination/index.mjs +3 -0
- package/dist/elements/Pagination/index.mjs.map +1 -0
- package/dist/elements/Panel/index.js +1 -330
- package/dist/elements/Panel/index.js.map +1 -1
- package/dist/elements/Panel/index.mjs +1 -323
- package/dist/elements/Panel/index.mjs.map +1 -1
- package/dist/elements/PasswordField/PasswordField.d.ts +27 -0
- package/dist/elements/PasswordField/PasswordField.d.ts.map +1 -0
- package/dist/elements/PasswordField/PasswordField.styles.d.ts +32 -0
- package/dist/elements/PasswordField/PasswordField.styles.d.ts.map +1 -0
- package/dist/elements/PasswordField/PasswordField.types.d.ts +100 -0
- package/dist/elements/PasswordField/PasswordField.types.d.ts.map +1 -0
- package/dist/elements/PasswordField/index.css +2 -0
- package/dist/elements/PasswordField/index.css.map +1 -0
- package/dist/elements/PasswordField/index.d.ts +20 -0
- package/dist/elements/PasswordField/index.d.ts.map +1 -0
- package/dist/elements/PasswordField/index.js +3 -0
- package/dist/elements/PasswordField/index.js.map +1 -0
- package/dist/elements/PasswordField/index.mjs +3 -0
- package/dist/elements/PasswordField/index.mjs.map +1 -0
- package/dist/elements/Progress/index.js +1 -187
- package/dist/elements/Progress/index.js.map +1 -1
- package/dist/elements/Progress/index.mjs +1 -181
- package/dist/elements/Progress/index.mjs.map +1 -1
- package/dist/elements/RadioGroup/index.js +1 -369
- package/dist/elements/RadioGroup/index.js.map +1 -1
- package/dist/elements/RadioGroup/index.mjs +1 -359
- package/dist/elements/RadioGroup/index.mjs.map +1 -1
- package/dist/elements/Resizable/index.js +1 -1580
- package/dist/elements/Resizable/index.js.map +1 -1
- package/dist/elements/Resizable/index.mjs +1 -1566
- package/dist/elements/Resizable/index.mjs.map +1 -1
- package/dist/elements/SearchField/SearchField.d.ts +27 -0
- package/dist/elements/SearchField/SearchField.d.ts.map +1 -0
- package/dist/elements/SearchField/SearchField.styles.d.ts +32 -0
- package/dist/elements/SearchField/SearchField.styles.d.ts.map +1 -0
- package/dist/elements/SearchField/SearchField.types.d.ts +45 -0
- package/dist/elements/SearchField/SearchField.types.d.ts.map +1 -0
- package/dist/elements/SearchField/index.css +2 -0
- package/dist/elements/SearchField/index.css.map +1 -0
- package/dist/elements/SearchField/index.d.ts +21 -0
- package/dist/elements/SearchField/index.d.ts.map +1 -0
- package/dist/elements/SearchField/index.js +3 -0
- package/dist/elements/SearchField/index.js.map +1 -0
- package/dist/elements/SearchField/index.mjs +3 -0
- package/dist/elements/SearchField/index.mjs.map +1 -0
- package/dist/elements/Select/Select.d.ts +19 -48
- package/dist/elements/Select/Select.d.ts.map +1 -1
- package/dist/elements/Select/Select.styles.d.ts +55 -0
- package/dist/elements/Select/Select.styles.d.ts.map +1 -0
- package/dist/elements/Select/index.js +1 -589
- package/dist/elements/Select/index.js.map +1 -1
- package/dist/elements/Select/index.mjs +1 -582
- package/dist/elements/Select/index.mjs.map +1 -1
- package/dist/elements/Skeleton/index.js +1 -82
- package/dist/elements/Skeleton/index.js.map +1 -1
- package/dist/elements/Skeleton/index.mjs +1 -78
- package/dist/elements/Skeleton/index.mjs.map +1 -1
- package/dist/elements/Switch/index.js +1 -179
- package/dist/elements/Switch/index.js.map +1 -1
- package/dist/elements/Switch/index.mjs +1 -173
- package/dist/elements/Switch/index.mjs.map +1 -1
- package/dist/elements/Table/Table.d.ts +3 -24
- package/dist/elements/Table/Table.d.ts.map +1 -1
- package/dist/elements/Table/Table.styles.d.ts +24 -0
- package/dist/elements/Table/Table.styles.d.ts.map +1 -0
- package/dist/elements/Table/index.js +1 -595
- package/dist/elements/Table/index.js.map +1 -1
- package/dist/elements/Table/index.mjs +1 -578
- package/dist/elements/Table/index.mjs.map +1 -1
- package/dist/elements/Tabs/index.js +1 -337
- package/dist/elements/Tabs/index.js.map +1 -1
- package/dist/elements/Tabs/index.mjs +1 -320
- package/dist/elements/Tabs/index.mjs.map +1 -1
- package/dist/elements/TextField/TextField.d.ts +6 -42
- package/dist/elements/TextField/TextField.d.ts.map +1 -1
- package/dist/elements/TextField/TextField.hooks.d.ts +63 -0
- package/dist/elements/TextField/TextField.hooks.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.icons.d.ts +19 -0
- package/dist/elements/TextField/TextField.icons.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.styles.d.ts +37 -0
- package/dist/elements/TextField/TextField.styles.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.types.d.ts +3 -0
- package/dist/elements/TextField/TextField.types.d.ts.map +1 -1
- package/dist/elements/TextField/index.css +1 -22
- package/dist/elements/TextField/index.css.map +1 -1
- package/dist/elements/TextField/index.js +1 -902
- package/dist/elements/TextField/index.js.map +1 -1
- package/dist/elements/TextField/index.mjs +1 -882
- package/dist/elements/TextField/index.mjs.map +1 -1
- package/dist/elements/TimeField/index.js +1 -254
- package/dist/elements/TimeField/index.js.map +1 -1
- package/dist/elements/TimeField/index.mjs +1 -238
- package/dist/elements/TimeField/index.mjs.map +1 -1
- package/dist/elements/Toast/Toast.d.ts +0 -22
- package/dist/elements/Toast/Toast.d.ts.map +1 -1
- package/dist/elements/Toast/index.js +1 -737
- package/dist/elements/Toast/index.js.map +1 -1
- package/dist/elements/Toast/index.mjs +1 -724
- package/dist/elements/Toast/index.mjs.map +1 -1
- package/dist/elements/Tooltip/index.js +1 -323
- package/dist/elements/Tooltip/index.js.map +1 -1
- package/dist/elements/Tooltip/index.mjs +1 -310
- package/dist/elements/Tooltip/index.mjs.map +1 -1
- package/dist/elements/index.css +1 -22
- package/dist/elements/index.css.map +1 -1
- package/dist/elements/index.d.ts +13 -1
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +1 -12455
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -12233
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.css +1 -22
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -12490
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -12262
- package/dist/index.mjs.map +1 -1
- package/dist/schemas/index.js +2 -54
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/index.mjs +2 -48
- package/dist/schemas/index.mjs.map +1 -1
- package/dist/styles/defaults.css +151 -0
- package/dist/styles/index.js +1 -166
- package/dist/styles/index.js.map +1 -1
- package/dist/styles/index.mjs +1 -129
- package/dist/styles/index.mjs.map +1 -1
- package/dist/utils/index.js +1 -12
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +1 -10
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +9 -7
- package/src/elements/Accordion/Accordion.stories.tsx +1 -1
- package/src/elements/AlertDialog/AlertDialog.stories.tsx +124 -0
- package/src/elements/Avatar/Avatar.stories.tsx +1 -1
- package/src/elements/Badge/Badge.stories.tsx +1 -1
- package/src/elements/Breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/elements/Button/Button.stories.tsx +1 -1
- package/src/elements/ButtonGroup/ButtonGroup.stories.tsx +1 -1
- package/src/elements/Card/Card.stories.tsx +1 -1
- package/src/elements/Carousel/Carousel.stories.tsx +1 -1
- package/src/elements/Chart/Chart.stories.tsx +1 -1
- package/src/elements/Checkbox/Checkbox.stories.tsx +1 -1
- package/src/elements/CheckboxGroup/CheckboxGroup.stories.tsx +1 -1
- package/src/elements/Combobox/Combobox.stories.tsx +133 -0
- package/src/elements/DatePicker/DatePicker.stories.tsx +1 -1
- package/src/elements/Dropdown/Dropdown.stories.tsx +1 -1
- package/src/elements/FileField/FileField.stories.tsx +1 -1
- package/src/elements/FileField/FileProgress.stories.tsx +1 -1
- package/src/elements/FormLayout/FormLayout.stories.tsx +1 -1
- package/src/elements/Modal/Modal.stories.tsx +1 -1
- package/src/elements/NumberField/NumberField.stories.tsx +1 -1
- package/src/elements/OTPInput/OTPInput.stories.tsx +1 -1
- package/src/elements/Pagination/Pagination.stories.tsx +203 -0
- package/src/elements/Panel/Panel.stories.tsx +1 -1
- package/src/elements/PasswordField/PasswordField.stories.tsx +167 -0
- package/src/elements/Progress/Progress.stories.tsx +1 -1
- package/src/elements/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/src/elements/Resizable/Resizable.stories.tsx +1 -1
- package/src/elements/SearchField/SearchField.stories.tsx +146 -0
- package/src/elements/Select/Select.stories.tsx +1 -1
- package/src/elements/Skeleton/Skeleton.stories.tsx +1 -1
- package/src/elements/Switch/Switch.stories.tsx +1 -1
- package/src/elements/Table/Table.stories.tsx +1 -1
- package/src/elements/Tabs/Tabs.stories.tsx +1 -1
- package/src/elements/TextField/TextField.stories.tsx +1 -1
- package/src/elements/TimeField/TimeField.stories.tsx +1 -1
- package/src/elements/Toast/Toast.stories.tsx +1 -1
- package/src/elements/Tooltip/Tooltip.stories.tsx +1 -1
|
@@ -1,325 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createContext, useState, useRef,
|
|
3
|
-
import { ModalOverlay, Modal, Dialog, Button } from 'react-aria-components';
|
|
4
|
-
import { cva } from 'class-variance-authority';
|
|
5
|
-
import { X } from 'lucide-react';
|
|
6
|
-
import { clsx } from 'clsx';
|
|
7
|
-
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
|
-
|
|
10
|
-
// src/elements/Panel/Panel.tsx
|
|
11
|
-
function cn(...inputs) {
|
|
12
|
-
return twMerge(clsx(inputs));
|
|
13
|
-
}
|
|
14
|
-
var panelContentVariants = cva(
|
|
15
|
-
[
|
|
16
|
-
"flex flex-col h-full",
|
|
17
|
-
"bg-[var(--content-background)] text-[var(--content-foreground)]",
|
|
18
|
-
"shadow-lg"
|
|
19
|
-
],
|
|
20
|
-
{
|
|
21
|
-
variants: {
|
|
22
|
-
position: {
|
|
23
|
-
right: "border-l border-[var(--border)]",
|
|
24
|
-
left: "border-r border-[var(--border)]"
|
|
25
|
-
},
|
|
26
|
-
width: {
|
|
27
|
-
sm: "w-[300px]",
|
|
28
|
-
md: "w-[400px]",
|
|
29
|
-
lg: "w-[500px]",
|
|
30
|
-
xl: "w-[600px]",
|
|
31
|
-
auto: "w-auto"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
defaultVariants: {
|
|
35
|
-
position: "right",
|
|
36
|
-
width: "md"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
);
|
|
40
|
-
var panelHeaderVariants = cva([
|
|
41
|
-
"flex items-start justify-between",
|
|
42
|
-
"px-4 py-4",
|
|
43
|
-
"border-b border-[var(--border)]"
|
|
44
|
-
]);
|
|
45
|
-
var panelBodyVariants = cva(["flex-1 overflow-y-auto", "px-4 py-4"]);
|
|
46
|
-
var panelFooterVariants = cva([
|
|
47
|
-
"flex items-center justify-end gap-2",
|
|
48
|
-
"px-4 py-4",
|
|
49
|
-
"border-t border-[var(--border)]"
|
|
50
|
-
]);
|
|
51
|
-
var panelCloseButtonVariants = cva([
|
|
52
|
-
"inline-flex items-center justify-center rounded-md",
|
|
53
|
-
"min-h-[44px] min-w-[44px]",
|
|
54
|
-
"text-[var(--menu-muted)]",
|
|
55
|
-
"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]",
|
|
56
|
-
"focus-visible:outline-none focus-visible:ring-2",
|
|
57
|
-
"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"
|
|
58
|
-
// No transition - instant state changes (v1)
|
|
59
|
-
]);
|
|
60
|
-
var PanelContext = createContext(null);
|
|
61
|
-
function usePanelContext() {
|
|
62
|
-
const context = useContext(PanelContext);
|
|
63
|
-
if (!context) {
|
|
64
|
-
throw new Error("Panel compound components must be used within a Panel");
|
|
65
|
-
}
|
|
66
|
-
return context;
|
|
67
|
-
}
|
|
68
|
-
function useMediaQuery(query) {
|
|
69
|
-
const [matches, setMatches] = useState(() => {
|
|
70
|
-
if (typeof window === "undefined") return false;
|
|
71
|
-
return window.matchMedia(query).matches;
|
|
72
|
-
});
|
|
73
|
-
useEffect(() => {
|
|
74
|
-
if (typeof window === "undefined") return;
|
|
75
|
-
const media = window.matchMedia(query);
|
|
76
|
-
if (media.matches !== matches) {
|
|
77
|
-
setMatches(media.matches);
|
|
78
|
-
}
|
|
79
|
-
const listener = (e) => setMatches(e.matches);
|
|
80
|
-
media.addEventListener("change", listener);
|
|
81
|
-
return () => media.removeEventListener("change", listener);
|
|
82
|
-
}, [query, matches]);
|
|
83
|
-
return matches;
|
|
84
|
-
}
|
|
85
|
-
function PanelRoot({
|
|
86
|
-
children,
|
|
87
|
-
isOpen: controlledIsOpen,
|
|
88
|
-
defaultOpen = false,
|
|
89
|
-
onOpenChange,
|
|
90
|
-
onClose,
|
|
91
|
-
position = "right",
|
|
92
|
-
width = "md",
|
|
93
|
-
mobileBreakpoint = 768
|
|
94
|
-
}) {
|
|
95
|
-
const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);
|
|
96
|
-
const isControlled = controlledIsOpen !== void 0;
|
|
97
|
-
const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;
|
|
98
|
-
const triggerRef = useRef(null);
|
|
99
|
-
const uniqueId = useId();
|
|
100
|
-
const panelId = `panel-${uniqueId}`;
|
|
101
|
-
const titleId = `panel-title-${uniqueId}`;
|
|
102
|
-
const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);
|
|
103
|
-
const setIsOpen = useCallback(
|
|
104
|
-
(open) => {
|
|
105
|
-
if (!isControlled) {
|
|
106
|
-
setUncontrolledIsOpen(open);
|
|
107
|
-
}
|
|
108
|
-
onOpenChange?.(open);
|
|
109
|
-
},
|
|
110
|
-
[isControlled, onOpenChange]
|
|
111
|
-
);
|
|
112
|
-
const handleClose = useCallback(() => {
|
|
113
|
-
setIsOpen(false);
|
|
114
|
-
onClose?.();
|
|
115
|
-
if (triggerRef.current) {
|
|
116
|
-
window.requestAnimationFrame(() => {
|
|
117
|
-
triggerRef.current?.focus();
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}, [setIsOpen, onClose]);
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
if (!isOpen || isMobile) return;
|
|
123
|
-
const handleKeyDown = (e) => {
|
|
124
|
-
if (e.key === "Escape") {
|
|
125
|
-
e.preventDefault();
|
|
126
|
-
handleClose();
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
130
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
131
|
-
}, [isOpen, isMobile, handleClose]);
|
|
132
|
-
const contextValue = {
|
|
133
|
-
isOpen,
|
|
134
|
-
setIsOpen,
|
|
135
|
-
panelId,
|
|
136
|
-
titleId,
|
|
137
|
-
triggerRef,
|
|
138
|
-
position,
|
|
139
|
-
width,
|
|
140
|
-
mobileBreakpoint,
|
|
141
|
-
isMobile,
|
|
142
|
-
handleClose
|
|
143
|
-
};
|
|
144
|
-
return /* @__PURE__ */ jsx(PanelContext.Provider, { value: contextValue, children });
|
|
145
|
-
}
|
|
146
|
-
PanelRoot.displayName = "Panel";
|
|
147
|
-
function PanelTrigger({
|
|
148
|
-
children,
|
|
149
|
-
asChild = true
|
|
150
|
-
}) {
|
|
151
|
-
const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();
|
|
152
|
-
const setRef = useCallback(
|
|
153
|
-
(element) => {
|
|
154
|
-
triggerRef.current = element;
|
|
155
|
-
},
|
|
156
|
-
[triggerRef]
|
|
157
|
-
);
|
|
158
|
-
const handlePress = useCallback(() => {
|
|
159
|
-
setIsOpen(!isOpen);
|
|
160
|
-
}, [setIsOpen, isOpen]);
|
|
161
|
-
if (asChild && isValidElement(children)) {
|
|
162
|
-
const childProps = children.props;
|
|
163
|
-
return cloneElement(children, {
|
|
164
|
-
ref: setRef,
|
|
165
|
-
"aria-expanded": isOpen,
|
|
166
|
-
"aria-controls": isOpen ? panelId : void 0,
|
|
167
|
-
"data-testid": "panel-trigger",
|
|
168
|
-
onPress: handlePress,
|
|
169
|
-
onClick: childProps.onClick ? () => {
|
|
170
|
-
childProps.onClick?.();
|
|
171
|
-
handlePress();
|
|
172
|
-
} : handlePress
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
return /* @__PURE__ */ jsx(
|
|
176
|
-
Button,
|
|
177
|
-
{
|
|
178
|
-
ref: setRef,
|
|
179
|
-
"aria-expanded": isOpen,
|
|
180
|
-
"aria-controls": isOpen ? panelId : void 0,
|
|
181
|
-
onPress: handlePress,
|
|
182
|
-
"data-testid": "panel-trigger",
|
|
183
|
-
children
|
|
184
|
-
}
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
PanelTrigger.displayName = "PanelTrigger";
|
|
188
|
-
function BuiltInCloseButton() {
|
|
189
|
-
const { handleClose } = usePanelContext();
|
|
190
|
-
return /* @__PURE__ */ jsx(
|
|
191
|
-
Button,
|
|
192
|
-
{
|
|
193
|
-
"aria-label": "Close panel",
|
|
194
|
-
"data-testid": "panel-close",
|
|
195
|
-
onPress: handleClose,
|
|
196
|
-
className: panelCloseButtonVariants(),
|
|
197
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-5 w-5" })
|
|
198
|
-
}
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
function PanelContent({
|
|
202
|
-
children,
|
|
203
|
-
showClose = true,
|
|
204
|
-
className
|
|
205
|
-
}) {
|
|
206
|
-
const { isOpen, isMobile, panelId, titleId, position, width, handleClose } = usePanelContext();
|
|
207
|
-
if (!isOpen) return null;
|
|
208
|
-
if (isMobile) {
|
|
209
|
-
return /* @__PURE__ */ jsx(
|
|
210
|
-
ModalOverlay,
|
|
211
|
-
{
|
|
212
|
-
isDismissable: true,
|
|
213
|
-
isOpen,
|
|
214
|
-
onOpenChange: (open) => !open && handleClose(),
|
|
215
|
-
className: "fixed inset-0 z-50 bg-black/50",
|
|
216
|
-
children: /* @__PURE__ */ jsx(Modal, { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs(
|
|
217
|
-
Dialog,
|
|
218
|
-
{
|
|
219
|
-
"aria-labelledby": titleId,
|
|
220
|
-
className: cn(
|
|
221
|
-
"w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none",
|
|
222
|
-
"flex max-h-[90vh] flex-col",
|
|
223
|
-
className
|
|
224
|
-
),
|
|
225
|
-
children: [
|
|
226
|
-
showClose && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2", children: /* @__PURE__ */ jsx(BuiltInCloseButton, {}) }),
|
|
227
|
-
children
|
|
228
|
-
]
|
|
229
|
-
}
|
|
230
|
-
) })
|
|
231
|
-
}
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
return /* @__PURE__ */ jsxs(
|
|
235
|
-
"aside",
|
|
236
|
-
{
|
|
237
|
-
id: panelId,
|
|
238
|
-
"aria-labelledby": titleId,
|
|
239
|
-
"data-testid": "panel-content",
|
|
240
|
-
className: cn(panelContentVariants({ position, width }), className),
|
|
241
|
-
children: [
|
|
242
|
-
children,
|
|
243
|
-
showClose && /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2", children: /* @__PURE__ */ jsx(BuiltInCloseButton, {}) })
|
|
244
|
-
]
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
PanelContent.displayName = "PanelContent";
|
|
249
|
-
function PanelHeader({
|
|
250
|
-
children,
|
|
251
|
-
className
|
|
252
|
-
}) {
|
|
253
|
-
return /* @__PURE__ */ jsx("header", { className: cn(panelHeaderVariants(), className), children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1", children }) });
|
|
254
|
-
}
|
|
255
|
-
PanelHeader.displayName = "PanelHeader";
|
|
256
|
-
function PanelTitle({
|
|
257
|
-
children,
|
|
258
|
-
as: Tag = "h2",
|
|
259
|
-
className
|
|
260
|
-
}) {
|
|
261
|
-
const { titleId } = usePanelContext();
|
|
262
|
-
return /* @__PURE__ */ jsx(
|
|
263
|
-
Tag,
|
|
264
|
-
{
|
|
265
|
-
id: titleId,
|
|
266
|
-
"aria-live": "polite",
|
|
267
|
-
className: cn(
|
|
268
|
-
"text-lg font-semibold text-[var(--content-foreground)]",
|
|
269
|
-
className
|
|
270
|
-
),
|
|
271
|
-
children
|
|
272
|
-
}
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
PanelTitle.displayName = "PanelTitle";
|
|
276
|
-
function PanelDescription({
|
|
277
|
-
children,
|
|
278
|
-
className
|
|
279
|
-
}) {
|
|
280
|
-
return /* @__PURE__ */ jsx("p", { className: cn("text-sm text-[var(--menu-muted)]", className), children });
|
|
281
|
-
}
|
|
282
|
-
PanelDescription.displayName = "PanelDescription";
|
|
283
|
-
function PanelBody({ children, className }) {
|
|
284
|
-
return /* @__PURE__ */ jsx("div", { className: cn(panelBodyVariants(), className), children });
|
|
285
|
-
}
|
|
286
|
-
PanelBody.displayName = "PanelBody";
|
|
287
|
-
function PanelFooter({
|
|
288
|
-
children,
|
|
289
|
-
className
|
|
290
|
-
}) {
|
|
291
|
-
return /* @__PURE__ */ jsx("footer", { className: cn(panelFooterVariants(), className), children });
|
|
292
|
-
}
|
|
293
|
-
PanelFooter.displayName = "PanelFooter";
|
|
294
|
-
function PanelClose({ children }) {
|
|
295
|
-
const { handleClose } = usePanelContext();
|
|
296
|
-
if (!isValidElement(children)) {
|
|
297
|
-
return null;
|
|
298
|
-
}
|
|
299
|
-
const childProps = children.props;
|
|
300
|
-
return cloneElement(children, {
|
|
301
|
-
onPress: () => {
|
|
302
|
-
childProps.onPress?.();
|
|
303
|
-
handleClose();
|
|
304
|
-
},
|
|
305
|
-
onClick: () => {
|
|
306
|
-
childProps.onClick?.();
|
|
307
|
-
handleClose();
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
PanelClose.displayName = "PanelClose";
|
|
312
|
-
var Panel = Object.assign(PanelRoot, {
|
|
313
|
-
Trigger: PanelTrigger,
|
|
314
|
-
Content: PanelContent,
|
|
315
|
-
Header: PanelHeader,
|
|
316
|
-
Title: PanelTitle,
|
|
317
|
-
Description: PanelDescription,
|
|
318
|
-
Body: PanelBody,
|
|
319
|
-
Footer: PanelFooter,
|
|
320
|
-
Close: PanelClose
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
export { Panel, panelBodyVariants, panelCloseButtonVariants, panelContentVariants, panelFooterVariants, panelHeaderVariants };
|
|
324
|
-
//# sourceMappingURL=index.mjs.map
|
|
2
|
+
import {createContext,useState,useRef,useId,useCallback,useEffect,isValidElement,cloneElement,useContext}from'react';import {ModalOverlay,Modal,Dialog,Button}from'react-aria-components';import {cva}from'class-variance-authority';import {X}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs}from'react/jsx-runtime';function d(...e){return twMerge(clsx(e))}var B=cva(["flex flex-col h-full","bg-[var(--content-background)] text-[var(--content-foreground)]","shadow-lg"],{variants:{position:{right:"border-l border-[var(--border)]",left:"border-r border-[var(--border)]"},width:{sm:"w-[300px]",md:"w-[400px]",lg:"w-[500px]",xl:"w-[600px]",auto:"w-auto"}},defaultVariants:{position:"right",width:"md"}}),O=cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),I=cva(["flex-1 overflow-y-auto","px-4 py-4"]),D=cva(["flex items-center justify-end gap-2","px-4 py-4","border-t border-[var(--border)]"]),H=cva(["inline-flex items-center justify-center rounded-md","min-h-[44px] min-w-[44px]","text-[var(--menu-muted)]","hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"]),A=createContext(null);function f(){let e=useContext(A);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function re(e){let[n,t]=useState(()=>typeof window>"u"?false:window.matchMedia(e).matches);return useEffect(()=>{if(typeof window>"u")return;let o=window.matchMedia(e);o.matches!==n&&t(o.matches);let r=s=>t(s.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function F({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:s="right",width:p="md",mobileBreakpoint:l=768}){let[i,g]=useState(t),c=n!==void 0,x=c?n:i,v=useRef(null),C=useId(),U=`panel-${C}`,X=`panel-title-${C}`,b=re(`(max-width: ${l-1}px)`),y=useCallback(u=>{c||g(u),o?.(u);},[c,o]),h=useCallback(()=>{y(false),r?.(),v.current&&window.requestAnimationFrame(()=>{v.current?.focus();});},[y,r]);useEffect(()=>{if(!x||b)return;let u=w=>{w.key==="Escape"&&(w.preventDefault(),h());};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[x,b,h]);let q={isOpen:x,setIsOpen:y,panelId:U,titleId:X,triggerRef:v,position:s,width:p,mobileBreakpoint:l,isMobile:b,handleClose:h};return jsx(A.Provider,{value:q,children:e})}F.displayName="Panel";function L({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:s}=f(),p=useCallback(i=>{s.current=i;},[s]),l=useCallback(()=>{o(!t);},[o,t]);if(n&&isValidElement(e)){let i=e.props;return cloneElement(e,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:l,onClick:i.onClick?()=>{i.onClick?.(),l();}:l})}return jsx(Button,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:l,"data-testid":"panel-trigger",children:e})}L.displayName="PanelTrigger";function E(){let{handleClose:e}=f();return jsx(Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsx(X,{className:"h-5 w-5"})})}function j({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:s,titleId:p,position:l,width:i,handleClose:g}=f();return o?r?jsx(ModalOverlay,{isDismissable:true,isOpen:o,onOpenChange:c=>!c&&g(),className:"fixed inset-0 z-50 bg-black/50",children:jsx(Modal,{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:jsxs(Dialog,{"aria-labelledby":p,className:d("w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none","flex max-h-[90vh] flex-col",t),children:[n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})}),e]})})}):jsxs("aside",{id:s,"aria-labelledby":p,"data-testid":"panel-content",className:d(B({position:l,width:i}),t),children:[e,n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})})]}):null}j.displayName="PanelContent";function W({children:e,className:n}){return jsx("header",{className:d(O(),n),children:jsx("div",{className:"flex flex-col gap-1",children:e})})}W.displayName="PanelHeader";function $({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsx(n,{id:o,"aria-live":"polite",className:d("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}$.displayName="PanelTitle";function z({children:e,className:n}){return jsx("p",{className:d("text-sm text-[var(--menu-muted)]",n),children:e})}z.displayName="PanelDescription";function K({children:e,className:n}){return jsx("div",{className:d(I(),n),children:e})}K.displayName="PanelBody";function Q({children:e,className:n}){return jsx("footer",{className:d(D(),n),children:e})}Q.displayName="PanelFooter";function S({children:e}){let{handleClose:n}=f();if(!isValidElement(e))return null;let t=e.props;return cloneElement(e,{onPress:()=>{t.onPress?.(),n();},onClick:()=>{t.onClick?.(),n();}})}S.displayName="PanelClose";var le=Object.assign(F,{Trigger:L,Content:j,Header:W,Title:$,Description:z,Body:K,Footer:Q,Close:S});export{le as Panel,I as panelBodyVariants,H as panelCloseButtonVariants,B as panelContentVariants,D as panelFooterVariants,O as panelHeaderVariants};//# sourceMappingURL=index.mjs.map
|
|
325
3
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["AriaButton","AriaModalOverlay","AriaModal","AriaDialog"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n \"shadow-lg\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","panelContentVariants","cva","panelHeaderVariants","panelBodyVariants","panelFooterVariants","panelCloseButtonVariants","PanelContext","createContext","usePanelContext","context","useContext","useMediaQuery","query","matches","setMatches","useState","useEffect","media","listener","e","PanelRoot","children","controlledIsOpen","defaultOpen","onOpenChange","onClose","position","width","mobileBreakpoint","uncontrolledIsOpen","setUncontrolledIsOpen","isControlled","isOpen","triggerRef","useRef","uniqueId","useId","panelId","titleId","isMobile","setIsOpen","useCallback","open","handleClose","handleKeyDown","contextValue","jsx","PanelTrigger","asChild","setRef","element","handlePress","isValidElement","childProps","cloneElement","AriaButton","BuiltInCloseButton","X","PanelContent","showClose","className","AriaModalOverlay","AriaModal","jsxs","AriaDialog","PanelHeader","PanelTitle","Tag","PanelDescription","PanelBody","PanelFooter","PanelClose","Panel"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n \"shadow-lg\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const PasswordField: import("react").ForwardRefExoticComponent<{
|
|
2
|
+
size: "default" | "sm" | "lg";
|
|
3
|
+
hasToggle: boolean;
|
|
4
|
+
className?: string | undefined;
|
|
5
|
+
children?: any;
|
|
6
|
+
id?: string | undefined;
|
|
7
|
+
'aria-label'?: string | undefined;
|
|
8
|
+
'aria-labelledby'?: string | undefined;
|
|
9
|
+
'aria-describedby'?: string | undefined;
|
|
10
|
+
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
11
|
+
'aria-hidden'?: boolean | undefined;
|
|
12
|
+
'data-testid'?: string | undefined;
|
|
13
|
+
label?: string | undefined;
|
|
14
|
+
description?: string | undefined;
|
|
15
|
+
errorMessage?: string | undefined;
|
|
16
|
+
successMessage?: string | undefined;
|
|
17
|
+
isRequired?: boolean | undefined;
|
|
18
|
+
isReadOnly?: boolean | undefined;
|
|
19
|
+
isDisabled?: boolean | undefined;
|
|
20
|
+
placeholder?: string | undefined;
|
|
21
|
+
value?: string | undefined;
|
|
22
|
+
defaultValue?: string | undefined;
|
|
23
|
+
name?: string | undefined;
|
|
24
|
+
autoComplete?: "off" | "name" | "on" | "tel" | "url" | "email" | "additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday-day" | "bday-month" | "bday-year" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "new-password" | "one-time-code" | "organization" | "postal-code" | "street-address" | "transaction-amount" | "transaction-currency" | "username" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-national" | "nickname" | "organization-title" | "cc-additional-name" | "language" | "bday" | "sex" | "impp" | "photo" | undefined;
|
|
25
|
+
onChange?: ((value: string) => void) | undefined;
|
|
26
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
27
|
+
//# sourceMappingURL=PasswordField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordField.d.ts","sourceRoot":"","sources":["../../../src/elements/PasswordField/PasswordField.tsx"],"names":[],"mappings":"AA6BA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;kDA4CzB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PasswordField CVA Variant Styles
|
|
3
|
+
*
|
|
4
|
+
* Note: Most styling is delegated to the underlying TextField component.
|
|
5
|
+
* These variants are kept for consumers who need direct access to
|
|
6
|
+
* PasswordField-specific style tokens.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Root wrapper variant styles
|
|
10
|
+
*/
|
|
11
|
+
export declare const passwordFieldVariants: (props?: ({
|
|
12
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
13
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
14
|
+
/**
|
|
15
|
+
* Label variant styles
|
|
16
|
+
*/
|
|
17
|
+
export declare const passwordFieldLabelVariants: (props?: ({
|
|
18
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
19
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Description text variant styles
|
|
22
|
+
*/
|
|
23
|
+
export declare const passwordFieldDescriptionVariants: (props?: ({
|
|
24
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
25
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
26
|
+
/**
|
|
27
|
+
* Error message variant styles
|
|
28
|
+
*/
|
|
29
|
+
export declare const passwordFieldErrorVariants: (props?: ({
|
|
30
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
31
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
32
|
+
//# sourceMappingURL=PasswordField.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordField.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/PasswordField/PasswordField.styles.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,eAAO,MAAM,qBAAqB;;8EAYjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;8EAYtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gCAAgC;;8EAY5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;8EAYtC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* PasswordField props schema extending BaseComponentProps
|
|
4
|
+
*
|
|
5
|
+
* A specialized password input built on the Themis TextField component.
|
|
6
|
+
* Provides show/hide toggle (using Themis Button with three-layer
|
|
7
|
+
* architecture for 44x44px touch targets) and sensible password defaults.
|
|
8
|
+
*/
|
|
9
|
+
export declare const PasswordFieldPropsSchema: z.ZodObject<{
|
|
10
|
+
className: z.ZodOptional<z.ZodString>;
|
|
11
|
+
children: z.ZodOptional<z.ZodAny>;
|
|
12
|
+
id: z.ZodOptional<z.ZodString>;
|
|
13
|
+
'aria-label': z.ZodOptional<z.ZodString>;
|
|
14
|
+
'aria-labelledby': z.ZodOptional<z.ZodString>;
|
|
15
|
+
'aria-describedby': z.ZodOptional<z.ZodString>;
|
|
16
|
+
'aria-live': z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
off: "off";
|
|
18
|
+
polite: "polite";
|
|
19
|
+
assertive: "assertive";
|
|
20
|
+
}>>;
|
|
21
|
+
'aria-hidden': z.ZodOptional<z.ZodBoolean>;
|
|
22
|
+
'data-testid': z.ZodOptional<z.ZodString>;
|
|
23
|
+
size: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
default: "default";
|
|
25
|
+
sm: "sm";
|
|
26
|
+
lg: "lg";
|
|
27
|
+
}>>>;
|
|
28
|
+
label: z.ZodOptional<z.ZodString>;
|
|
29
|
+
description: z.ZodOptional<z.ZodString>;
|
|
30
|
+
errorMessage: z.ZodOptional<z.ZodString>;
|
|
31
|
+
successMessage: z.ZodOptional<z.ZodString>;
|
|
32
|
+
isRequired: z.ZodOptional<z.ZodBoolean>;
|
|
33
|
+
isReadOnly: z.ZodOptional<z.ZodBoolean>;
|
|
34
|
+
isDisabled: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
placeholder: z.ZodOptional<z.ZodString>;
|
|
36
|
+
value: z.ZodOptional<z.ZodString>;
|
|
37
|
+
defaultValue: z.ZodOptional<z.ZodString>;
|
|
38
|
+
name: z.ZodOptional<z.ZodString>;
|
|
39
|
+
autoComplete: z.ZodOptional<z.ZodEnum<{
|
|
40
|
+
off: "off";
|
|
41
|
+
name: "name";
|
|
42
|
+
on: "on";
|
|
43
|
+
tel: "tel";
|
|
44
|
+
url: "url";
|
|
45
|
+
email: "email";
|
|
46
|
+
"additional-name": "additional-name";
|
|
47
|
+
"address-level1": "address-level1";
|
|
48
|
+
"address-level2": "address-level2";
|
|
49
|
+
"address-level3": "address-level3";
|
|
50
|
+
"address-level4": "address-level4";
|
|
51
|
+
"address-line1": "address-line1";
|
|
52
|
+
"address-line2": "address-line2";
|
|
53
|
+
"address-line3": "address-line3";
|
|
54
|
+
"bday-day": "bday-day";
|
|
55
|
+
"bday-month": "bday-month";
|
|
56
|
+
"bday-year": "bday-year";
|
|
57
|
+
"cc-csc": "cc-csc";
|
|
58
|
+
"cc-exp": "cc-exp";
|
|
59
|
+
"cc-exp-month": "cc-exp-month";
|
|
60
|
+
"cc-exp-year": "cc-exp-year";
|
|
61
|
+
"cc-family-name": "cc-family-name";
|
|
62
|
+
"cc-given-name": "cc-given-name";
|
|
63
|
+
"cc-name": "cc-name";
|
|
64
|
+
"cc-number": "cc-number";
|
|
65
|
+
"cc-type": "cc-type";
|
|
66
|
+
country: "country";
|
|
67
|
+
"country-name": "country-name";
|
|
68
|
+
"current-password": "current-password";
|
|
69
|
+
"family-name": "family-name";
|
|
70
|
+
"given-name": "given-name";
|
|
71
|
+
"honorific-prefix": "honorific-prefix";
|
|
72
|
+
"honorific-suffix": "honorific-suffix";
|
|
73
|
+
"new-password": "new-password";
|
|
74
|
+
"one-time-code": "one-time-code";
|
|
75
|
+
organization: "organization";
|
|
76
|
+
"postal-code": "postal-code";
|
|
77
|
+
"street-address": "street-address";
|
|
78
|
+
"transaction-amount": "transaction-amount";
|
|
79
|
+
"transaction-currency": "transaction-currency";
|
|
80
|
+
username: "username";
|
|
81
|
+
"tel-area-code": "tel-area-code";
|
|
82
|
+
"tel-country-code": "tel-country-code";
|
|
83
|
+
"tel-extension": "tel-extension";
|
|
84
|
+
"tel-local": "tel-local";
|
|
85
|
+
"tel-national": "tel-national";
|
|
86
|
+
nickname: "nickname";
|
|
87
|
+
"organization-title": "organization-title";
|
|
88
|
+
"cc-additional-name": "cc-additional-name";
|
|
89
|
+
language: "language";
|
|
90
|
+
bday: "bday";
|
|
91
|
+
sex: "sex";
|
|
92
|
+
impp: "impp";
|
|
93
|
+
photo: "photo";
|
|
94
|
+
}>>;
|
|
95
|
+
hasToggle: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
96
|
+
onChange: z.ZodOptional<z.ZodCustom<(value: string) => void, (value: string) => void>>;
|
|
97
|
+
}, z.core.$strip>;
|
|
98
|
+
export type PasswordFieldProps = z.infer<typeof PasswordFieldPropsSchema>;
|
|
99
|
+
export type PasswordFieldSize = z.infer<typeof PasswordFieldPropsSchema>['size'];
|
|
100
|
+
//# sourceMappingURL=PasswordField.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordField.types.d.ts","sourceRoot":"","sources":["../../../src/elements/PasswordField/PasswordField.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDA6BR,MAAM,KAAK,IAAI,UAAf,MAAM,KAAK,IAAI;iBAC1C,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
@keyframes shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-4px)}20%,40%,60%,80%{transform:translate(4px)}}.shake{animation:shake .4s ease-in-out}@media(prefers-reduced-motion:reduce){.shake{animation:none;border-color:var(--destructive);transition:border-color .1s}}
|
|
2
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/elements/TextField/TextField.css"],"sourcesContent":["/**\n * TextField Component Styles\n * Additional CSS for animations and effects\n */\n\n/* Shake animation for paste prevention (Phase 3) */\n@keyframes shake {\n 0%, 100% { transform: translateX(0); }\n 10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }\n 20%, 40%, 60%, 80% { transform: translateX(4px); }\n}\n\n.shake {\n animation: shake 400ms ease-in-out;\n}\n\n/* Respect reduced motion preference (WCAG 2.2) */\n@media (prefers-reduced-motion: reduce) {\n .shake {\n animation: none;\n /* Alternative: brief border color flash */\n border-color: var(--destructive);\n transition: border-color 100ms;\n }\n}\n"],"mappings":"AAMA,WAAW,MACT,MAAW,UAAW,UAAW,EAAI,CACrC,oBAA0B,UAAW,UAAW,KAAO,CACvD,gBAAqB,UAAW,UAAW,IAAM,CACnD,CAEA,CANW,MAOT,UAAW,MAAM,IAAM,WACzB,CAGA,OAAO,uBAAyB,QAC9B,CAZS,MAaP,UAAW,KAEX,aAAc,IAAI,eAClB,WAAY,aAAa,GAC3B,CACF","names":[]}
|