@fragments-sdk/ui 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Accordion/index.cjs +11 -4
- package/dist/components/Accordion/index.cjs.map +1 -1
- package/dist/components/Accordion/index.d.ts +3 -3
- package/dist/components/Accordion/index.d.ts.map +1 -1
- package/dist/components/Accordion/index.js +11 -4
- package/dist/components/Accordion/index.js.map +1 -1
- package/dist/components/Collapsible/index.cjs +45 -10
- package/dist/components/Collapsible/index.cjs.map +1 -1
- package/dist/components/Collapsible/index.d.ts +6 -12
- package/dist/components/Collapsible/index.d.ts.map +1 -1
- package/dist/components/Collapsible/index.js +45 -10
- package/dist/components/Collapsible/index.js.map +1 -1
- package/dist/components/Combobox/index.cjs +18 -9
- package/dist/components/Combobox/index.cjs.map +1 -1
- package/dist/components/Combobox/index.d.ts +8 -12
- package/dist/components/Combobox/index.d.ts.map +1 -1
- package/dist/components/Combobox/index.js +18 -9
- package/dist/components/Combobox/index.js.map +1 -1
- package/dist/components/Command/index.cjs +54 -21
- package/dist/components/Command/index.cjs.map +1 -1
- package/dist/components/Command/index.d.ts +2 -2
- package/dist/components/Command/index.d.ts.map +1 -1
- package/dist/components/Command/index.js +54 -21
- package/dist/components/Command/index.js.map +1 -1
- package/dist/components/DataTable/index.cjs +13 -1
- package/dist/components/DataTable/index.cjs.map +1 -1
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +13 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DatePicker/index.d.ts +2 -3
- package/dist/components/DatePicker/index.d.ts.map +1 -1
- package/dist/components/Dialog/index.cjs +12 -9
- package/dist/components/Dialog/index.cjs.map +1 -1
- package/dist/components/Dialog/index.d.ts +8 -12
- package/dist/components/Dialog/index.d.ts.map +1 -1
- package/dist/components/Dialog/index.js +12 -9
- package/dist/components/Dialog/index.js.map +1 -1
- package/dist/components/Drawer/index.cjs +12 -9
- package/dist/components/Drawer/index.cjs.map +1 -1
- package/dist/components/Drawer/index.d.ts +8 -12
- package/dist/components/Drawer/index.d.ts.map +1 -1
- package/dist/components/Drawer/index.js +12 -9
- package/dist/components/Drawer/index.js.map +1 -1
- package/dist/components/Menu/index.cjs +30 -16
- package/dist/components/Menu/index.cjs.map +1 -1
- package/dist/components/Menu/index.d.ts +17 -25
- package/dist/components/Menu/index.d.ts.map +1 -1
- package/dist/components/Menu/index.js +30 -16
- package/dist/components/Menu/index.js.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenuContext.cjs.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenuContext.d.ts +1 -0
- package/dist/components/NavigationMenu/NavigationMenuContext.d.ts.map +1 -1
- package/dist/components/NavigationMenu/NavigationMenuContext.js.map +1 -1
- package/dist/components/NavigationMenu/index.cjs +43 -11
- package/dist/components/NavigationMenu/index.cjs.map +1 -1
- package/dist/components/NavigationMenu/index.d.ts.map +1 -1
- package/dist/components/NavigationMenu/index.js +43 -11
- package/dist/components/NavigationMenu/index.js.map +1 -1
- package/dist/components/NavigationMenu/useNavigationMenu.cjs +2 -0
- package/dist/components/NavigationMenu/useNavigationMenu.cjs.map +1 -1
- package/dist/components/NavigationMenu/useNavigationMenu.d.ts +1 -0
- package/dist/components/NavigationMenu/useNavigationMenu.d.ts.map +1 -1
- package/dist/components/NavigationMenu/useNavigationMenu.js +2 -0
- package/dist/components/NavigationMenu/useNavigationMenu.js.map +1 -1
- package/dist/components/Popover/index.cjs +11 -10
- package/dist/components/Popover/index.cjs.map +1 -1
- package/dist/components/Popover/index.d.ts +8 -12
- package/dist/components/Popover/index.d.ts.map +1 -1
- package/dist/components/Popover/index.js +11 -10
- package/dist/components/Popover/index.js.map +1 -1
- package/dist/components/Select/index.cjs +7 -6
- package/dist/components/Select/index.cjs.map +1 -1
- package/dist/components/Select/index.d.ts +6 -9
- package/dist/components/Select/index.d.ts.map +1 -1
- package/dist/components/Select/index.js +7 -6
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/Sidebar/index.cjs +71 -24
- package/dist/components/Sidebar/index.cjs.map +1 -1
- package/dist/components/Sidebar/index.d.ts +21 -33
- package/dist/components/Sidebar/index.d.ts.map +1 -1
- package/dist/components/Sidebar/index.js +71 -24
- package/dist/components/Sidebar/index.js.map +1 -1
- package/dist/components/Tooltip/index.cjs +12 -6
- package/dist/components/Tooltip/index.cjs.map +1 -1
- package/dist/components/Tooltip/index.d.ts.map +1 -1
- package/dist/components/Tooltip/index.js +12 -6
- package/dist/components/Tooltip/index.js.map +1 -1
- package/dist/datepicker.cjs +24 -10
- package/dist/datepicker.cjs.map +1 -1
- package/dist/datepicker.js +24 -10
- package/dist/datepicker.js.map +1 -1
- package/fragments.json +1 -1
- package/package.json +2 -2
- package/src/components/Accordion/Accordion.test.tsx +33 -0
- package/src/components/Accordion/index.tsx +10 -3
- package/src/components/Collapsible/Collapsible.test.tsx +41 -0
- package/src/components/Collapsible/index.tsx +53 -16
- package/src/components/Combobox/Combobox.test.tsx +55 -0
- package/src/components/Combobox/index.tsx +23 -17
- package/src/components/Command/Command.test.tsx +93 -0
- package/src/components/Command/index.tsx +61 -18
- package/src/components/DataTable/DataTable.test.tsx +11 -2
- package/src/components/DataTable/index.tsx +22 -2
- package/src/components/DatePicker/DatePicker.test.tsx +79 -0
- package/src/components/DatePicker/index.tsx +29 -14
- package/src/components/Dialog/Dialog.test.tsx +23 -0
- package/src/components/Dialog/index.tsx +15 -16
- package/src/components/Drawer/Drawer.test.tsx +27 -0
- package/src/components/Drawer/index.tsx +15 -16
- package/src/components/Menu/index.tsx +35 -30
- package/src/components/NavigationMenu/NavigationMenu.fragment.tsx +1 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +40 -4
- package/src/components/NavigationMenu/NavigationMenuContext.ts +3 -0
- package/src/components/NavigationMenu/index.tsx +49 -13
- package/src/components/NavigationMenu/useNavigationMenu.ts +4 -0
- package/src/components/Popover/Popover.test.tsx +23 -0
- package/src/components/Popover/index.tsx +15 -18
- package/src/components/Select/Select.test.tsx +41 -0
- package/src/components/Select/index.tsx +10 -12
- package/src/components/Sidebar/Sidebar.test.tsx +83 -4
- package/src/components/Sidebar/index.tsx +87 -45
- package/src/components/Tooltip/Tooltip.test.tsx +17 -0
- package/src/components/Tooltip/index.tsx +46 -32
|
@@ -75,7 +75,7 @@ function AccordionRoot({
|
|
|
75
75
|
setOpenItems(newItems);
|
|
76
76
|
}
|
|
77
77
|
if (onValueChange) {
|
|
78
|
-
onValueChange(type === "single" ? newItems[0]
|
|
78
|
+
onValueChange(type === "single" ? newItems[0] : newItems);
|
|
79
79
|
}
|
|
80
80
|
}, [type, currentOpenItems, collapsible2, controlledOpenItems, onValueChange]);
|
|
81
81
|
const classes = [Accordion_module.default.accordion, className].filter(Boolean).join(" ");
|
|
@@ -103,11 +103,15 @@ function AccordionItem({
|
|
|
103
103
|
}
|
|
104
104
|
function AccordionTrigger({
|
|
105
105
|
children,
|
|
106
|
-
className
|
|
106
|
+
className,
|
|
107
|
+
onClick,
|
|
108
|
+
...htmlProps
|
|
107
109
|
}) {
|
|
108
110
|
const { toggle, headingLevel } = useAccordionContext();
|
|
109
111
|
const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();
|
|
110
|
-
const handleClick = () => {
|
|
112
|
+
const handleClick = (event) => {
|
|
113
|
+
onClick == null ? void 0 : onClick(event);
|
|
114
|
+
if (event.defaultPrevented) return;
|
|
111
115
|
if (!disabled) {
|
|
112
116
|
toggle(value);
|
|
113
117
|
}
|
|
@@ -117,6 +121,7 @@ function AccordionTrigger({
|
|
|
117
121
|
return /* @__PURE__ */ jsxRuntime.jsx(HeadingTag, { className: Accordion_module.default.heading, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
118
122
|
collapsible.Collapsible.Trigger,
|
|
119
123
|
{
|
|
124
|
+
...htmlProps,
|
|
120
125
|
id: triggerId,
|
|
121
126
|
className: classes,
|
|
122
127
|
onClick: handleClick,
|
|
@@ -153,13 +158,15 @@ function AccordionTrigger({
|
|
|
153
158
|
}
|
|
154
159
|
function AccordionContent({
|
|
155
160
|
children,
|
|
156
|
-
className
|
|
161
|
+
className,
|
|
162
|
+
...htmlProps
|
|
157
163
|
}) {
|
|
158
164
|
const { isOpen, triggerId, contentId } = useAccordionItemContext();
|
|
159
165
|
const classes = [Accordion_module.default.content, className].filter(Boolean).join(" ");
|
|
160
166
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
161
167
|
collapsible.Collapsible.Panel,
|
|
162
168
|
{
|
|
169
|
+
...htmlProps,
|
|
163
170
|
id: contentId,
|
|
164
171
|
className: classes,
|
|
165
172
|
"data-state": isOpen ? "open" : "closed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Collapsible as BaseCollapsible } from '@base-ui/react/collapsible';\nimport styles from './Accordion.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type AccordionValue = string | string[];\n\nexport interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'> {\n children: React.ReactNode;\n /** Allow multiple items to be open at once */\n type?: 'single' | 'multiple';\n /** Controlled value - string for single, string[] for multiple */\n value?: AccordionValue;\n /** Default value for uncontrolled usage */\n defaultValue?: AccordionValue;\n /** Callback when value changes */\n onValueChange?: (value: AccordionValue) => void;\n /** Whether items can be fully collapsed (only for type=\"single\") */\n collapsible?: boolean;\n /**\n * Heading level for accordion triggers (for semantic HTML).\n * The trigger will be wrapped in an <h{level}> element.\n * @default 3\n */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface AccordionItemProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Unique value for this item */\n value: string;\n /** Disable this item */\n disabled?: boolean;\n}\n\nexport interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n}\n\nexport interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\n// ============================================\n// Context\n// ============================================\n\ninterface AccordionContextValue {\n type: 'single' | 'multiple';\n openItems: string[];\n toggle: (value: string) => void;\n collapsible: boolean;\n headingLevel: 2 | 3 | 4 | 5 | 6;\n}\n\nconst AccordionContext = React.createContext<AccordionContextValue | null>(null);\n\ninterface AccordionItemContextValue {\n value: string;\n isOpen: boolean;\n disabled: boolean;\n triggerId: string;\n contentId: string;\n}\n\nconst AccordionItemContext = React.createContext<AccordionItemContextValue | null>(null);\n\nfunction useAccordionContext() {\n const context = React.useContext(AccordionContext);\n if (!context) {\n throw new Error('Accordion components must be used within an Accordion');\n }\n return context;\n}\n\nfunction useAccordionItemContext() {\n const context = React.useContext(AccordionItemContext);\n if (!context) {\n throw new Error('Accordion.Trigger/Content must be used within an Accordion.Item');\n }\n return context;\n}\n\n// ============================================\n// Components\n// ============================================\n\nfunction AccordionRoot({\n children,\n type = 'single',\n value,\n defaultValue,\n onValueChange,\n collapsible = false,\n headingLevel = 3,\n className,\n ...htmlProps\n}: AccordionProps) {\n // Normalize value to array for internal handling\n const normalizeValue = (val: AccordionValue | undefined): string[] => {\n if (val === undefined) return [];\n return Array.isArray(val) ? val : [val];\n };\n\n const [openItems, setOpenItems] = React.useState<string[]>(() =>\n normalizeValue(defaultValue)\n );\n\n // Use controlled value if provided\n const controlledOpenItems = value !== undefined ? normalizeValue(value) : undefined;\n const currentOpenItems = controlledOpenItems ?? openItems;\n\n const toggle = React.useCallback((itemValue: string) => {\n const newItems = (() => {\n if (type === 'single') {\n // For single, toggle or set new item\n if (currentOpenItems.includes(itemValue)) {\n return collapsible ? [] : currentOpenItems;\n }\n return [itemValue];\n } else {\n // For multiple, toggle item in array\n if (currentOpenItems.includes(itemValue)) {\n return currentOpenItems.filter(v => v !== itemValue);\n }\n return [...currentOpenItems, itemValue];\n }\n })();\n\n if (controlledOpenItems === undefined) {\n setOpenItems(newItems);\n }\n\n if (onValueChange) {\n onValueChange(type === 'single' ? (newItems[0] ?? '') : newItems);\n }\n }, [type, currentOpenItems, collapsible, controlledOpenItems, onValueChange]);\n\n const classes = [styles.accordion, className].filter(Boolean).join(' ');\n\n return (\n <AccordionContext.Provider value={{ type, openItems: currentOpenItems, toggle, collapsible, headingLevel }}>\n <div {...htmlProps} className={classes} data-orientation=\"vertical\" role=\"region\">\n {children}\n </div>\n </AccordionContext.Provider>\n );\n}\n\nfunction AccordionItem({\n children,\n value,\n disabled = false,\n className,\n ...htmlProps\n}: AccordionItemProps) {\n const { openItems } = useAccordionContext();\n const isOpen = openItems.includes(value);\n const baseId = React.useId();\n const triggerId = `accordion-trigger-${baseId}`;\n const contentId = `accordion-content-${baseId}`;\n\n const classes = [\n styles.item,\n isOpen && styles.itemOpen,\n disabled && styles.itemDisabled,\n className,\n ].filter(Boolean).join(' ');\n\n return (\n <AccordionItemContext.Provider value={{ value, isOpen, disabled, triggerId, contentId }}>\n <BaseCollapsible.Root open={isOpen} disabled={disabled}>\n <div {...htmlProps} className={classes} data-state={isOpen ? 'open' : 'closed'} data-disabled={disabled || undefined}>\n {children}\n </div>\n </BaseCollapsible.Root>\n </AccordionItemContext.Provider>\n );\n}\n\nfunction AccordionTrigger({\n children,\n className,\n}: AccordionTriggerProps) {\n const { toggle, headingLevel } = useAccordionContext();\n const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();\n\n const handleClick = () => {\n if (!disabled) {\n toggle(value);\n }\n };\n\n const classes = [styles.trigger, className].filter(Boolean).join(' ');\n\n // Create the heading element dynamically based on headingLevel\n const HeadingTag = `h${headingLevel}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\n return (\n <HeadingTag className={styles.heading}>\n <BaseCollapsible.Trigger\n id={triggerId}\n className={classes}\n onClick={handleClick}\n aria-expanded={isOpen}\n aria-controls={contentId}\n data-state={isOpen ? 'open' : 'closed'}\n disabled={disabled}\n >\n <span className={styles.triggerContent}>{children}</span>\n <svg\n className={styles.chevron}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </BaseCollapsible.Trigger>\n </HeadingTag>\n );\n}\n\nfunction AccordionContent({\n children,\n className,\n}: AccordionContentProps) {\n const { isOpen, triggerId, contentId } = useAccordionItemContext();\n\n const classes = [styles.content, className].filter(Boolean).join(' ');\n\n return (\n <BaseCollapsible.Panel\n id={contentId}\n className={classes}\n data-state={isOpen ? 'open' : 'closed'}\n role=\"region\"\n aria-labelledby={triggerId}\n >\n <div className={styles.contentInner}>\n {children}\n </div>\n </BaseCollapsible.Panel>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Accordion = Object.assign(AccordionRoot, {\n Item: AccordionItem,\n Trigger: AccordionTrigger,\n Content: AccordionContent,\n});\n\nexport { AccordionRoot, AccordionItem, AccordionTrigger, AccordionContent };\n"],"names":["React","collapsible","styles","jsx","BaseCollapsible","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Collapsible as BaseCollapsible } from '@base-ui/react/collapsible';\nimport styles from './Accordion.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type AccordionValue = string | string[];\n\nexport interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'> {\n children: React.ReactNode;\n /** Allow multiple items to be open at once */\n type?: 'single' | 'multiple';\n /** Controlled value - string for single, string[] for multiple */\n value?: AccordionValue;\n /** Default value for uncontrolled usage */\n defaultValue?: AccordionValue;\n /** Callback when value changes */\n onValueChange?: (value: AccordionValue | undefined) => void;\n /** Whether items can be fully collapsed (only for type=\"single\") */\n collapsible?: boolean;\n /**\n * Heading level for accordion triggers (for semantic HTML).\n * The trigger will be wrapped in an <h{level}> element.\n * @default 3\n */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface AccordionItemProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Unique value for this item */\n value: string;\n /** Disable this item */\n disabled?: boolean;\n}\n\nexport interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n}\n\nexport interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\n// ============================================\n// Context\n// ============================================\n\ninterface AccordionContextValue {\n type: 'single' | 'multiple';\n openItems: string[];\n toggle: (value: string) => void;\n collapsible: boolean;\n headingLevel: 2 | 3 | 4 | 5 | 6;\n}\n\nconst AccordionContext = React.createContext<AccordionContextValue | null>(null);\n\ninterface AccordionItemContextValue {\n value: string;\n isOpen: boolean;\n disabled: boolean;\n triggerId: string;\n contentId: string;\n}\n\nconst AccordionItemContext = React.createContext<AccordionItemContextValue | null>(null);\n\nfunction useAccordionContext() {\n const context = React.useContext(AccordionContext);\n if (!context) {\n throw new Error('Accordion components must be used within an Accordion');\n }\n return context;\n}\n\nfunction useAccordionItemContext() {\n const context = React.useContext(AccordionItemContext);\n if (!context) {\n throw new Error('Accordion.Trigger/Content must be used within an Accordion.Item');\n }\n return context;\n}\n\n// ============================================\n// Components\n// ============================================\n\nfunction AccordionRoot({\n children,\n type = 'single',\n value,\n defaultValue,\n onValueChange,\n collapsible = false,\n headingLevel = 3,\n className,\n ...htmlProps\n}: AccordionProps) {\n // Normalize value to array for internal handling\n const normalizeValue = (val: AccordionValue | undefined): string[] => {\n if (val === undefined) return [];\n return Array.isArray(val) ? val : [val];\n };\n\n const [openItems, setOpenItems] = React.useState<string[]>(() =>\n normalizeValue(defaultValue)\n );\n\n // Use controlled value if provided\n const controlledOpenItems = value !== undefined ? normalizeValue(value) : undefined;\n const currentOpenItems = controlledOpenItems ?? openItems;\n\n const toggle = React.useCallback((itemValue: string) => {\n const newItems = (() => {\n if (type === 'single') {\n // For single, toggle or set new item\n if (currentOpenItems.includes(itemValue)) {\n return collapsible ? [] : currentOpenItems;\n }\n return [itemValue];\n } else {\n // For multiple, toggle item in array\n if (currentOpenItems.includes(itemValue)) {\n return currentOpenItems.filter(v => v !== itemValue);\n }\n return [...currentOpenItems, itemValue];\n }\n })();\n\n if (controlledOpenItems === undefined) {\n setOpenItems(newItems);\n }\n\n if (onValueChange) {\n onValueChange(type === 'single' ? newItems[0] : newItems);\n }\n }, [type, currentOpenItems, collapsible, controlledOpenItems, onValueChange]);\n\n const classes = [styles.accordion, className].filter(Boolean).join(' ');\n\n return (\n <AccordionContext.Provider value={{ type, openItems: currentOpenItems, toggle, collapsible, headingLevel }}>\n <div {...htmlProps} className={classes} data-orientation=\"vertical\" role=\"region\">\n {children}\n </div>\n </AccordionContext.Provider>\n );\n}\n\nfunction AccordionItem({\n children,\n value,\n disabled = false,\n className,\n ...htmlProps\n}: AccordionItemProps) {\n const { openItems } = useAccordionContext();\n const isOpen = openItems.includes(value);\n const baseId = React.useId();\n const triggerId = `accordion-trigger-${baseId}`;\n const contentId = `accordion-content-${baseId}`;\n\n const classes = [\n styles.item,\n isOpen && styles.itemOpen,\n disabled && styles.itemDisabled,\n className,\n ].filter(Boolean).join(' ');\n\n return (\n <AccordionItemContext.Provider value={{ value, isOpen, disabled, triggerId, contentId }}>\n <BaseCollapsible.Root open={isOpen} disabled={disabled}>\n <div {...htmlProps} className={classes} data-state={isOpen ? 'open' : 'closed'} data-disabled={disabled || undefined}>\n {children}\n </div>\n </BaseCollapsible.Root>\n </AccordionItemContext.Provider>\n );\n}\n\nfunction AccordionTrigger({\n children,\n className,\n onClick,\n ...htmlProps\n}: AccordionTriggerProps) {\n const { toggle, headingLevel } = useAccordionContext();\n const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n if (!disabled) {\n toggle(value);\n }\n };\n\n const classes = [styles.trigger, className].filter(Boolean).join(' ');\n\n // Create the heading element dynamically based on headingLevel\n const HeadingTag = `h${headingLevel}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\n return (\n <HeadingTag className={styles.heading}>\n <BaseCollapsible.Trigger\n {...htmlProps}\n id={triggerId}\n className={classes}\n onClick={handleClick}\n aria-expanded={isOpen}\n aria-controls={contentId}\n data-state={isOpen ? 'open' : 'closed'}\n disabled={disabled}\n >\n <span className={styles.triggerContent}>{children}</span>\n <svg\n className={styles.chevron}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </BaseCollapsible.Trigger>\n </HeadingTag>\n );\n}\n\nfunction AccordionContent({\n children,\n className,\n ...htmlProps\n}: AccordionContentProps) {\n const { isOpen, triggerId, contentId } = useAccordionItemContext();\n\n const classes = [styles.content, className].filter(Boolean).join(' ');\n\n return (\n <BaseCollapsible.Panel\n {...htmlProps}\n id={contentId}\n className={classes}\n data-state={isOpen ? 'open' : 'closed'}\n role=\"region\"\n aria-labelledby={triggerId}\n >\n <div className={styles.contentInner}>\n {children}\n </div>\n </BaseCollapsible.Panel>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Accordion = Object.assign(AccordionRoot, {\n Item: AccordionItem,\n Trigger: AccordionTrigger,\n Content: AccordionContent,\n});\n\nexport { AccordionRoot, AccordionItem, AccordionTrigger, AccordionContent };\n"],"names":["React","collapsible","styles","jsx","BaseCollapsible","jsxs"],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ export interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement
|
|
|
9
9
|
/** Default value for uncontrolled usage */
|
|
10
10
|
defaultValue?: AccordionValue;
|
|
11
11
|
/** Callback when value changes */
|
|
12
|
-
onValueChange?: (value: AccordionValue) => void;
|
|
12
|
+
onValueChange?: (value: AccordionValue | undefined) => void;
|
|
13
13
|
/** Whether items can be fully collapsed (only for type="single") */
|
|
14
14
|
collapsible?: boolean;
|
|
15
15
|
/**
|
|
@@ -34,8 +34,8 @@ export interface AccordionContentProps extends React.HTMLAttributes<HTMLDivEleme
|
|
|
34
34
|
}
|
|
35
35
|
declare function AccordionRoot({ children, type, value, defaultValue, onValueChange, collapsible, headingLevel, className, ...htmlProps }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
36
36
|
declare function AccordionItem({ children, value, disabled, className, ...htmlProps }: AccordionItemProps): import("react/jsx-runtime").JSX.Element;
|
|
37
|
-
declare function AccordionTrigger({ children, className, }: AccordionTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
-
declare function AccordionContent({ children, className, }: AccordionContentProps): import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
declare function AccordionTrigger({ children, className, onClick, ...htmlProps }: AccordionTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
declare function AccordionContent({ children, className, ...htmlProps }: AccordionContentProps): import("react/jsx-runtime").JSX.Element;
|
|
39
39
|
export declare const Accordion: typeof AccordionRoot & {
|
|
40
40
|
Item: typeof AccordionItem;
|
|
41
41
|
Trigger: typeof AccordionTrigger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAE/C,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChG,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,kEAAkE;IAClE,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAE/C,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChG,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC7B,kEAAkE;IAClE,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5D,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAsB,SAAQ,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC;IACpF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAsB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACjF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AA8CD,iBAAS,aAAa,CAAC,EACrB,QAAQ,EACR,IAAe,EACf,KAAK,EACL,YAAY,EACZ,aAAa,EACb,WAAmB,EACnB,YAAgB,EAChB,SAAS,EACT,GAAG,SAAS,EACb,EAAE,cAAc,2CAkDhB;AAED,iBAAS,aAAa,CAAC,EACrB,QAAQ,EACR,KAAK,EACL,QAAgB,EAChB,SAAS,EACT,GAAG,SAAS,EACb,EAAE,kBAAkB,2CAuBpB;AAED,iBAAS,gBAAgB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,GAAG,SAAS,EACb,EAAE,qBAAqB,2CAiDvB;AAED,iBAAS,gBAAgB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,GAAG,SAAS,EACb,EAAE,qBAAqB,2CAmBvB;AAMD,eAAO,MAAM,SAAS;;;;CAIpB,CAAC;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -56,7 +56,7 @@ function AccordionRoot({
|
|
|
56
56
|
setOpenItems(newItems);
|
|
57
57
|
}
|
|
58
58
|
if (onValueChange) {
|
|
59
|
-
onValueChange(type === "single" ? newItems[0]
|
|
59
|
+
onValueChange(type === "single" ? newItems[0] : newItems);
|
|
60
60
|
}
|
|
61
61
|
}, [type, currentOpenItems, collapsible, controlledOpenItems, onValueChange]);
|
|
62
62
|
const classes = [styles.accordion, className].filter(Boolean).join(" ");
|
|
@@ -84,11 +84,15 @@ function AccordionItem({
|
|
|
84
84
|
}
|
|
85
85
|
function AccordionTrigger({
|
|
86
86
|
children,
|
|
87
|
-
className
|
|
87
|
+
className,
|
|
88
|
+
onClick,
|
|
89
|
+
...htmlProps
|
|
88
90
|
}) {
|
|
89
91
|
const { toggle, headingLevel } = useAccordionContext();
|
|
90
92
|
const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();
|
|
91
|
-
const handleClick = () => {
|
|
93
|
+
const handleClick = (event) => {
|
|
94
|
+
onClick == null ? void 0 : onClick(event);
|
|
95
|
+
if (event.defaultPrevented) return;
|
|
92
96
|
if (!disabled) {
|
|
93
97
|
toggle(value);
|
|
94
98
|
}
|
|
@@ -98,6 +102,7 @@ function AccordionTrigger({
|
|
|
98
102
|
return /* @__PURE__ */ jsx(HeadingTag, { className: styles.heading, children: /* @__PURE__ */ jsxs(
|
|
99
103
|
Collapsible.Trigger,
|
|
100
104
|
{
|
|
105
|
+
...htmlProps,
|
|
101
106
|
id: triggerId,
|
|
102
107
|
className: classes,
|
|
103
108
|
onClick: handleClick,
|
|
@@ -134,13 +139,15 @@ function AccordionTrigger({
|
|
|
134
139
|
}
|
|
135
140
|
function AccordionContent({
|
|
136
141
|
children,
|
|
137
|
-
className
|
|
142
|
+
className,
|
|
143
|
+
...htmlProps
|
|
138
144
|
}) {
|
|
139
145
|
const { isOpen, triggerId, contentId } = useAccordionItemContext();
|
|
140
146
|
const classes = [styles.content, className].filter(Boolean).join(" ");
|
|
141
147
|
return /* @__PURE__ */ jsx(
|
|
142
148
|
Collapsible.Panel,
|
|
143
149
|
{
|
|
150
|
+
...htmlProps,
|
|
144
151
|
id: contentId,
|
|
145
152
|
className: classes,
|
|
146
153
|
"data-state": isOpen ? "open" : "closed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Collapsible as BaseCollapsible } from '@base-ui/react/collapsible';\nimport styles from './Accordion.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type AccordionValue = string | string[];\n\nexport interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'> {\n children: React.ReactNode;\n /** Allow multiple items to be open at once */\n type?: 'single' | 'multiple';\n /** Controlled value - string for single, string[] for multiple */\n value?: AccordionValue;\n /** Default value for uncontrolled usage */\n defaultValue?: AccordionValue;\n /** Callback when value changes */\n onValueChange?: (value: AccordionValue) => void;\n /** Whether items can be fully collapsed (only for type=\"single\") */\n collapsible?: boolean;\n /**\n * Heading level for accordion triggers (for semantic HTML).\n * The trigger will be wrapped in an <h{level}> element.\n * @default 3\n */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface AccordionItemProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Unique value for this item */\n value: string;\n /** Disable this item */\n disabled?: boolean;\n}\n\nexport interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n}\n\nexport interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\n// ============================================\n// Context\n// ============================================\n\ninterface AccordionContextValue {\n type: 'single' | 'multiple';\n openItems: string[];\n toggle: (value: string) => void;\n collapsible: boolean;\n headingLevel: 2 | 3 | 4 | 5 | 6;\n}\n\nconst AccordionContext = React.createContext<AccordionContextValue | null>(null);\n\ninterface AccordionItemContextValue {\n value: string;\n isOpen: boolean;\n disabled: boolean;\n triggerId: string;\n contentId: string;\n}\n\nconst AccordionItemContext = React.createContext<AccordionItemContextValue | null>(null);\n\nfunction useAccordionContext() {\n const context = React.useContext(AccordionContext);\n if (!context) {\n throw new Error('Accordion components must be used within an Accordion');\n }\n return context;\n}\n\nfunction useAccordionItemContext() {\n const context = React.useContext(AccordionItemContext);\n if (!context) {\n throw new Error('Accordion.Trigger/Content must be used within an Accordion.Item');\n }\n return context;\n}\n\n// ============================================\n// Components\n// ============================================\n\nfunction AccordionRoot({\n children,\n type = 'single',\n value,\n defaultValue,\n onValueChange,\n collapsible = false,\n headingLevel = 3,\n className,\n ...htmlProps\n}: AccordionProps) {\n // Normalize value to array for internal handling\n const normalizeValue = (val: AccordionValue | undefined): string[] => {\n if (val === undefined) return [];\n return Array.isArray(val) ? val : [val];\n };\n\n const [openItems, setOpenItems] = React.useState<string[]>(() =>\n normalizeValue(defaultValue)\n );\n\n // Use controlled value if provided\n const controlledOpenItems = value !== undefined ? normalizeValue(value) : undefined;\n const currentOpenItems = controlledOpenItems ?? openItems;\n\n const toggle = React.useCallback((itemValue: string) => {\n const newItems = (() => {\n if (type === 'single') {\n // For single, toggle or set new item\n if (currentOpenItems.includes(itemValue)) {\n return collapsible ? [] : currentOpenItems;\n }\n return [itemValue];\n } else {\n // For multiple, toggle item in array\n if (currentOpenItems.includes(itemValue)) {\n return currentOpenItems.filter(v => v !== itemValue);\n }\n return [...currentOpenItems, itemValue];\n }\n })();\n\n if (controlledOpenItems === undefined) {\n setOpenItems(newItems);\n }\n\n if (onValueChange) {\n onValueChange(type === 'single' ? (newItems[0] ?? '') : newItems);\n }\n }, [type, currentOpenItems, collapsible, controlledOpenItems, onValueChange]);\n\n const classes = [styles.accordion, className].filter(Boolean).join(' ');\n\n return (\n <AccordionContext.Provider value={{ type, openItems: currentOpenItems, toggle, collapsible, headingLevel }}>\n <div {...htmlProps} className={classes} data-orientation=\"vertical\" role=\"region\">\n {children}\n </div>\n </AccordionContext.Provider>\n );\n}\n\nfunction AccordionItem({\n children,\n value,\n disabled = false,\n className,\n ...htmlProps\n}: AccordionItemProps) {\n const { openItems } = useAccordionContext();\n const isOpen = openItems.includes(value);\n const baseId = React.useId();\n const triggerId = `accordion-trigger-${baseId}`;\n const contentId = `accordion-content-${baseId}`;\n\n const classes = [\n styles.item,\n isOpen && styles.itemOpen,\n disabled && styles.itemDisabled,\n className,\n ].filter(Boolean).join(' ');\n\n return (\n <AccordionItemContext.Provider value={{ value, isOpen, disabled, triggerId, contentId }}>\n <BaseCollapsible.Root open={isOpen} disabled={disabled}>\n <div {...htmlProps} className={classes} data-state={isOpen ? 'open' : 'closed'} data-disabled={disabled || undefined}>\n {children}\n </div>\n </BaseCollapsible.Root>\n </AccordionItemContext.Provider>\n );\n}\n\nfunction AccordionTrigger({\n children,\n className,\n}: AccordionTriggerProps) {\n const { toggle, headingLevel } = useAccordionContext();\n const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();\n\n const handleClick = () => {\n if (!disabled) {\n toggle(value);\n }\n };\n\n const classes = [styles.trigger, className].filter(Boolean).join(' ');\n\n // Create the heading element dynamically based on headingLevel\n const HeadingTag = `h${headingLevel}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\n return (\n <HeadingTag className={styles.heading}>\n <BaseCollapsible.Trigger\n id={triggerId}\n className={classes}\n onClick={handleClick}\n aria-expanded={isOpen}\n aria-controls={contentId}\n data-state={isOpen ? 'open' : 'closed'}\n disabled={disabled}\n >\n <span className={styles.triggerContent}>{children}</span>\n <svg\n className={styles.chevron}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </BaseCollapsible.Trigger>\n </HeadingTag>\n );\n}\n\nfunction AccordionContent({\n children,\n className,\n}: AccordionContentProps) {\n const { isOpen, triggerId, contentId } = useAccordionItemContext();\n\n const classes = [styles.content, className].filter(Boolean).join(' ');\n\n return (\n <BaseCollapsible.Panel\n id={contentId}\n className={classes}\n data-state={isOpen ? 'open' : 'closed'}\n role=\"region\"\n aria-labelledby={triggerId}\n >\n <div className={styles.contentInner}>\n {children}\n </div>\n </BaseCollapsible.Panel>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Accordion = Object.assign(AccordionRoot, {\n Item: AccordionItem,\n Trigger: AccordionTrigger,\n Content: AccordionContent,\n});\n\nexport { AccordionRoot, AccordionItem, AccordionTrigger, AccordionContent };\n"],"names":["BaseCollapsible"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/Accordion/index.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Collapsible as BaseCollapsible } from '@base-ui/react/collapsible';\nimport styles from './Accordion.module.scss';\n\n// ============================================\n// Types\n// ============================================\n\nexport type AccordionValue = string | string[];\n\nexport interface AccordionProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'> {\n children: React.ReactNode;\n /** Allow multiple items to be open at once */\n type?: 'single' | 'multiple';\n /** Controlled value - string for single, string[] for multiple */\n value?: AccordionValue;\n /** Default value for uncontrolled usage */\n defaultValue?: AccordionValue;\n /** Callback when value changes */\n onValueChange?: (value: AccordionValue | undefined) => void;\n /** Whether items can be fully collapsed (only for type=\"single\") */\n collapsible?: boolean;\n /**\n * Heading level for accordion triggers (for semantic HTML).\n * The trigger will be wrapped in an <h{level}> element.\n * @default 3\n */\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n}\n\nexport interface AccordionItemProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Unique value for this item */\n value: string;\n /** Disable this item */\n disabled?: boolean;\n}\n\nexport interface AccordionTriggerProps extends React.HTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n}\n\nexport interface AccordionContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\n// ============================================\n// Context\n// ============================================\n\ninterface AccordionContextValue {\n type: 'single' | 'multiple';\n openItems: string[];\n toggle: (value: string) => void;\n collapsible: boolean;\n headingLevel: 2 | 3 | 4 | 5 | 6;\n}\n\nconst AccordionContext = React.createContext<AccordionContextValue | null>(null);\n\ninterface AccordionItemContextValue {\n value: string;\n isOpen: boolean;\n disabled: boolean;\n triggerId: string;\n contentId: string;\n}\n\nconst AccordionItemContext = React.createContext<AccordionItemContextValue | null>(null);\n\nfunction useAccordionContext() {\n const context = React.useContext(AccordionContext);\n if (!context) {\n throw new Error('Accordion components must be used within an Accordion');\n }\n return context;\n}\n\nfunction useAccordionItemContext() {\n const context = React.useContext(AccordionItemContext);\n if (!context) {\n throw new Error('Accordion.Trigger/Content must be used within an Accordion.Item');\n }\n return context;\n}\n\n// ============================================\n// Components\n// ============================================\n\nfunction AccordionRoot({\n children,\n type = 'single',\n value,\n defaultValue,\n onValueChange,\n collapsible = false,\n headingLevel = 3,\n className,\n ...htmlProps\n}: AccordionProps) {\n // Normalize value to array for internal handling\n const normalizeValue = (val: AccordionValue | undefined): string[] => {\n if (val === undefined) return [];\n return Array.isArray(val) ? val : [val];\n };\n\n const [openItems, setOpenItems] = React.useState<string[]>(() =>\n normalizeValue(defaultValue)\n );\n\n // Use controlled value if provided\n const controlledOpenItems = value !== undefined ? normalizeValue(value) : undefined;\n const currentOpenItems = controlledOpenItems ?? openItems;\n\n const toggle = React.useCallback((itemValue: string) => {\n const newItems = (() => {\n if (type === 'single') {\n // For single, toggle or set new item\n if (currentOpenItems.includes(itemValue)) {\n return collapsible ? [] : currentOpenItems;\n }\n return [itemValue];\n } else {\n // For multiple, toggle item in array\n if (currentOpenItems.includes(itemValue)) {\n return currentOpenItems.filter(v => v !== itemValue);\n }\n return [...currentOpenItems, itemValue];\n }\n })();\n\n if (controlledOpenItems === undefined) {\n setOpenItems(newItems);\n }\n\n if (onValueChange) {\n onValueChange(type === 'single' ? newItems[0] : newItems);\n }\n }, [type, currentOpenItems, collapsible, controlledOpenItems, onValueChange]);\n\n const classes = [styles.accordion, className].filter(Boolean).join(' ');\n\n return (\n <AccordionContext.Provider value={{ type, openItems: currentOpenItems, toggle, collapsible, headingLevel }}>\n <div {...htmlProps} className={classes} data-orientation=\"vertical\" role=\"region\">\n {children}\n </div>\n </AccordionContext.Provider>\n );\n}\n\nfunction AccordionItem({\n children,\n value,\n disabled = false,\n className,\n ...htmlProps\n}: AccordionItemProps) {\n const { openItems } = useAccordionContext();\n const isOpen = openItems.includes(value);\n const baseId = React.useId();\n const triggerId = `accordion-trigger-${baseId}`;\n const contentId = `accordion-content-${baseId}`;\n\n const classes = [\n styles.item,\n isOpen && styles.itemOpen,\n disabled && styles.itemDisabled,\n className,\n ].filter(Boolean).join(' ');\n\n return (\n <AccordionItemContext.Provider value={{ value, isOpen, disabled, triggerId, contentId }}>\n <BaseCollapsible.Root open={isOpen} disabled={disabled}>\n <div {...htmlProps} className={classes} data-state={isOpen ? 'open' : 'closed'} data-disabled={disabled || undefined}>\n {children}\n </div>\n </BaseCollapsible.Root>\n </AccordionItemContext.Provider>\n );\n}\n\nfunction AccordionTrigger({\n children,\n className,\n onClick,\n ...htmlProps\n}: AccordionTriggerProps) {\n const { toggle, headingLevel } = useAccordionContext();\n const { value, isOpen, disabled, triggerId, contentId } = useAccordionItemContext();\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n if (!disabled) {\n toggle(value);\n }\n };\n\n const classes = [styles.trigger, className].filter(Boolean).join(' ');\n\n // Create the heading element dynamically based on headingLevel\n const HeadingTag = `h${headingLevel}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\n return (\n <HeadingTag className={styles.heading}>\n <BaseCollapsible.Trigger\n {...htmlProps}\n id={triggerId}\n className={classes}\n onClick={handleClick}\n aria-expanded={isOpen}\n aria-controls={contentId}\n data-state={isOpen ? 'open' : 'closed'}\n disabled={disabled}\n >\n <span className={styles.triggerContent}>{children}</span>\n <svg\n className={styles.chevron}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </BaseCollapsible.Trigger>\n </HeadingTag>\n );\n}\n\nfunction AccordionContent({\n children,\n className,\n ...htmlProps\n}: AccordionContentProps) {\n const { isOpen, triggerId, contentId } = useAccordionItemContext();\n\n const classes = [styles.content, className].filter(Boolean).join(' ');\n\n return (\n <BaseCollapsible.Panel\n {...htmlProps}\n id={contentId}\n className={classes}\n data-state={isOpen ? 'open' : 'closed'}\n role=\"region\"\n aria-labelledby={triggerId}\n >\n <div className={styles.contentInner}>\n {children}\n </div>\n </BaseCollapsible.Panel>\n );\n}\n\n// ============================================\n// Export compound component\n// ============================================\n\nexport const Accordion = Object.assign(AccordionRoot, {\n Item: AccordionItem,\n Trigger: AccordionTrigger,\n Content: AccordionContent,\n});\n\nexport { AccordionRoot, AccordionItem, AccordionTrigger, AccordionContent };\n"],"names":["BaseCollapsible"],"mappings":"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"}
|
|
@@ -3,6 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const Collapsible_module = require("./Collapsible.module.scss.cjs");
|
|
6
|
+
function composeEventHandlers(userHandler, internalHandler) {
|
|
7
|
+
return (event) => {
|
|
8
|
+
userHandler == null ? void 0 : userHandler(event);
|
|
9
|
+
if (event.defaultPrevented) return;
|
|
10
|
+
internalHandler(event);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
6
13
|
const CollapsibleContext = React.createContext(null);
|
|
7
14
|
function useCollapsibleContext() {
|
|
8
15
|
const context = React.useContext(CollapsibleContext);
|
|
@@ -17,7 +24,8 @@ function CollapsibleRoot({
|
|
|
17
24
|
open: controlledOpen,
|
|
18
25
|
onOpenChange,
|
|
19
26
|
disabled = false,
|
|
20
|
-
className
|
|
27
|
+
className,
|
|
28
|
+
...htmlProps
|
|
21
29
|
}) {
|
|
22
30
|
const [internalOpen, setInternalOpen] = React.useState(defaultOpen);
|
|
23
31
|
const isControlled = controlledOpen !== void 0;
|
|
@@ -47,6 +55,7 @@ function CollapsibleRoot({
|
|
|
47
55
|
return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48
56
|
"div",
|
|
49
57
|
{
|
|
58
|
+
...htmlProps,
|
|
50
59
|
className: `${Collapsible_module.default.root} ${isOpen ? Collapsible_module.default.open : ""} ${disabled ? Collapsible_module.default.disabled : ""} ${className || ""}`,
|
|
51
60
|
"data-state": isOpen ? "open" : "closed",
|
|
52
61
|
"data-disabled": disabled || void 0,
|
|
@@ -59,7 +68,10 @@ function CollapsibleTrigger({
|
|
|
59
68
|
className,
|
|
60
69
|
showChevron = true,
|
|
61
70
|
chevronPosition = "end",
|
|
62
|
-
asChild = false
|
|
71
|
+
asChild = false,
|
|
72
|
+
onClick,
|
|
73
|
+
onKeyDown,
|
|
74
|
+
...htmlProps
|
|
63
75
|
}) {
|
|
64
76
|
const { isOpen, toggle, contentId, triggerId, disabled } = useCollapsibleContext();
|
|
65
77
|
const handleKeyDown = (e) => {
|
|
@@ -68,6 +80,9 @@ function CollapsibleTrigger({
|
|
|
68
80
|
toggle();
|
|
69
81
|
}
|
|
70
82
|
};
|
|
83
|
+
const handleClick = () => {
|
|
84
|
+
toggle();
|
|
85
|
+
};
|
|
71
86
|
const chevronIcon = showChevron && /* @__PURE__ */ jsxRuntime.jsx(
|
|
72
87
|
"svg",
|
|
73
88
|
{
|
|
@@ -90,26 +105,44 @@ function CollapsibleTrigger({
|
|
|
90
105
|
}
|
|
91
106
|
);
|
|
92
107
|
if (asChild && React.isValidElement(children)) {
|
|
108
|
+
const childProps = children.props;
|
|
93
109
|
return React.cloneElement(children, {
|
|
94
|
-
|
|
110
|
+
...htmlProps,
|
|
111
|
+
id: htmlProps.id ?? triggerId,
|
|
95
112
|
"aria-expanded": isOpen,
|
|
96
113
|
"aria-controls": contentId,
|
|
97
114
|
"aria-disabled": disabled || void 0,
|
|
98
|
-
onClick:
|
|
99
|
-
|
|
115
|
+
onClick: composeEventHandlers(
|
|
116
|
+
(event) => {
|
|
117
|
+
var _a;
|
|
118
|
+
(_a = childProps.onClick) == null ? void 0 : _a.call(childProps, event);
|
|
119
|
+
onClick == null ? void 0 : onClick(event);
|
|
120
|
+
},
|
|
121
|
+
() => handleClick()
|
|
122
|
+
),
|
|
123
|
+
onKeyDown: composeEventHandlers(
|
|
124
|
+
(event) => {
|
|
125
|
+
var _a;
|
|
126
|
+
(_a = childProps.onKeyDown) == null ? void 0 : _a.call(childProps, event);
|
|
127
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
128
|
+
},
|
|
129
|
+
(event) => handleKeyDown(event)
|
|
130
|
+
),
|
|
131
|
+
className: [className, childProps.className].filter(Boolean).join(" ")
|
|
100
132
|
});
|
|
101
133
|
}
|
|
102
134
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
103
135
|
"button",
|
|
104
136
|
{
|
|
137
|
+
...htmlProps,
|
|
105
138
|
type: "button",
|
|
106
|
-
id: triggerId,
|
|
139
|
+
id: htmlProps.id ?? triggerId,
|
|
107
140
|
className: `${Collapsible_module.default.trigger} ${className || ""}`,
|
|
108
141
|
"aria-expanded": isOpen,
|
|
109
142
|
"aria-controls": contentId,
|
|
110
143
|
"aria-disabled": disabled || void 0,
|
|
111
|
-
onClick:
|
|
112
|
-
onKeyDown: handleKeyDown,
|
|
144
|
+
onClick: composeEventHandlers(onClick, handleClick),
|
|
145
|
+
onKeyDown: composeEventHandlers(onKeyDown, handleKeyDown),
|
|
113
146
|
disabled,
|
|
114
147
|
children: [
|
|
115
148
|
chevronPosition === "start" && chevronIcon,
|
|
@@ -122,7 +155,8 @@ function CollapsibleTrigger({
|
|
|
122
155
|
function CollapsibleContent({
|
|
123
156
|
children,
|
|
124
157
|
className,
|
|
125
|
-
forceMount = false
|
|
158
|
+
forceMount = false,
|
|
159
|
+
...htmlProps
|
|
126
160
|
}) {
|
|
127
161
|
const { isOpen, contentId, triggerId } = useCollapsibleContext();
|
|
128
162
|
if (!forceMount && !isOpen) {
|
|
@@ -131,7 +165,8 @@ function CollapsibleContent({
|
|
|
131
165
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
132
166
|
"div",
|
|
133
167
|
{
|
|
134
|
-
|
|
168
|
+
...htmlProps,
|
|
169
|
+
id: htmlProps.id ?? contentId,
|
|
135
170
|
role: "region",
|
|
136
171
|
"aria-labelledby": triggerId,
|
|
137
172
|
className: `${Collapsible_module.default.content} ${isOpen ? Collapsible_module.default.contentOpen : Collapsible_module.default.contentClosed} ${className || ""}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/Collapsible/index.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useCallback, useId, createContext, useContext } from 'react';\nimport styles from './Collapsible.module.scss';\n\n// Context for sharing state between compound components\ninterface CollapsibleContextValue {\n isOpen: boolean;\n toggle: () => void;\n contentId: string;\n triggerId: string;\n disabled?: boolean;\n}\n\nconst CollapsibleContext = createContext<CollapsibleContextValue | null>(null);\n\nfunction useCollapsibleContext() {\n const context = useContext(CollapsibleContext);\n if (!context) {\n throw new Error('Collapsible compound components must be used within Collapsible.Root');\n }\n return context;\n}\n\n// Root component\nexport interface CollapsibleRootProps {\n children: React.ReactNode;\n /** Whether the collapsible is initially open */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Whether the collapsible is disabled */\n disabled?: boolean;\n /** Additional class name */\n className?: string;\n}\n\nfunction CollapsibleRoot({\n children,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n disabled = false,\n className,\n}: CollapsibleRootProps) {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const uniqueId = useId();\n const contentId = `collapsible-content-${uniqueId}`;\n const triggerId = `collapsible-trigger-${uniqueId}`;\n\n const toggle = useCallback(() => {\n if (disabled) return;\n\n if (isControlled) {\n onOpenChange?.(!isOpen);\n } else {\n setInternalOpen((prev) => {\n const newValue = !prev;\n onOpenChange?.(newValue);\n return newValue;\n });\n }\n }, [disabled, isControlled, isOpen, onOpenChange]);\n\n const contextValue: CollapsibleContextValue = {\n isOpen,\n toggle,\n contentId,\n triggerId,\n disabled,\n };\n\n return (\n <CollapsibleContext.Provider value={contextValue}>\n <div\n className={`${styles.root} ${isOpen ? styles.open : ''} ${disabled ? styles.disabled : ''} ${className || ''}`}\n data-state={isOpen ? 'open' : 'closed'}\n data-disabled={disabled || undefined}\n >\n {children}\n </div>\n </CollapsibleContext.Provider>\n );\n}\n\n// Trigger component\nexport interface CollapsibleTriggerProps {\n children: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Show chevron indicator */\n showChevron?: boolean;\n /** Chevron position */\n chevronPosition?: 'start' | 'end';\n /** Render as child element (for custom triggers) */\n asChild?: boolean;\n}\n\nfunction CollapsibleTrigger({\n children,\n className,\n showChevron = true,\n chevronPosition = 'end',\n asChild = false,\n}: CollapsibleTriggerProps) {\n const { isOpen, toggle, contentId, triggerId, disabled } = useCollapsibleContext();\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n };\n\n const chevronIcon = showChevron && (\n <svg\n className={`${styles.chevron} ${isOpen ? styles.chevronOpen : ''}`}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(children as React.ReactElement<any>, {\n id: triggerId,\n 'aria-expanded': isOpen,\n 'aria-controls': contentId,\n 'aria-disabled': disabled || undefined,\n onClick: toggle,\n onKeyDown: handleKeyDown,\n });\n }\n\n return (\n <button\n type=\"button\"\n id={triggerId}\n className={`${styles.trigger} ${className || ''}`}\n aria-expanded={isOpen}\n aria-controls={contentId}\n aria-disabled={disabled || undefined}\n onClick={toggle}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n >\n {chevronPosition === 'start' && chevronIcon}\n <span className={styles.triggerContent}>{children}</span>\n {chevronPosition === 'end' && chevronIcon}\n </button>\n );\n}\n\n// Content component\nexport interface CollapsibleContentProps {\n children: React.ReactNode;\n /** Additional class name */\n className?: string;\n /** Force mount content even when closed (useful for animations) */\n forceMount?: boolean;\n}\n\nfunction CollapsibleContent({\n children,\n className,\n forceMount = false,\n}: CollapsibleContentProps) {\n const { isOpen, contentId, triggerId } = useCollapsibleContext();\n\n // If not force mounted and closed, don't render\n if (!forceMount && !isOpen) {\n return null;\n }\n\n return (\n <div\n id={contentId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={`${styles.content} ${isOpen ? styles.contentOpen : styles.contentClosed} ${className || ''}`}\n data-state={isOpen ? 'open' : 'closed'}\n hidden={!isOpen && !forceMount}\n >\n <div className={styles.contentInner}>{children}</div>\n </div>\n );\n}\n\n// Compound component export\nexport const Collapsible = Object.assign(CollapsibleRoot, {\n Root: CollapsibleRoot,\n Trigger: CollapsibleTrigger,\n Content: CollapsibleContent,\n});\n\n// Named exports for direct imports\nexport {\n CollapsibleRoot,\n CollapsibleTrigger,\n CollapsibleContent,\n useCollapsibleContext,\n};\n\nexport type CollapsibleProps = CollapsibleRootProps;\n"],"names":["createContext","useContext","useState","useId","useCallback","jsx","styles","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/Collapsible/index.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useCallback, useId, createContext, useContext } from 'react';\nimport styles from './Collapsible.module.scss';\n\nfunction composeEventHandlers<E extends { defaultPrevented: boolean }>(\n userHandler: ((event: E) => void) | undefined,\n internalHandler: (event: E) => void\n) {\n return (event: E) => {\n userHandler?.(event);\n if (event.defaultPrevented) return;\n internalHandler(event);\n };\n}\n\n// Context for sharing state between compound components\ninterface CollapsibleContextValue {\n isOpen: boolean;\n toggle: () => void;\n contentId: string;\n triggerId: string;\n disabled?: boolean;\n}\n\nconst CollapsibleContext = createContext<CollapsibleContextValue | null>(null);\n\nfunction useCollapsibleContext() {\n const context = useContext(CollapsibleContext);\n if (!context) {\n throw new Error('Collapsible compound components must be used within Collapsible.Root');\n }\n return context;\n}\n\n// Root component\nexport interface CollapsibleRootProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Whether the collapsible is initially open */\n defaultOpen?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Callback when open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Whether the collapsible is disabled */\n disabled?: boolean;\n}\n\nfunction CollapsibleRoot({\n children,\n defaultOpen = false,\n open: controlledOpen,\n onOpenChange,\n disabled = false,\n className,\n ...htmlProps\n}: CollapsibleRootProps) {\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const uniqueId = useId();\n const contentId = `collapsible-content-${uniqueId}`;\n const triggerId = `collapsible-trigger-${uniqueId}`;\n\n const toggle = useCallback(() => {\n if (disabled) return;\n\n if (isControlled) {\n onOpenChange?.(!isOpen);\n } else {\n setInternalOpen((prev) => {\n const newValue = !prev;\n onOpenChange?.(newValue);\n return newValue;\n });\n }\n }, [disabled, isControlled, isOpen, onOpenChange]);\n\n const contextValue: CollapsibleContextValue = {\n isOpen,\n toggle,\n contentId,\n triggerId,\n disabled,\n };\n\n return (\n <CollapsibleContext.Provider value={contextValue}>\n <div\n {...htmlProps}\n className={`${styles.root} ${isOpen ? styles.open : ''} ${disabled ? styles.disabled : ''} ${className || ''}`}\n data-state={isOpen ? 'open' : 'closed'}\n data-disabled={disabled || undefined}\n >\n {children}\n </div>\n </CollapsibleContext.Provider>\n );\n}\n\n// Trigger component\nexport interface CollapsibleTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n /** Show chevron indicator */\n showChevron?: boolean;\n /** Chevron position */\n chevronPosition?: 'start' | 'end';\n /** Render as child element (for custom triggers) */\n asChild?: boolean;\n}\n\nfunction CollapsibleTrigger({\n children,\n className,\n showChevron = true,\n chevronPosition = 'end',\n asChild = false,\n onClick,\n onKeyDown,\n ...htmlProps\n}: CollapsibleTriggerProps) {\n const { isOpen, toggle, contentId, triggerId, disabled } = useCollapsibleContext();\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n toggle();\n }\n };\n\n const handleClick = () => {\n toggle();\n };\n\n const chevronIcon = showChevron && (\n <svg\n className={`${styles.chevron} ${isOpen ? styles.chevronOpen : ''}`}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n\n if (asChild && React.isValidElement(children)) {\n const childProps = children.props as {\n className?: string;\n onClick?: (event: React.MouseEvent<HTMLElement>) => void;\n onKeyDown?: (event: React.KeyboardEvent<HTMLElement>) => void;\n };\n\n return React.cloneElement(children as React.ReactElement<any>, {\n ...htmlProps,\n id: (htmlProps.id as string | undefined) ?? triggerId,\n 'aria-expanded': isOpen,\n 'aria-controls': contentId,\n 'aria-disabled': disabled || undefined,\n onClick: composeEventHandlers(\n (event: React.MouseEvent<HTMLElement>) => {\n childProps.onClick?.(event);\n onClick?.(event as unknown as React.MouseEvent<HTMLButtonElement>);\n },\n () => handleClick()\n ),\n onKeyDown: composeEventHandlers(\n (event: React.KeyboardEvent<HTMLElement>) => {\n childProps.onKeyDown?.(event);\n onKeyDown?.(event as unknown as React.KeyboardEvent<HTMLButtonElement>);\n },\n (event) => handleKeyDown(event as unknown as React.KeyboardEvent)\n ),\n className: [className, childProps.className].filter(Boolean).join(' '),\n });\n }\n\n return (\n <button\n {...htmlProps}\n type=\"button\"\n id={(htmlProps.id as string | undefined) ?? triggerId}\n className={`${styles.trigger} ${className || ''}`}\n aria-expanded={isOpen}\n aria-controls={contentId}\n aria-disabled={disabled || undefined}\n onClick={composeEventHandlers(onClick, handleClick)}\n onKeyDown={composeEventHandlers(onKeyDown, handleKeyDown)}\n disabled={disabled}\n >\n {chevronPosition === 'start' && chevronIcon}\n <span className={styles.triggerContent}>{children}</span>\n {chevronPosition === 'end' && chevronIcon}\n </button>\n );\n}\n\n// Content component\nexport interface CollapsibleContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Force mount content even when closed (useful for animations) */\n forceMount?: boolean;\n}\n\nfunction CollapsibleContent({\n children,\n className,\n forceMount = false,\n ...htmlProps\n}: CollapsibleContentProps) {\n const { isOpen, contentId, triggerId } = useCollapsibleContext();\n\n // If not force mounted and closed, don't render\n if (!forceMount && !isOpen) {\n return null;\n }\n\n return (\n <div\n {...htmlProps}\n id={(htmlProps.id as string | undefined) ?? contentId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={`${styles.content} ${isOpen ? styles.contentOpen : styles.contentClosed} ${className || ''}`}\n data-state={isOpen ? 'open' : 'closed'}\n hidden={!isOpen && !forceMount}\n >\n <div className={styles.contentInner}>{children}</div>\n </div>\n );\n}\n\n// Compound component export\nexport const Collapsible = Object.assign(CollapsibleRoot, {\n Root: CollapsibleRoot,\n Trigger: CollapsibleTrigger,\n Content: CollapsibleContent,\n});\n\n// Named exports for direct imports\nexport {\n CollapsibleRoot,\n CollapsibleTrigger,\n CollapsibleContent,\n useCollapsibleContext,\n};\n\nexport type CollapsibleProps = CollapsibleRootProps;\n"],"names":["createContext","useContext","useState","useId","useCallback","jsx","styles","jsxs"],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ interface CollapsibleContextValue {
|
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
}
|
|
9
9
|
declare function useCollapsibleContext(): CollapsibleContextValue;
|
|
10
|
-
export interface CollapsibleRootProps {
|
|
10
|
+
export interface CollapsibleRootProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
/** Whether the collapsible is initially open */
|
|
13
13
|
defaultOpen?: boolean;
|
|
@@ -17,14 +17,10 @@ export interface CollapsibleRootProps {
|
|
|
17
17
|
onOpenChange?: (open: boolean) => void;
|
|
18
18
|
/** Whether the collapsible is disabled */
|
|
19
19
|
disabled?: boolean;
|
|
20
|
-
/** Additional class name */
|
|
21
|
-
className?: string;
|
|
22
20
|
}
|
|
23
|
-
declare function CollapsibleRoot({ children, defaultOpen, open: controlledOpen, onOpenChange, disabled, className, }: CollapsibleRootProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
-
export interface CollapsibleTriggerProps {
|
|
21
|
+
declare function CollapsibleRoot({ children, defaultOpen, open: controlledOpen, onOpenChange, disabled, className, ...htmlProps }: CollapsibleRootProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export interface CollapsibleTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
25
23
|
children: React.ReactNode;
|
|
26
|
-
/** Additional class name */
|
|
27
|
-
className?: string;
|
|
28
24
|
/** Show chevron indicator */
|
|
29
25
|
showChevron?: boolean;
|
|
30
26
|
/** Chevron position */
|
|
@@ -32,15 +28,13 @@ export interface CollapsibleTriggerProps {
|
|
|
32
28
|
/** Render as child element (for custom triggers) */
|
|
33
29
|
asChild?: boolean;
|
|
34
30
|
}
|
|
35
|
-
declare function CollapsibleTrigger({ children, className, showChevron, chevronPosition, asChild, }: CollapsibleTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
-
export interface CollapsibleContentProps {
|
|
31
|
+
declare function CollapsibleTrigger({ children, className, showChevron, chevronPosition, asChild, onClick, onKeyDown, ...htmlProps }: CollapsibleTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export interface CollapsibleContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
37
33
|
children: React.ReactNode;
|
|
38
|
-
/** Additional class name */
|
|
39
|
-
className?: string;
|
|
40
34
|
/** Force mount content even when closed (useful for animations) */
|
|
41
35
|
forceMount?: boolean;
|
|
42
36
|
}
|
|
43
|
-
declare function CollapsibleContent({ children, className, forceMount, }: CollapsibleContentProps): import("react/jsx-runtime").JSX.Element | null;
|
|
37
|
+
declare function CollapsibleContent({ children, className, forceMount, ...htmlProps }: CollapsibleContentProps): import("react/jsx-runtime").JSX.Element | null;
|
|
44
38
|
export declare const Collapsible: typeof CollapsibleRoot & {
|
|
45
39
|
Root: typeof CollapsibleRoot;
|
|
46
40
|
Trigger: typeof CollapsibleTrigger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Collapsible/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAkE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Collapsible/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAkE,MAAM,OAAO,CAAC;AAevF,UAAU,uBAAuB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAID,iBAAS,qBAAqB,4BAM7B;AAGD,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAChF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,iBAAS,eAAe,CAAC,EACvB,QAAQ,EACR,WAAmB,EACnB,IAAI,EAAE,cAAc,EACpB,YAAY,EACZ,QAAgB,EAChB,SAAS,EACT,GAAG,SAAS,EACb,EAAE,oBAAoB,2CA2CtB;AAGD,MAAM,WAAW,uBAAwB,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAC5F,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,6BAA6B;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uBAAuB;IACvB,eAAe,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAClC,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,iBAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,SAAS,EACT,WAAkB,EAClB,eAAuB,EACvB,OAAe,EACf,OAAO,EACP,SAAS,EACT,GAAG,SAAS,EACb,EAAE,uBAAuB,2CAkFzB;AAGD,MAAM,WAAW,uBAAwB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACnF,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mEAAmE;IACnE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,iBAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,SAAS,EACT,UAAkB,EAClB,GAAG,SAAS,EACb,EAAE,uBAAuB,kDAqBzB;AAGD,eAAO,MAAM,WAAW;;;;CAItB,CAAC;AAGH,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,GACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React__default, { useState, useId, useCallback, createContext, useContext } from "react";
|
|
3
3
|
import styles from "./Collapsible.module.scss.js";
|
|
4
|
+
function composeEventHandlers(userHandler, internalHandler) {
|
|
5
|
+
return (event) => {
|
|
6
|
+
userHandler == null ? void 0 : userHandler(event);
|
|
7
|
+
if (event.defaultPrevented) return;
|
|
8
|
+
internalHandler(event);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
4
11
|
const CollapsibleContext = createContext(null);
|
|
5
12
|
function useCollapsibleContext() {
|
|
6
13
|
const context = useContext(CollapsibleContext);
|
|
@@ -15,7 +22,8 @@ function CollapsibleRoot({
|
|
|
15
22
|
open: controlledOpen,
|
|
16
23
|
onOpenChange,
|
|
17
24
|
disabled = false,
|
|
18
|
-
className
|
|
25
|
+
className,
|
|
26
|
+
...htmlProps
|
|
19
27
|
}) {
|
|
20
28
|
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
21
29
|
const isControlled = controlledOpen !== void 0;
|
|
@@ -45,6 +53,7 @@ function CollapsibleRoot({
|
|
|
45
53
|
return /* @__PURE__ */ jsx(CollapsibleContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
46
54
|
"div",
|
|
47
55
|
{
|
|
56
|
+
...htmlProps,
|
|
48
57
|
className: `${styles.root} ${isOpen ? styles.open : ""} ${disabled ? styles.disabled : ""} ${className || ""}`,
|
|
49
58
|
"data-state": isOpen ? "open" : "closed",
|
|
50
59
|
"data-disabled": disabled || void 0,
|
|
@@ -57,7 +66,10 @@ function CollapsibleTrigger({
|
|
|
57
66
|
className,
|
|
58
67
|
showChevron = true,
|
|
59
68
|
chevronPosition = "end",
|
|
60
|
-
asChild = false
|
|
69
|
+
asChild = false,
|
|
70
|
+
onClick,
|
|
71
|
+
onKeyDown,
|
|
72
|
+
...htmlProps
|
|
61
73
|
}) {
|
|
62
74
|
const { isOpen, toggle, contentId, triggerId, disabled } = useCollapsibleContext();
|
|
63
75
|
const handleKeyDown = (e) => {
|
|
@@ -66,6 +78,9 @@ function CollapsibleTrigger({
|
|
|
66
78
|
toggle();
|
|
67
79
|
}
|
|
68
80
|
};
|
|
81
|
+
const handleClick = () => {
|
|
82
|
+
toggle();
|
|
83
|
+
};
|
|
69
84
|
const chevronIcon = showChevron && /* @__PURE__ */ jsx(
|
|
70
85
|
"svg",
|
|
71
86
|
{
|
|
@@ -88,26 +103,44 @@ function CollapsibleTrigger({
|
|
|
88
103
|
}
|
|
89
104
|
);
|
|
90
105
|
if (asChild && React__default.isValidElement(children)) {
|
|
106
|
+
const childProps = children.props;
|
|
91
107
|
return React__default.cloneElement(children, {
|
|
92
|
-
|
|
108
|
+
...htmlProps,
|
|
109
|
+
id: htmlProps.id ?? triggerId,
|
|
93
110
|
"aria-expanded": isOpen,
|
|
94
111
|
"aria-controls": contentId,
|
|
95
112
|
"aria-disabled": disabled || void 0,
|
|
96
|
-
onClick:
|
|
97
|
-
|
|
113
|
+
onClick: composeEventHandlers(
|
|
114
|
+
(event) => {
|
|
115
|
+
var _a;
|
|
116
|
+
(_a = childProps.onClick) == null ? void 0 : _a.call(childProps, event);
|
|
117
|
+
onClick == null ? void 0 : onClick(event);
|
|
118
|
+
},
|
|
119
|
+
() => handleClick()
|
|
120
|
+
),
|
|
121
|
+
onKeyDown: composeEventHandlers(
|
|
122
|
+
(event) => {
|
|
123
|
+
var _a;
|
|
124
|
+
(_a = childProps.onKeyDown) == null ? void 0 : _a.call(childProps, event);
|
|
125
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
126
|
+
},
|
|
127
|
+
(event) => handleKeyDown(event)
|
|
128
|
+
),
|
|
129
|
+
className: [className, childProps.className].filter(Boolean).join(" ")
|
|
98
130
|
});
|
|
99
131
|
}
|
|
100
132
|
return /* @__PURE__ */ jsxs(
|
|
101
133
|
"button",
|
|
102
134
|
{
|
|
135
|
+
...htmlProps,
|
|
103
136
|
type: "button",
|
|
104
|
-
id: triggerId,
|
|
137
|
+
id: htmlProps.id ?? triggerId,
|
|
105
138
|
className: `${styles.trigger} ${className || ""}`,
|
|
106
139
|
"aria-expanded": isOpen,
|
|
107
140
|
"aria-controls": contentId,
|
|
108
141
|
"aria-disabled": disabled || void 0,
|
|
109
|
-
onClick:
|
|
110
|
-
onKeyDown: handleKeyDown,
|
|
142
|
+
onClick: composeEventHandlers(onClick, handleClick),
|
|
143
|
+
onKeyDown: composeEventHandlers(onKeyDown, handleKeyDown),
|
|
111
144
|
disabled,
|
|
112
145
|
children: [
|
|
113
146
|
chevronPosition === "start" && chevronIcon,
|
|
@@ -120,7 +153,8 @@ function CollapsibleTrigger({
|
|
|
120
153
|
function CollapsibleContent({
|
|
121
154
|
children,
|
|
122
155
|
className,
|
|
123
|
-
forceMount = false
|
|
156
|
+
forceMount = false,
|
|
157
|
+
...htmlProps
|
|
124
158
|
}) {
|
|
125
159
|
const { isOpen, contentId, triggerId } = useCollapsibleContext();
|
|
126
160
|
if (!forceMount && !isOpen) {
|
|
@@ -129,7 +163,8 @@ function CollapsibleContent({
|
|
|
129
163
|
return /* @__PURE__ */ jsx(
|
|
130
164
|
"div",
|
|
131
165
|
{
|
|
132
|
-
|
|
166
|
+
...htmlProps,
|
|
167
|
+
id: htmlProps.id ?? contentId,
|
|
133
168
|
role: "region",
|
|
134
169
|
"aria-labelledby": triggerId,
|
|
135
170
|
className: `${styles.content} ${isOpen ? styles.contentOpen : styles.contentClosed} ${className || ""}`,
|