@intlayer/design-system 6.1.5 → 6.1.6
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/.vite/manifest.json +13 -9
- package/dist/Form-CriPBaZk.js.map +1 -1
- package/dist/Form-DJrUK3mm.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.cjs +51 -15
- package/dist/components/Accordion/Accordion.cjs.map +1 -1
- package/dist/components/Accordion/Accordion.d.ts +44 -5
- package/dist/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/components/Accordion/Accordion.mjs +52 -16
- package/dist/components/Accordion/Accordion.mjs.map +1 -1
- package/dist/components/Avatar/index.cjs +114 -31
- package/dist/components/Avatar/index.cjs.map +1 -1
- package/dist/components/Avatar/index.d.ts +46 -2
- package/dist/components/Avatar/index.d.ts.map +1 -1
- package/dist/components/Avatar/index.mjs +115 -32
- package/dist/components/Avatar/index.mjs.map +1 -1
- package/dist/components/Badge/index.cjs +88 -9
- package/dist/components/Badge/index.cjs.map +1 -1
- package/dist/components/Badge/index.d.ts +80 -2
- package/dist/components/Badge/index.d.ts.map +1 -1
- package/dist/components/Badge/index.mjs +89 -10
- package/dist/components/Badge/index.mjs.map +1 -1
- package/dist/components/Breadcrumb/index.cjs +124 -59
- package/dist/components/Breadcrumb/index.cjs.map +1 -1
- package/dist/components/Breadcrumb/index.d.ts +89 -5
- package/dist/components/Breadcrumb/index.d.ts.map +1 -1
- package/dist/components/Breadcrumb/index.mjs +124 -59
- package/dist/components/Breadcrumb/index.mjs.map +1 -1
- package/dist/components/Button/Button.cjs +44 -25
- package/dist/components/Button/Button.cjs.map +1 -1
- package/dist/components/Button/Button.d.ts +95 -1
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.mjs +44 -25
- package/dist/components/Button/Button.mjs.map +1 -1
- package/dist/components/ClickOutsideDiv/index.cjs +38 -7
- package/dist/components/ClickOutsideDiv/index.cjs.map +1 -1
- package/dist/components/ClickOutsideDiv/index.d.ts +13 -0
- package/dist/components/ClickOutsideDiv/index.d.ts.map +1 -1
- package/dist/components/ClickOutsideDiv/index.mjs +39 -8
- package/dist/components/ClickOutsideDiv/index.mjs.map +1 -1
- package/dist/components/Container/index.cjs +2 -0
- package/dist/components/Container/index.cjs.map +1 -1
- package/dist/components/Container/index.d.ts +42 -0
- package/dist/components/Container/index.d.ts.map +1 -1
- package/dist/components/Container/index.mjs +2 -0
- package/dist/components/Container/index.mjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditor.cjs +80 -33
- package/dist/components/ContentEditor/ContentEditor.cjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditor.d.ts +29 -0
- package/dist/components/ContentEditor/ContentEditor.d.ts.map +1 -1
- package/dist/components/ContentEditor/ContentEditor.mjs +80 -33
- package/dist/components/ContentEditor/ContentEditor.mjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditorInput.cjs +58 -31
- package/dist/components/ContentEditor/ContentEditorInput.cjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditorInput.d.ts +33 -0
- package/dist/components/ContentEditor/ContentEditorInput.d.ts.map +1 -1
- package/dist/components/ContentEditor/ContentEditorInput.mjs +58 -31
- package/dist/components/ContentEditor/ContentEditorInput.mjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditorTextArea.cjs +58 -30
- package/dist/components/ContentEditor/ContentEditorTextArea.cjs.map +1 -1
- package/dist/components/ContentEditor/ContentEditorTextArea.d.ts +35 -0
- package/dist/components/ContentEditor/ContentEditorTextArea.d.ts.map +1 -1
- package/dist/components/ContentEditor/ContentEditorTextArea.mjs +59 -31
- package/dist/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
- package/dist/components/ContentEditor/index.cjs +4 -0
- package/dist/components/ContentEditor/index.cjs.map +1 -1
- package/dist/components/ContentEditor/index.d.ts +2 -0
- package/dist/components/ContentEditor/index.d.ts.map +1 -1
- package/dist/components/ContentEditor/index.mjs +5 -1
- package/dist/components/ContentEditor/index.mjs.map +1 -1
- package/dist/components/ContentSelector/ContentSelector.cjs +9 -1
- package/dist/components/ContentSelector/ContentSelector.cjs.map +1 -1
- package/dist/components/ContentSelector/ContentSelector.d.ts +167 -0
- package/dist/components/ContentSelector/ContentSelector.d.ts.map +1 -1
- package/dist/components/ContentSelector/ContentSelector.mjs +9 -1
- package/dist/components/ContentSelector/ContentSelector.mjs.map +1 -1
- package/dist/components/CopyButton/index.cjs +23 -8
- package/dist/components/CopyButton/index.cjs.map +1 -1
- package/dist/components/CopyButton/index.d.ts +78 -0
- package/dist/components/CopyButton/index.d.ts.map +1 -1
- package/dist/components/CopyButton/index.mjs +23 -8
- package/dist/components/CopyButton/index.mjs.map +1 -1
- package/dist/components/CopyToClipboard/index.cjs +58 -22
- package/dist/components/CopyToClipboard/index.cjs.map +1 -1
- package/dist/components/CopyToClipboard/index.d.ts +68 -2
- package/dist/components/CopyToClipboard/index.d.ts.map +1 -1
- package/dist/components/CopyToClipboard/index.mjs +59 -23
- package/dist/components/CopyToClipboard/index.mjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.cjs +4 -2
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.cjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.d.ts +1 -0
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.d.ts.map +1 -1
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +4 -2
- package/dist/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.cjs +2 -2
- package/dist/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.cjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +2 -2
- package/dist/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.cjs +3 -0
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.cjs.map +1 -1
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.d.ts +1 -0
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.d.ts.map +1 -1
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -0
- package/dist/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
- package/dist/components/DropDown/index.cjs +6 -4
- package/dist/components/DropDown/index.cjs.map +1 -1
- package/dist/components/DropDown/index.d.ts +92 -15
- package/dist/components/DropDown/index.d.ts.map +1 -1
- package/dist/components/DropDown/index.mjs +6 -4
- package/dist/components/DropDown/index.mjs.map +1 -1
- package/dist/components/EditableField/EditableFieldInput.cjs.map +1 -1
- package/dist/components/EditableField/EditableFieldInput.d.ts +38 -0
- package/dist/components/EditableField/EditableFieldInput.d.ts.map +1 -1
- package/dist/components/EditableField/EditableFieldInput.mjs.map +1 -1
- package/dist/components/EditableField/EditableFieldLayout.cjs +10 -2
- package/dist/components/EditableField/EditableFieldLayout.cjs.map +1 -1
- package/dist/components/EditableField/EditableFieldLayout.d.ts.map +1 -1
- package/dist/components/EditableField/EditableFieldLayout.mjs +10 -2
- package/dist/components/EditableField/EditableFieldLayout.mjs.map +1 -1
- package/dist/components/EditableField/EditableFieldTextArea.cjs.map +1 -1
- package/dist/components/EditableField/EditableFieldTextArea.d.ts +42 -0
- package/dist/components/EditableField/EditableFieldTextArea.d.ts.map +1 -1
- package/dist/components/EditableField/EditableFieldTextArea.mjs.map +1 -1
- package/dist/components/ExpandCollapse/ExpandCollapse.cjs.map +1 -1
- package/dist/components/ExpandCollapse/ExpandCollapse.d.ts +58 -0
- package/dist/components/ExpandCollapse/ExpandCollapse.d.ts.map +1 -1
- package/dist/components/ExpandCollapse/ExpandCollapse.mjs.map +1 -1
- package/dist/components/Footer/index.cjs.map +1 -1
- package/dist/components/Footer/index.d.ts +101 -0
- package/dist/components/Footer/index.d.ts.map +1 -1
- package/dist/components/Footer/index.mjs.map +1 -1
- package/dist/components/Form/elements/MultiselectElement.d.ts.map +1 -1
- package/dist/components/Form/elements/SelectElement.d.ts.map +1 -1
- package/dist/components/Form/elements/SwitchSelectorElement.d.ts.map +1 -1
- package/dist/components/Headers/index.cjs.map +1 -1
- package/dist/components/Headers/index.d.ts +69 -2
- package/dist/components/Headers/index.d.ts.map +1 -1
- package/dist/components/Headers/index.mjs.map +1 -1
- package/dist/components/HeightResizer/index.cjs +10 -7
- package/dist/components/HeightResizer/index.cjs.map +1 -1
- package/dist/components/HeightResizer/index.d.ts +89 -0
- package/dist/components/HeightResizer/index.d.ts.map +1 -1
- package/dist/components/HeightResizer/index.mjs +10 -7
- package/dist/components/HeightResizer/index.mjs.map +1 -1
- package/dist/components/InformationTag/index.cjs.map +1 -1
- package/dist/components/InformationTag/index.d.ts +72 -0
- package/dist/components/InformationTag/index.d.ts.map +1 -1
- package/dist/components/InformationTag/index.mjs.map +1 -1
- package/dist/components/KeyboardScreenAdapter/index.cjs.map +1 -1
- package/dist/components/KeyboardScreenAdapter/index.d.ts +100 -0
- package/dist/components/KeyboardScreenAdapter/index.d.ts.map +1 -1
- package/dist/components/KeyboardScreenAdapter/index.mjs.map +1 -1
- package/dist/components/Label/index.cjs +25 -3
- package/dist/components/Label/index.cjs.map +1 -1
- package/dist/components/Label/index.d.ts +65 -1
- package/dist/components/Label/index.d.ts.map +1 -1
- package/dist/components/Label/index.mjs +26 -4
- package/dist/components/Label/index.mjs.map +1 -1
- package/dist/components/Link/Link.cjs +0 -4
- package/dist/components/Link/Link.cjs.map +1 -1
- package/dist/components/Link/Link.d.ts +169 -0
- package/dist/components/Link/Link.d.ts.map +1 -1
- package/dist/components/Link/Link.mjs +0 -4
- package/dist/components/Link/Link.mjs.map +1 -1
- package/dist/components/Loader/index.cjs.map +1 -1
- package/dist/components/Loader/index.d.ts +82 -11
- package/dist/components/Loader/index.d.ts.map +1 -1
- package/dist/components/Loader/index.mjs.map +1 -1
- package/dist/components/Loader/spinner.cjs.map +1 -1
- package/dist/components/Loader/spinner.d.ts +56 -0
- package/dist/components/Loader/spinner.d.ts.map +1 -1
- package/dist/components/Loader/spinner.mjs.map +1 -1
- package/dist/components/MarkDownRender/MarkDownRender.cjs +0 -1
- package/dist/components/MarkDownRender/MarkDownRender.cjs.map +1 -1
- package/dist/components/MarkDownRender/MarkDownRender.d.ts +147 -0
- package/dist/components/MarkDownRender/MarkDownRender.d.ts.map +1 -1
- package/dist/components/MarkDownRender/MarkDownRender.mjs +0 -1
- package/dist/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
- package/dist/components/MarkDownRender/processor.cjs +12 -9
- package/dist/components/MarkDownRender/processor.cjs.map +1 -1
- package/dist/components/MarkDownRender/processor.d.ts.map +1 -1
- package/dist/components/MarkDownRender/processor.mjs +12 -9
- package/dist/components/MarkDownRender/processor.mjs.map +1 -1
- package/dist/components/MaxHeightSmoother/index.cjs.map +1 -1
- package/dist/components/MaxHeightSmoother/index.d.ts +152 -0
- package/dist/components/MaxHeightSmoother/index.d.ts.map +1 -1
- package/dist/components/MaxHeightSmoother/index.mjs.map +1 -1
- package/dist/components/Modal/Modal.cjs +5 -0
- package/dist/components/Modal/Modal.cjs.map +1 -1
- package/dist/components/Modal/Modal.d.ts +81 -3
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.mjs +5 -0
- package/dist/components/Modal/Modal.mjs.map +1 -1
- package/dist/components/Navbar/Burger.cjs.map +1 -1
- package/dist/components/Navbar/Burger.d.ts +54 -0
- package/dist/components/Navbar/Burger.d.ts.map +1 -1
- package/dist/components/Navbar/Burger.mjs.map +1 -1
- package/dist/components/Navbar/DesktopNavbar.cjs.map +1 -1
- package/dist/components/Navbar/DesktopNavbar.d.ts +78 -0
- package/dist/components/Navbar/DesktopNavbar.d.ts.map +1 -1
- package/dist/components/Navbar/DesktopNavbar.mjs.map +1 -1
- package/dist/components/Navbar/MobileNavbar.cjs.map +1 -1
- package/dist/components/Navbar/MobileNavbar.d.ts +88 -0
- package/dist/components/Navbar/MobileNavbar.d.ts.map +1 -1
- package/dist/components/Navbar/MobileNavbar.mjs.map +1 -1
- package/dist/components/Navbar/index.cjs.map +1 -1
- package/dist/components/Navbar/index.d.ts +69 -0
- package/dist/components/Navbar/index.d.ts.map +1 -1
- package/dist/components/Navbar/index.mjs.map +1 -1
- package/dist/components/Navbar/useNavigation.cjs +8 -1
- package/dist/components/Navbar/useNavigation.cjs.map +1 -1
- package/dist/components/Navbar/useNavigation.d.ts +83 -0
- package/dist/components/Navbar/useNavigation.d.ts.map +1 -1
- package/dist/components/Navbar/useNavigation.mjs +8 -1
- package/dist/components/Navbar/useNavigation.mjs.map +1 -1
- package/dist/components/Pattern/DotPattern.cjs.map +1 -1
- package/dist/components/Pattern/DotPattern.d.ts +101 -0
- package/dist/components/Pattern/DotPattern.d.ts.map +1 -1
- package/dist/components/Pattern/DotPattern.mjs.map +1 -1
- package/dist/components/Pattern/GridPattern.cjs.map +1 -1
- package/dist/components/Pattern/GridPattern.d.ts +114 -0
- package/dist/components/Pattern/GridPattern.d.ts.map +1 -1
- package/dist/components/Pattern/GridPattern.mjs.map +1 -1
- package/dist/components/Pattern/SpotLight.cjs.map +1 -1
- package/dist/components/Pattern/SpotLight.d.ts +125 -0
- package/dist/components/Pattern/SpotLight.d.ts.map +1 -1
- package/dist/components/Pattern/SpotLight.mjs.map +1 -1
- package/dist/components/Popover/index.cjs +10 -10
- package/dist/components/Popover/index.cjs.map +1 -1
- package/dist/components/Popover/index.d.ts +110 -15
- package/dist/components/Popover/index.d.ts.map +1 -1
- package/dist/components/Popover/index.mjs +10 -10
- package/dist/components/Popover/index.mjs.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.cjs +22 -5
- package/dist/components/PressableSpan/PressableSpan.cjs.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.d.ts +105 -3
- package/dist/components/PressableSpan/PressableSpan.d.ts.map +1 -1
- package/dist/components/PressableSpan/PressableSpan.mjs +22 -5
- package/dist/components/PressableSpan/PressableSpan.mjs.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.cjs.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.d.ts +182 -0
- package/dist/components/RightDrawer/RightDrawer.d.ts.map +1 -1
- package/dist/components/RightDrawer/RightDrawer.mjs.map +1 -1
- package/dist/components/RightDrawer/isElementAtTopAndNotCovered.cjs.map +1 -1
- package/dist/components/RightDrawer/isElementAtTopAndNotCovered.d.ts +44 -0
- package/dist/components/RightDrawer/isElementAtTopAndNotCovered.d.ts.map +1 -1
- package/dist/components/RightDrawer/isElementAtTopAndNotCovered.mjs.map +1 -1
- package/dist/components/RightDrawer/useRightDrawerStore.cjs.map +1 -1
- package/dist/components/RightDrawer/useRightDrawerStore.d.ts +102 -0
- package/dist/components/RightDrawer/useRightDrawerStore.d.ts.map +1 -1
- package/dist/components/RightDrawer/useRightDrawerStore.mjs.map +1 -1
- package/dist/components/Select/Multiselect.cjs.map +1 -1
- package/dist/components/Select/Multiselect.d.ts +125 -18
- package/dist/components/Select/Multiselect.d.ts.map +1 -1
- package/dist/components/Select/Multiselect.mjs.map +1 -1
- package/dist/components/Select/Select.cjs.map +1 -1
- package/dist/components/Select/Select.d.ts +214 -7
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.mjs.map +1 -1
- package/dist/components/SwitchSelector/index.cjs.map +1 -1
- package/dist/components/SwitchSelector/index.d.ts +157 -8
- package/dist/components/SwitchSelector/index.d.ts.map +1 -1
- package/dist/components/SwitchSelector/index.mjs.map +1 -1
- package/dist/components/Table/Table.cjs.map +1 -1
- package/dist/components/Table/Table.d.ts +184 -0
- package/dist/components/Table/Table.d.ts.map +1 -1
- package/dist/components/Table/Table.mjs.map +1 -1
- package/dist/components/Tag/index.cjs.map +1 -1
- package/dist/components/Tag/index.d.ts +223 -0
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.mjs.map +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.cjs.map +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.d.ts +91 -0
- package/dist/components/TextArea/AutoSizeTextArea.d.ts.map +1 -1
- package/dist/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
- package/dist/components/TextArea/AutocompleteTextArea.cjs.map +1 -1
- package/dist/components/TextArea/AutocompleteTextArea.d.ts +145 -0
- package/dist/components/TextArea/AutocompleteTextArea.d.ts.map +1 -1
- package/dist/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
- package/dist/components/TextArea/TextArea.cjs.map +1 -1
- package/dist/components/TextArea/TextArea.d.ts +74 -0
- package/dist/components/TextArea/TextArea.d.ts.map +1 -1
- package/dist/components/TextArea/TextArea.mjs.map +1 -1
- package/dist/components/Toaster/Toast.cjs +4 -0
- package/dist/components/Toaster/Toast.cjs.map +1 -1
- package/dist/components/Toaster/Toast.d.ts +148 -2
- package/dist/components/Toaster/Toast.d.ts.map +1 -1
- package/dist/components/Toaster/Toast.mjs +4 -0
- package/dist/components/Toaster/Toast.mjs.map +1 -1
- package/dist/components/Toaster/Toaster.cjs.map +1 -1
- package/dist/components/Toaster/Toaster.d.ts +42 -0
- package/dist/components/Toaster/Toaster.d.ts.map +1 -1
- package/dist/components/Toaster/Toaster.mjs.map +1 -1
- package/dist/components/Toaster/useToast.cjs.map +1 -1
- package/dist/components/Toaster/useToast.d.ts +199 -2
- package/dist/components/Toaster/useToast.d.ts.map +1 -1
- package/dist/components/Toaster/useToast.mjs.map +1 -1
- package/dist/components/WithResizer/index.cjs.map +1 -1
- package/dist/components/WithResizer/index.d.ts +143 -0
- package/dist/components/WithResizer/index.d.ts.map +1 -1
- package/dist/components/WithResizer/index.mjs.map +1 -1
- package/dist/components/index.cjs +2 -2
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.mjs +4 -4
- package/dist/components/index.mjs.map +1 -1
- package/dist/hooks/auth.cjs +2 -2
- package/dist/hooks/auth.cjs.map +1 -1
- package/dist/hooks/auth.mjs +2 -2
- package/dist/hooks/auth.mjs.map +1 -1
- package/dist/hooks/reactQuery.cjs +2 -1
- package/dist/hooks/reactQuery.cjs.map +1 -1
- package/dist/hooks/reactQuery.d.ts +1 -1
- package/dist/hooks/reactQuery.d.ts.map +1 -1
- package/dist/hooks/reactQuery.mjs +2 -1
- package/dist/hooks/reactQuery.mjs.map +1 -1
- package/dist/hooks/useAuth/useOAuth2.cjs +3 -3
- package/dist/hooks/useAuth/useOAuth2.cjs.map +1 -1
- package/dist/hooks/useAuth/useOAuth2.mjs +3 -3
- package/dist/hooks/useAuth/useOAuth2.mjs.map +1 -1
- package/dist/hooks/useAuth/useSession.cjs +3 -3
- package/dist/hooks/useAuth/useSession.cjs.map +1 -1
- package/dist/hooks/useAuth/useSession.mjs +3 -3
- package/dist/hooks/useAuth/useSession.mjs.map +1 -1
- package/dist/utils/image.cjs +30 -0
- package/dist/utils/image.cjs.map +1 -0
- package/dist/utils/image.d.ts +37 -0
- package/dist/utils/image.d.ts.map +1 -0
- package/dist/utils/image.mjs +30 -0
- package/dist/utils/image.mjs.map +1 -0
- package/package.json +20 -18
- package/dist/utils/capitalize.cjs +0 -10
- package/dist/utils/capitalize.cjs.map +0 -1
- package/dist/utils/capitalize.d.ts +0 -2
- package/dist/utils/capitalize.d.ts.map +0 -1
- package/dist/utils/capitalize.mjs +0 -10
- package/dist/utils/capitalize.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\n\ninterface MaxHeightSmootherProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n isHidden?: boolean;\n isOverable?: boolean;\n isFocusable?: boolean;\n minHeight?: number;\n}\n\nexport const MaxHeightSmoother: FC<MaxHeightSmootherProps> = ({\n children,\n isHidden,\n className = '',\n isOverable = false,\n isFocusable = false,\n minHeight = 0,\n ...props\n}) => (\n <div\n aria-hidden={isFocusable ? isHidden : undefined}\n tabIndex={isFocusable ? 0 : undefined}\n role={isFocusable ? 'button' : 'none'}\n className={cn(\n 'group/height-smoother relative grid w-full grid-rows-[0fr] overflow-hidden transition-all duration-700 ease-in-out',\n typeof isHidden !== 'undefined' &&\n !isHidden &&\n 'grid-rows-[1fr] overflow-x-auto',\n isOverable && 'hover:grid-rows-[1fr] hover:overflow-x-auto',\n isFocusable &&\n 'focus-within:grid-rows-[1fr] focus-within:overflow-x-auto focus:grid-rows-[1fr] focus:overflow-x-auto',\n className\n )}\n {...props}\n >\n <div\n style={{\n minHeight: `${minHeight}px`,\n }}\n className={cn(\n isOverable && 'group-hover/height-smoother:visible',\n isFocusable && 'group-focus/height-smoother:visible',\n className\n )}\n >\n {children}\n </div>\n </div>\n);\n"],"names":["jsx","cn"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the MaxHeightSmoother component\n */\ninterface MaxHeightSmootherProps extends HTMLAttributes<HTMLDivElement> {\n /** Content to render within the smoother container */\n children: ReactNode;\n /** Controls collapse state. When true, content is collapsed; when false, expanded; when undefined, relies on hover/focus behavior */\n isHidden?: boolean;\n /** Enable expand-on-hover behavior */\n isOverable?: boolean;\n /** Enable expand-on-focus behavior for accessibility and keyboard navigation */\n isFocusable?: boolean;\n /** Minimum height in pixels for the collapsed state */\n minHeight?: number;\n}\n\n/**\n * MaxHeightSmoother Component\n *\n * A sophisticated container component that provides smooth height transitions\n * for collapsible content. Uses CSS Grid's fractional rows to create fluid\n * animations without JavaScript height calculations, making it performant\n * and smooth across all devices and screen sizes.\n *\n * @component\n * @example\n * Basic controlled usage:\n * ```tsx\n * const [isCollapsed, setIsCollapsed] = useState(true);\n *\n * <MaxHeightSmoother isHidden={isCollapsed}>\n * <div>Your collapsible content here</div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Hover-triggered expansion:\n * ```tsx\n * <MaxHeightSmoother isOverable={true}>\n * <div>\n * <p>This content expands when you hover over the container.</p>\n * <p>Perfect for preview cards or tooltips.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Accessible focus-triggered expansion:\n * ```tsx\n * <MaxHeightSmoother isFocusable={true}>\n * <div>\n * <h3>Expandable Section</h3>\n * <p>Tab to focus this container to expand the content.</p>\n * <p>Great for accessible progressive disclosure.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * With minimum height for preview:\n * ```tsx\n * <MaxHeightSmoother\n * isOverable={true}\n * minHeight={100}\n * className=\"border rounded-lg p-4\"\n * >\n * <div>\n * <h3>Article Preview</h3>\n * <p>This article preview shows the first few lines...</p>\n * <p>Hover to see the full content with smooth expansion.</p>\n * <p>The minHeight ensures some content is always visible.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Combined hover and focus behavior:\n * ```tsx\n * <MaxHeightSmoother\n * isOverable={true}\n * isFocusable={true}\n * minHeight={80}\n * >\n * <div>\n * <h4>Interactive Card</h4>\n * <p>Expands on both hover and keyboard focus.</p>\n * <p>Accessible to both mouse and keyboard users.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * Features:\n * - Smooth CSS Grid-based height transitions (700ms duration)\n * - Three interaction modes: controlled, hover, and focus\n * - Configurable minimum height for collapsed state\n * - Accessible keyboard navigation support\n * - Overflow handling with smooth scrolling\n * - ARIA attributes for screen reader compatibility\n * - Performance-optimized with CSS-only animations\n * - Responsive design that works on all screen sizes\n *\n * Animation Technique:\n * Uses CSS Grid `grid-rows-[0fr]` to `grid-rows-[1fr]` transitions\n * instead of height animations, which provides:\n * - Smooth animations without knowing content height\n * - Better performance (no layout recalculations)\n * - More reliable across different content types\n * - Automatic adaptation to dynamic content changes\n *\n * Interaction Modes:\n * 1. **Controlled**: Use `isHidden` prop for external state control\n * 2. **Hover**: Set `isOverable={true}` for mouse hover expansion\n * 3. **Focus**: Set `isFocusable={true}` for keyboard focus expansion\n * 4. **Combined**: Use both `isOverable` and `isFocusable` together\n *\n * Accessibility Features:\n * - `role=\"button\"` when focusable for proper screen reader context\n * - `tabIndex={0}` for keyboard navigation when focusable\n * - `aria-hidden` attribute for screen reader control\n * - Semantic focus management with focus-within pseudo-class\n * - High contrast focus indicators\n * - Respects prefers-reduced-motion settings\n *\n * Use Cases:\n * - FAQ accordions and expandable sections\n * - Article previews and read-more functionality\n * - Card hover effects and content previews\n * - Progressive disclosure for complex forms\n * - Tooltip and popover content containers\n * - Mobile-friendly collapsible navigation\n * - Dashboard widget expansion\n * - Email preview in mail clients\n *\n * Performance Considerations:\n * - Pure CSS animations (no JavaScript timer overhead)\n * - GPU acceleration through transform-based animations\n * - Minimal repaints and layout shifts\n * - Efficient event handling with CSS pseudo-classes\n * - No DOM measurements or calculations required\n *\n * @param props - Component props extending HTML div attributes\n * @param props.children - Content to render within the container\n * @param props.isHidden - Controlled collapse state (true=collapsed, false=expanded)\n * @param props.isOverable - Enable hover-to-expand behavior\n * @param props.isFocusable - Enable focus-to-expand behavior with keyboard navigation\n * @param props.minHeight - Minimum height in pixels for collapsed state (default: 0)\n * @param props.className - Additional CSS classes for styling\n * @param props.style - Inline styles (note: minHeight style will be applied)\n * @param props.role - ARIA role (automatically set to \"button\" when focusable)\n * @param props.tabIndex - Tab index (automatically set to 0 when focusable)\n * @param props.aria-hidden - ARIA hidden state (controlled by isHidden when focusable)\n * @param props.onClick - Click event handler\n * @param props.onMouseEnter - Mouse enter event handler\n * @param props.onMouseLeave - Mouse leave event handler\n * @param props.onFocus - Focus event handler\n * @param props.onBlur - Blur event handler\n * @param props...rest - All other standard HTML div attributes\n *\n * @returns A smooth height-transitioning container with configurable interaction modes\n */\nexport const MaxHeightSmoother: FC<MaxHeightSmootherProps> = ({\n children,\n isHidden,\n className = '',\n isOverable = false,\n isFocusable = false,\n minHeight = 0,\n ...props\n}) => (\n <div\n aria-hidden={isFocusable ? isHidden : undefined}\n tabIndex={isFocusable ? 0 : undefined}\n role={isFocusable ? 'button' : 'none'}\n className={cn(\n 'group/height-smoother relative grid w-full grid-rows-[0fr] overflow-hidden transition-all duration-700 ease-in-out',\n typeof isHidden !== 'undefined' &&\n !isHidden &&\n 'grid-rows-[1fr] overflow-x-auto',\n isOverable && 'hover:grid-rows-[1fr] hover:overflow-x-auto',\n isFocusable &&\n 'focus-within:grid-rows-[1fr] focus-within:overflow-x-auto focus:grid-rows-[1fr] focus:overflow-x-auto',\n className\n )}\n {...props}\n >\n <div\n style={{\n minHeight: `${minHeight}px`,\n }}\n className={cn(\n isOverable && 'group-hover/height-smoother:visible',\n isFocusable && 'group-focus/height-smoother:visible',\n className\n )}\n >\n {children}\n </div>\n </div>\n);\n"],"names":["jsx","cn"],"mappings":";;;;AAmKO,MAAM,oBAAgD,CAAC;AAAA,EAC5D;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,GAAG;AACL,MACEA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,eAAa,cAAc,WAAW;AAAA,IACtC,UAAU,cAAc,IAAI;AAAA,IAC5B,MAAM,cAAc,WAAW;AAAA,IAC/B,WAAWC,SAAAA;AAAAA,MACT;AAAA,MACA,OAAO,aAAa,eAClB,CAAC,YACD;AAAA,MACF,cAAc;AAAA,MACd,eACE;AAAA,MACF;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,IAEJ,UAAAD,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,WAAW,GAAG,SAAS;AAAA,QAAA;AAAA,QAEzB,WAAWC,SAAAA;AAAAA,UACT,cAAc;AAAA,UACd,eAAe;AAAA,UACf;AAAA,QAAA;AAAA,QAGD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;;"}
|
|
@@ -1,11 +1,163 @@
|
|
|
1
1
|
import { FC, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the MaxHeightSmoother component
|
|
4
|
+
*/
|
|
2
5
|
interface MaxHeightSmootherProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/** Content to render within the smoother container */
|
|
3
7
|
children: ReactNode;
|
|
8
|
+
/** Controls collapse state. When true, content is collapsed; when false, expanded; when undefined, relies on hover/focus behavior */
|
|
4
9
|
isHidden?: boolean;
|
|
10
|
+
/** Enable expand-on-hover behavior */
|
|
5
11
|
isOverable?: boolean;
|
|
12
|
+
/** Enable expand-on-focus behavior for accessibility and keyboard navigation */
|
|
6
13
|
isFocusable?: boolean;
|
|
14
|
+
/** Minimum height in pixels for the collapsed state */
|
|
7
15
|
minHeight?: number;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* MaxHeightSmoother Component
|
|
19
|
+
*
|
|
20
|
+
* A sophisticated container component that provides smooth height transitions
|
|
21
|
+
* for collapsible content. Uses CSS Grid's fractional rows to create fluid
|
|
22
|
+
* animations without JavaScript height calculations, making it performant
|
|
23
|
+
* and smooth across all devices and screen sizes.
|
|
24
|
+
*
|
|
25
|
+
* @component
|
|
26
|
+
* @example
|
|
27
|
+
* Basic controlled usage:
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const [isCollapsed, setIsCollapsed] = useState(true);
|
|
30
|
+
*
|
|
31
|
+
* <MaxHeightSmoother isHidden={isCollapsed}>
|
|
32
|
+
* <div>Your collapsible content here</div>
|
|
33
|
+
* </MaxHeightSmoother>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* Hover-triggered expansion:
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <MaxHeightSmoother isOverable={true}>
|
|
40
|
+
* <div>
|
|
41
|
+
* <p>This content expands when you hover over the container.</p>
|
|
42
|
+
* <p>Perfect for preview cards or tooltips.</p>
|
|
43
|
+
* </div>
|
|
44
|
+
* </MaxHeightSmoother>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* Accessible focus-triggered expansion:
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <MaxHeightSmoother isFocusable={true}>
|
|
51
|
+
* <div>
|
|
52
|
+
* <h3>Expandable Section</h3>
|
|
53
|
+
* <p>Tab to focus this container to expand the content.</p>
|
|
54
|
+
* <p>Great for accessible progressive disclosure.</p>
|
|
55
|
+
* </div>
|
|
56
|
+
* </MaxHeightSmoother>
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* With minimum height for preview:
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <MaxHeightSmoother
|
|
63
|
+
* isOverable={true}
|
|
64
|
+
* minHeight={100}
|
|
65
|
+
* className="border rounded-lg p-4"
|
|
66
|
+
* >
|
|
67
|
+
* <div>
|
|
68
|
+
* <h3>Article Preview</h3>
|
|
69
|
+
* <p>This article preview shows the first few lines...</p>
|
|
70
|
+
* <p>Hover to see the full content with smooth expansion.</p>
|
|
71
|
+
* <p>The minHeight ensures some content is always visible.</p>
|
|
72
|
+
* </div>
|
|
73
|
+
* </MaxHeightSmoother>
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* Combined hover and focus behavior:
|
|
78
|
+
* ```tsx
|
|
79
|
+
* <MaxHeightSmoother
|
|
80
|
+
* isOverable={true}
|
|
81
|
+
* isFocusable={true}
|
|
82
|
+
* minHeight={80}
|
|
83
|
+
* >
|
|
84
|
+
* <div>
|
|
85
|
+
* <h4>Interactive Card</h4>
|
|
86
|
+
* <p>Expands on both hover and keyboard focus.</p>
|
|
87
|
+
* <p>Accessible to both mouse and keyboard users.</p>
|
|
88
|
+
* </div>
|
|
89
|
+
* </MaxHeightSmoother>
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* Features:
|
|
93
|
+
* - Smooth CSS Grid-based height transitions (700ms duration)
|
|
94
|
+
* - Three interaction modes: controlled, hover, and focus
|
|
95
|
+
* - Configurable minimum height for collapsed state
|
|
96
|
+
* - Accessible keyboard navigation support
|
|
97
|
+
* - Overflow handling with smooth scrolling
|
|
98
|
+
* - ARIA attributes for screen reader compatibility
|
|
99
|
+
* - Performance-optimized with CSS-only animations
|
|
100
|
+
* - Responsive design that works on all screen sizes
|
|
101
|
+
*
|
|
102
|
+
* Animation Technique:
|
|
103
|
+
* Uses CSS Grid `grid-rows-[0fr]` to `grid-rows-[1fr]` transitions
|
|
104
|
+
* instead of height animations, which provides:
|
|
105
|
+
* - Smooth animations without knowing content height
|
|
106
|
+
* - Better performance (no layout recalculations)
|
|
107
|
+
* - More reliable across different content types
|
|
108
|
+
* - Automatic adaptation to dynamic content changes
|
|
109
|
+
*
|
|
110
|
+
* Interaction Modes:
|
|
111
|
+
* 1. **Controlled**: Use `isHidden` prop for external state control
|
|
112
|
+
* 2. **Hover**: Set `isOverable={true}` for mouse hover expansion
|
|
113
|
+
* 3. **Focus**: Set `isFocusable={true}` for keyboard focus expansion
|
|
114
|
+
* 4. **Combined**: Use both `isOverable` and `isFocusable` together
|
|
115
|
+
*
|
|
116
|
+
* Accessibility Features:
|
|
117
|
+
* - `role="button"` when focusable for proper screen reader context
|
|
118
|
+
* - `tabIndex={0}` for keyboard navigation when focusable
|
|
119
|
+
* - `aria-hidden` attribute for screen reader control
|
|
120
|
+
* - Semantic focus management with focus-within pseudo-class
|
|
121
|
+
* - High contrast focus indicators
|
|
122
|
+
* - Respects prefers-reduced-motion settings
|
|
123
|
+
*
|
|
124
|
+
* Use Cases:
|
|
125
|
+
* - FAQ accordions and expandable sections
|
|
126
|
+
* - Article previews and read-more functionality
|
|
127
|
+
* - Card hover effects and content previews
|
|
128
|
+
* - Progressive disclosure for complex forms
|
|
129
|
+
* - Tooltip and popover content containers
|
|
130
|
+
* - Mobile-friendly collapsible navigation
|
|
131
|
+
* - Dashboard widget expansion
|
|
132
|
+
* - Email preview in mail clients
|
|
133
|
+
*
|
|
134
|
+
* Performance Considerations:
|
|
135
|
+
* - Pure CSS animations (no JavaScript timer overhead)
|
|
136
|
+
* - GPU acceleration through transform-based animations
|
|
137
|
+
* - Minimal repaints and layout shifts
|
|
138
|
+
* - Efficient event handling with CSS pseudo-classes
|
|
139
|
+
* - No DOM measurements or calculations required
|
|
140
|
+
*
|
|
141
|
+
* @param props - Component props extending HTML div attributes
|
|
142
|
+
* @param props.children - Content to render within the container
|
|
143
|
+
* @param props.isHidden - Controlled collapse state (true=collapsed, false=expanded)
|
|
144
|
+
* @param props.isOverable - Enable hover-to-expand behavior
|
|
145
|
+
* @param props.isFocusable - Enable focus-to-expand behavior with keyboard navigation
|
|
146
|
+
* @param props.minHeight - Minimum height in pixels for collapsed state (default: 0)
|
|
147
|
+
* @param props.className - Additional CSS classes for styling
|
|
148
|
+
* @param props.style - Inline styles (note: minHeight style will be applied)
|
|
149
|
+
* @param props.role - ARIA role (automatically set to "button" when focusable)
|
|
150
|
+
* @param props.tabIndex - Tab index (automatically set to 0 when focusable)
|
|
151
|
+
* @param props.aria-hidden - ARIA hidden state (controlled by isHidden when focusable)
|
|
152
|
+
* @param props.onClick - Click event handler
|
|
153
|
+
* @param props.onMouseEnter - Mouse enter event handler
|
|
154
|
+
* @param props.onMouseLeave - Mouse leave event handler
|
|
155
|
+
* @param props.onFocus - Focus event handler
|
|
156
|
+
* @param props.onBlur - Blur event handler
|
|
157
|
+
* @param props...rest - All other standard HTML div attributes
|
|
158
|
+
*
|
|
159
|
+
* @returns A smooth height-transitioning container with configurable interaction modes
|
|
160
|
+
*/
|
|
9
161
|
export declare const MaxHeightSmoother: FC<MaxHeightSmootherProps>;
|
|
10
162
|
export {};
|
|
11
163
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3D,UAAU,sBAAuB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACrE,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAsCxD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG3D;;GAEG;AACH,UAAU,sBAAuB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACrE,sDAAsD;IACtD,QAAQ,EAAE,SAAS,CAAC;IACpB,qIAAqI;IACrI,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+IG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAsCxD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\n\ninterface MaxHeightSmootherProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n isHidden?: boolean;\n isOverable?: boolean;\n isFocusable?: boolean;\n minHeight?: number;\n}\n\nexport const MaxHeightSmoother: FC<MaxHeightSmootherProps> = ({\n children,\n isHidden,\n className = '',\n isOverable = false,\n isFocusable = false,\n minHeight = 0,\n ...props\n}) => (\n <div\n aria-hidden={isFocusable ? isHidden : undefined}\n tabIndex={isFocusable ? 0 : undefined}\n role={isFocusable ? 'button' : 'none'}\n className={cn(\n 'group/height-smoother relative grid w-full grid-rows-[0fr] overflow-hidden transition-all duration-700 ease-in-out',\n typeof isHidden !== 'undefined' &&\n !isHidden &&\n 'grid-rows-[1fr] overflow-x-auto',\n isOverable && 'hover:grid-rows-[1fr] hover:overflow-x-auto',\n isFocusable &&\n 'focus-within:grid-rows-[1fr] focus-within:overflow-x-auto focus:grid-rows-[1fr] focus:overflow-x-auto',\n className\n )}\n {...props}\n >\n <div\n style={{\n minHeight: `${minHeight}px`,\n }}\n className={cn(\n isOverable && 'group-hover/height-smoother:visible',\n isFocusable && 'group-focus/height-smoother:visible',\n className\n )}\n >\n {children}\n </div>\n </div>\n);\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../src/components/MaxHeightSmoother/index.tsx"],"sourcesContent":["import type { FC, HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the MaxHeightSmoother component\n */\ninterface MaxHeightSmootherProps extends HTMLAttributes<HTMLDivElement> {\n /** Content to render within the smoother container */\n children: ReactNode;\n /** Controls collapse state. When true, content is collapsed; when false, expanded; when undefined, relies on hover/focus behavior */\n isHidden?: boolean;\n /** Enable expand-on-hover behavior */\n isOverable?: boolean;\n /** Enable expand-on-focus behavior for accessibility and keyboard navigation */\n isFocusable?: boolean;\n /** Minimum height in pixels for the collapsed state */\n minHeight?: number;\n}\n\n/**\n * MaxHeightSmoother Component\n *\n * A sophisticated container component that provides smooth height transitions\n * for collapsible content. Uses CSS Grid's fractional rows to create fluid\n * animations without JavaScript height calculations, making it performant\n * and smooth across all devices and screen sizes.\n *\n * @component\n * @example\n * Basic controlled usage:\n * ```tsx\n * const [isCollapsed, setIsCollapsed] = useState(true);\n *\n * <MaxHeightSmoother isHidden={isCollapsed}>\n * <div>Your collapsible content here</div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Hover-triggered expansion:\n * ```tsx\n * <MaxHeightSmoother isOverable={true}>\n * <div>\n * <p>This content expands when you hover over the container.</p>\n * <p>Perfect for preview cards or tooltips.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Accessible focus-triggered expansion:\n * ```tsx\n * <MaxHeightSmoother isFocusable={true}>\n * <div>\n * <h3>Expandable Section</h3>\n * <p>Tab to focus this container to expand the content.</p>\n * <p>Great for accessible progressive disclosure.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * With minimum height for preview:\n * ```tsx\n * <MaxHeightSmoother\n * isOverable={true}\n * minHeight={100}\n * className=\"border rounded-lg p-4\"\n * >\n * <div>\n * <h3>Article Preview</h3>\n * <p>This article preview shows the first few lines...</p>\n * <p>Hover to see the full content with smooth expansion.</p>\n * <p>The minHeight ensures some content is always visible.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * @example\n * Combined hover and focus behavior:\n * ```tsx\n * <MaxHeightSmoother\n * isOverable={true}\n * isFocusable={true}\n * minHeight={80}\n * >\n * <div>\n * <h4>Interactive Card</h4>\n * <p>Expands on both hover and keyboard focus.</p>\n * <p>Accessible to both mouse and keyboard users.</p>\n * </div>\n * </MaxHeightSmoother>\n * ```\n *\n * Features:\n * - Smooth CSS Grid-based height transitions (700ms duration)\n * - Three interaction modes: controlled, hover, and focus\n * - Configurable minimum height for collapsed state\n * - Accessible keyboard navigation support\n * - Overflow handling with smooth scrolling\n * - ARIA attributes for screen reader compatibility\n * - Performance-optimized with CSS-only animations\n * - Responsive design that works on all screen sizes\n *\n * Animation Technique:\n * Uses CSS Grid `grid-rows-[0fr]` to `grid-rows-[1fr]` transitions\n * instead of height animations, which provides:\n * - Smooth animations without knowing content height\n * - Better performance (no layout recalculations)\n * - More reliable across different content types\n * - Automatic adaptation to dynamic content changes\n *\n * Interaction Modes:\n * 1. **Controlled**: Use `isHidden` prop for external state control\n * 2. **Hover**: Set `isOverable={true}` for mouse hover expansion\n * 3. **Focus**: Set `isFocusable={true}` for keyboard focus expansion\n * 4. **Combined**: Use both `isOverable` and `isFocusable` together\n *\n * Accessibility Features:\n * - `role=\"button\"` when focusable for proper screen reader context\n * - `tabIndex={0}` for keyboard navigation when focusable\n * - `aria-hidden` attribute for screen reader control\n * - Semantic focus management with focus-within pseudo-class\n * - High contrast focus indicators\n * - Respects prefers-reduced-motion settings\n *\n * Use Cases:\n * - FAQ accordions and expandable sections\n * - Article previews and read-more functionality\n * - Card hover effects and content previews\n * - Progressive disclosure for complex forms\n * - Tooltip and popover content containers\n * - Mobile-friendly collapsible navigation\n * - Dashboard widget expansion\n * - Email preview in mail clients\n *\n * Performance Considerations:\n * - Pure CSS animations (no JavaScript timer overhead)\n * - GPU acceleration through transform-based animations\n * - Minimal repaints and layout shifts\n * - Efficient event handling with CSS pseudo-classes\n * - No DOM measurements or calculations required\n *\n * @param props - Component props extending HTML div attributes\n * @param props.children - Content to render within the container\n * @param props.isHidden - Controlled collapse state (true=collapsed, false=expanded)\n * @param props.isOverable - Enable hover-to-expand behavior\n * @param props.isFocusable - Enable focus-to-expand behavior with keyboard navigation\n * @param props.minHeight - Minimum height in pixels for collapsed state (default: 0)\n * @param props.className - Additional CSS classes for styling\n * @param props.style - Inline styles (note: minHeight style will be applied)\n * @param props.role - ARIA role (automatically set to \"button\" when focusable)\n * @param props.tabIndex - Tab index (automatically set to 0 when focusable)\n * @param props.aria-hidden - ARIA hidden state (controlled by isHidden when focusable)\n * @param props.onClick - Click event handler\n * @param props.onMouseEnter - Mouse enter event handler\n * @param props.onMouseLeave - Mouse leave event handler\n * @param props.onFocus - Focus event handler\n * @param props.onBlur - Blur event handler\n * @param props...rest - All other standard HTML div attributes\n *\n * @returns A smooth height-transitioning container with configurable interaction modes\n */\nexport const MaxHeightSmoother: FC<MaxHeightSmootherProps> = ({\n children,\n isHidden,\n className = '',\n isOverable = false,\n isFocusable = false,\n minHeight = 0,\n ...props\n}) => (\n <div\n aria-hidden={isFocusable ? isHidden : undefined}\n tabIndex={isFocusable ? 0 : undefined}\n role={isFocusable ? 'button' : 'none'}\n className={cn(\n 'group/height-smoother relative grid w-full grid-rows-[0fr] overflow-hidden transition-all duration-700 ease-in-out',\n typeof isHidden !== 'undefined' &&\n !isHidden &&\n 'grid-rows-[1fr] overflow-x-auto',\n isOverable && 'hover:grid-rows-[1fr] hover:overflow-x-auto',\n isFocusable &&\n 'focus-within:grid-rows-[1fr] focus-within:overflow-x-auto focus:grid-rows-[1fr] focus:overflow-x-auto',\n className\n )}\n {...props}\n >\n <div\n style={{\n minHeight: `${minHeight}px`,\n }}\n className={cn(\n isOverable && 'group-hover/height-smoother:visible',\n isFocusable && 'group-focus/height-smoother:visible',\n className\n )}\n >\n {children}\n </div>\n </div>\n);\n"],"names":[],"mappings":";;AAmKO,MAAM,oBAAgD,CAAC;AAAA,EAC5D;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,eAAa,cAAc,WAAW;AAAA,IACtC,UAAU,cAAc,IAAI;AAAA,IAC5B,MAAM,cAAc,WAAW;AAAA,IAC/B,WAAW;AAAA,MACT;AAAA,MACA,OAAO,aAAa,eAClB,CAAC,YACD;AAAA,MACF,cAAc;AAAA,MACd,eACE;AAAA,MACF;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,WAAW,GAAG,SAAS;AAAA,QAAA;AAAA,QAEzB,WAAW;AAAA,UACT,cAAc;AAAA,UACd,eAAe;AAAA,UACf;AAAA,QAAA;AAAA,QAGD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH;AACF;"}
|
|
@@ -31,10 +31,15 @@ const modalVariants = classVarianceAuthority.cva(
|
|
|
31
31
|
{
|
|
32
32
|
variants: {
|
|
33
33
|
size: {
|
|
34
|
+
/** Small modal: height auto, max-height 30vh, width 95vw, max-width xl */
|
|
34
35
|
sm: "h-auto max-h-[30vh] w-[95vw] max-w-xl",
|
|
36
|
+
/** Medium modal: height auto, max-height 50vh, width 95vw, max-width xl */
|
|
35
37
|
md: "h-auto max-h-[50vh] w-[95vw] max-w-xl",
|
|
38
|
+
/** Large modal: height auto, max-height 70vh, width 95vw, max-width 2xl */
|
|
36
39
|
lg: "h-auto max-h-[70vh] w-[95vw] max-w-2xl",
|
|
40
|
+
/** Extra large modal: height auto, max-height 95vh, width 95vw, max-width 6xl */
|
|
37
41
|
xl: "h-auto max-h-[95vh] w-[95vw] max-w-6xl",
|
|
42
|
+
/** Unset modal: height auto, max-height 95vh, width 95vw, no max-width */
|
|
38
43
|
unset: "h-auto max-h-[95vh] w-[95vw]"
|
|
39
44
|
}
|
|
40
45
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.cjs","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { motion as m } from 'framer-motion';\nimport { X } from 'lucide-react';\nimport { ReactNode, type FC } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useGetElementOrWindow, useScrollBlockage } from '../../hooks/index';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container, type ContainerProps } from '../Container';\nimport { H3 } from '../Headers';\n\nexport enum ModalSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n UNSET = 'unset',\n}\n\ntype ModalProps = {\n children: ReactNode;\n isOpen: boolean;\n onClose?: () => void;\n container?: HTMLElement;\n disableScroll?: boolean;\n hasCloseButton?: boolean;\n title?: string;\n size?: ModalSize | `${ModalSize}`;\n} & Pick<\n ContainerProps,\n | 'className'\n | 'transparency'\n | 'border'\n | 'background'\n | 'roundedSize'\n | 'borderColor'\n | 'padding'\n | 'separator'\n | 'gap'\n>;\n\nconst modalVariants = cva(\n 'cursor-default overflow-auto py-3 shadow-sm justify-center',\n {\n variants: {\n size: {\n sm: 'h-auto max-h-[30vh] w-[95vw] max-w-xl',\n md: 'h-auto max-h-[50vh] w-[95vw] max-w-xl',\n lg: 'h-auto max-h-[70vh] w-[95vw] max-w-2xl',\n xl: 'h-auto max-h-[95vh] w-[95vw] max-w-6xl',\n unset: 'h-auto max-h-[95vh] w-[95vw]',\n },\n },\n defaultVariants: {\n size: 'unset',\n },\n }\n);\n\nconst MotionModal = m.create(Container);\n\n/**\n * Usage example:\n * ```jsx\n * <Modal isOpen={isOpen} onClose={onClose}>\n * Modal content\n * </Modal>\n * ```\n */\nexport const Modal: FC<ModalProps> = ({\n children,\n isOpen,\n container,\n disableScroll = true,\n onClose,\n hasCloseButton = false,\n title,\n size = ModalSize.MD,\n className,\n ...props\n}) => {\n const containerElement = useGetElementOrWindow(container);\n\n useScrollBlockage({ key: 'modal', disableScroll: isOpen && disableScroll });\n\n if (!containerElement) return <></>;\n\n const hasTitle = typeof title === 'string';\n\n return createPortal(\n <m.div\n className=\"bg-background/40 /40 invisible fixed left-0 top-0 z-50 flex size-full cursor-pointer items-center justify-center overflow-auto backdrop-blur\"\n animate={isOpen ? 'visible' : 'invisible'}\n variants={{\n visible: {\n opacity: 1,\n visibility: 'visible',\n transition: { duration: 0.1, when: 'beforeChildren' },\n },\n invisible: {\n opacity: 0,\n visibility: 'hidden',\n transition: { duration: 0.1, when: 'afterChildren' },\n },\n }}\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n aria-hidden={!isOpen}\n >\n <div className=\"flex justify-center p-4\">\n <MotionModal\n onClick={(e) => e.stopPropagation()}\n initial={{ scale: isOpen ? 0.5 : 1 }}\n animate={{ scale: isOpen ? 1 : 0.5 }}\n transition={{ duration: 0.3 }}\n className={modalVariants({\n size,\n className,\n })}\n role=\"dialog\"\n aria-modal\n roundedSize=\"2xl\"\n {...props}\n >\n <div\n className={cn(\n 'cursor-default px-4',\n hasCloseButton && hasTitle\n ? `flex items-center justify-center`\n : hasCloseButton\n ? `flex items-center justify-end`\n : hasTitle\n ? `items-center`\n : `hidden`\n )}\n >\n {hasTitle && (\n <H3 className=\"ml-4 flex items-center justify-center text-lg font-bold\">\n {title}\n </H3>\n )}\n {hasCloseButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close modal\"\n className=\"ml-auto\"\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-center overflow-auto\">\n {children}\n </div>\n </MotionModal>\n </div>\n </m.div>,\n containerElement\n );\n};\n"],"names":["ModalSize","cva","m","Container","useGetElementOrWindow","useScrollBlockage","jsx","Fragment","createPortal","jsxs","cn","H3","Button","ButtonVariant","ButtonColor","X","ButtonSize"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Modal.cjs","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { motion as m } from 'framer-motion';\nimport { X } from 'lucide-react';\nimport { ReactNode, type FC } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useGetElementOrWindow, useScrollBlockage } from '../../hooks/index';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container, type ContainerProps } from '../Container';\nimport { H3 } from '../Headers';\n\n/**\n * Enumeration of available modal sizes\n */\nexport enum ModalSize {\n /** Small modal: max height 30vh, max width xl */\n SM = 'sm',\n /** Medium modal: max height 50vh, max width xl */\n MD = 'md',\n /** Large modal: max height 70vh, max width 2xl */\n LG = 'lg',\n /** Extra large modal: max height 95vh, max width 6xl */\n XL = 'xl',\n /** Unset size: max height 95vh, full width responsive */\n UNSET = 'unset',\n}\n\n/**\n * Props for the Modal component\n */\ntype ModalProps = {\n /** Content to be displayed inside the modal */\n children: ReactNode;\n /** Controls whether the modal is visible */\n isOpen: boolean;\n /** Callback function called when the modal should be closed */\n onClose?: () => void;\n /** Container element to render the modal into (defaults to document.body) */\n container?: HTMLElement;\n /** Whether to disable scrolling on the background content */\n disableScroll?: boolean;\n /** Whether to display a close button in the modal header */\n hasCloseButton?: boolean;\n /** Optional title displayed at the top of the modal */\n title?: string;\n /** Size variant for the modal */\n size?: ModalSize | `${ModalSize}`;\n} & Pick<\n ContainerProps,\n | 'className'\n | 'transparency'\n | 'border'\n | 'background'\n | 'roundedSize'\n | 'borderColor'\n | 'padding'\n | 'separator'\n | 'gap'\n>;\n\n/**\n * Class name variants for different modal sizes using class-variance-authority\n * Defines responsive sizing and scrollable content for modal containers\n */\nconst modalVariants = cva(\n 'cursor-default overflow-auto py-3 shadow-sm justify-center',\n {\n variants: {\n size: {\n /** Small modal: height auto, max-height 30vh, width 95vw, max-width xl */\n sm: 'h-auto max-h-[30vh] w-[95vw] max-w-xl',\n /** Medium modal: height auto, max-height 50vh, width 95vw, max-width xl */\n md: 'h-auto max-h-[50vh] w-[95vw] max-w-xl',\n /** Large modal: height auto, max-height 70vh, width 95vw, max-width 2xl */\n lg: 'h-auto max-h-[70vh] w-[95vw] max-w-2xl',\n /** Extra large modal: height auto, max-height 95vh, width 95vw, max-width 6xl */\n xl: 'h-auto max-h-[95vh] w-[95vw] max-w-6xl',\n /** Unset modal: height auto, max-height 95vh, width 95vw, no max-width */\n unset: 'h-auto max-h-[95vh] w-[95vw]',\n },\n },\n defaultVariants: {\n size: 'unset',\n },\n }\n);\n\n/**\n * Motion-enabled modal component with Framer Motion support\n * Extends Container component with motion capabilities for animations\n */\nconst MotionModal = m.create(Container);\n\n/**\n * Modal Component\n *\n * A highly customizable modal dialog component with portal rendering, Framer Motion animations,\n * and comprehensive accessibility features. Supports multiple size variants and scroll management.\n *\n * Features:\n * - Portal rendering to any container element (defaults to document.body)\n * - Smooth animations with Framer Motion\n * - Size variants: SM, MD, LG, XL, UNSET with responsive sizing\n * - Optional title and close button\n * - Background scroll prevention\n * - Click-outside-to-close functionality\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation support (ESC to close)\n * - Extensible styling with Container props\n *\n * @example\n * Basic usage:\n * ```jsx\n * <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>\n * <p>Modal content goes here</p>\n * </Modal>\n * ```\n *\n * @example\n * With title and close button:\n * ```jsx\n * <Modal\n * isOpen={isOpen}\n * onClose={onClose}\n * title=\"Confirm Action\"\n * hasCloseButton\n * size={ModalSize.LG}\n * >\n * <div>\n * <p>Are you sure you want to continue?</p>\n * <Button onClick={onConfirm}>Confirm</Button>\n * </div>\n * </Modal>\n * ```\n *\n * @example\n * Custom container and styling:\n * ```jsx\n * <Modal\n * isOpen={isOpen}\n * onClose={onClose}\n * container={customContainer}\n * background=\"card\"\n * padding=\"lg\"\n * border=\"default\"\n * >\n * Content with custom styling\n * </Modal>\n * ```\n *\n * Accessibility Notes:\n * - Modal receives focus when opened\n * - Background content is hidden from screen readers when modal is open\n * - ESC key closes modal (handled by browser for role=\"dialog\")\n * - Click outside modal closes it\n * - Close button has descriptive label for screen readers\n *\n * @param props - Modal component props\n * @returns JSX element rendered via createPortal\n */\nexport const Modal: FC<ModalProps> = ({\n children,\n isOpen,\n container,\n disableScroll = true,\n onClose,\n hasCloseButton = false,\n title,\n size = ModalSize.MD,\n className,\n ...props\n}) => {\n const containerElement = useGetElementOrWindow(container);\n\n useScrollBlockage({ key: 'modal', disableScroll: isOpen && disableScroll });\n\n if (!containerElement) return <></>;\n\n const hasTitle = typeof title === 'string';\n\n return createPortal(\n <m.div\n className=\"bg-background/40 /40 invisible fixed left-0 top-0 z-50 flex size-full cursor-pointer items-center justify-center overflow-auto backdrop-blur\"\n animate={isOpen ? 'visible' : 'invisible'}\n variants={{\n visible: {\n opacity: 1,\n visibility: 'visible',\n transition: { duration: 0.1, when: 'beforeChildren' },\n },\n invisible: {\n opacity: 0,\n visibility: 'hidden',\n transition: { duration: 0.1, when: 'afterChildren' },\n },\n }}\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n aria-hidden={!isOpen}\n >\n <div className=\"flex justify-center p-4\">\n <MotionModal\n onClick={(e) => e.stopPropagation()}\n initial={{ scale: isOpen ? 0.5 : 1 }}\n animate={{ scale: isOpen ? 1 : 0.5 }}\n transition={{ duration: 0.3 }}\n className={modalVariants({\n size,\n className,\n })}\n role=\"dialog\"\n aria-modal\n roundedSize=\"2xl\"\n {...props}\n >\n <div\n className={cn(\n 'cursor-default px-4',\n hasCloseButton && hasTitle\n ? `flex items-center justify-center`\n : hasCloseButton\n ? `flex items-center justify-end`\n : hasTitle\n ? `items-center`\n : `hidden`\n )}\n >\n {hasTitle && (\n <H3 className=\"ml-4 flex items-center justify-center text-lg font-bold\">\n {title}\n </H3>\n )}\n {hasCloseButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close modal\"\n className=\"ml-auto\"\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-center overflow-auto\">\n {children}\n </div>\n </MotionModal>\n </div>\n </m.div>,\n containerElement\n );\n};\n"],"names":["ModalSize","cva","m","Container","useGetElementOrWindow","useScrollBlockage","jsx","Fragment","createPortal","jsxs","cn","H3","Button","ButtonVariant","ButtonColor","X","ButtonSize"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgBO,IAAK,8BAAAA,eAAL;AAELA,aAAA,IAAA,IAAK;AAELA,aAAA,IAAA,IAAK;AAELA,aAAA,IAAA,IAAK;AAELA,aAAA,IAAA,IAAK;AAELA,aAAA,OAAA,IAAQ;AAVE,SAAAA;AAAA,GAAA,aAAA,CAAA,CAAA;AAkDZ,MAAM,gBAAgBC,uBAAAA;AAAAA,EACpB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA;AAAA,QAEJ,IAAI;AAAA;AAAA,QAEJ,IAAI;AAAA;AAAA,QAEJ,IAAI;AAAA;AAAA,QAEJ,IAAI;AAAA;AAAA,QAEJ,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,IAAA;AAAA,EACR;AAEJ;AAMA,MAAM,cAAcC,aAAAA,OAAE,OAAOC,oCAAS;AAqE/B,MAAM,QAAwB,CAAC;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA,GAAG;AACL,MAAM;AACJ,QAAM,mBAAmBC,4BAAAA,sBAAsB,SAAS;AAExDC,gCAAAA,kBAAkB,EAAE,KAAK,SAAS,eAAe,UAAU,eAAe;AAE1E,MAAI,CAAC,iBAAkB,QAAOC,+BAAAC,WAAAA,UAAA,CAAA,CAAE;AAEhC,QAAM,WAAW,OAAO,UAAU;AAElC,SAAOC,SAAAA;AAAAA,IACLF,2BAAAA;AAAAA,MAACJ,aAAAA,OAAE;AAAA,MAAF;AAAA,QACC,WAAU;AAAA,QACV,SAAS,SAAS,YAAY;AAAA,QAC9B,UAAU;AAAA,UACR,SAAS;AAAA,YACP,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,YAAY,EAAE,UAAU,KAAK,MAAM,iBAAA;AAAA,UAAiB;AAAA,UAEtD,WAAW;AAAA,YACT,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,YAAY,EAAE,UAAU,KAAK,MAAM,gBAAA;AAAA,UAAgB;AAAA,QACrD;AAAA,QAEF,SAAS,CAAC,MAAM;AACd,YAAE,gBAAA;AACF,oBAAA;AAAA,QACF;AAAA,QACA,eAAa,CAAC;AAAA,QAEd,UAAAI,2BAAAA,IAAC,OAAA,EAAI,WAAU,2BACb,UAAAG,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,YAClB,SAAS,EAAE,OAAO,SAAS,MAAM,EAAA;AAAA,YACjC,SAAS,EAAE,OAAO,SAAS,IAAI,IAAA;AAAA,YAC/B,YAAY,EAAE,UAAU,IAAA;AAAA,YACxB,WAAW,cAAc;AAAA,cACvB;AAAA,cACA;AAAA,YAAA,CACD;AAAA,YACD,MAAK;AAAA,YACL,cAAU;AAAA,YACV,aAAY;AAAA,YACX,GAAG;AAAA,YAEJ,UAAA;AAAA,cAAAA,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWC,SAAAA;AAAAA,oBACT;AAAA,oBACA,kBAAkB,WACd,qCACA,iBACE,kCACA,WACE,iBACA;AAAA,kBAAA;AAAA,kBAGT,UAAA;AAAA,oBAAA,YACCJ,2BAAAA,IAACK,6BAAA,EAAG,WAAU,2DACX,UAAA,OACH;AAAA,oBAED,kBACCL,2BAAAA;AAAAA,sBAACM,yBAAAA;AAAAA,sBAAA;AAAA,wBACC,SAASC,yBAAAA,cAAc;AAAA,wBACvB,OAAOC,yBAAAA,YAAY;AAAA,wBACnB,OAAM;AAAA,wBACN,WAAU;AAAA,wBACV,SAAS,CAAC,MAAM;AACd,4BAAE,gBAAA;AACF,oCAAA;AAAA,wBACF;AAAA,wBACA,MAAMC,YAAAA;AAAAA,wBACN,MAAMC,yBAAAA,WAAW;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACnB;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGJV,2BAAAA,IAAC,OAAA,EAAI,WAAU,mDACZ,SAAA,CACH;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAEJ;;;"}
|
|
@@ -1,29 +1,107 @@
|
|
|
1
1
|
import { ReactNode, FC } from 'react';
|
|
2
2
|
import { ContainerProps } from '../Container';
|
|
3
|
+
/**
|
|
4
|
+
* Enumeration of available modal sizes
|
|
5
|
+
*/
|
|
3
6
|
export declare enum ModalSize {
|
|
7
|
+
/** Small modal: max height 30vh, max width xl */
|
|
4
8
|
SM = "sm",
|
|
9
|
+
/** Medium modal: max height 50vh, max width xl */
|
|
5
10
|
MD = "md",
|
|
11
|
+
/** Large modal: max height 70vh, max width 2xl */
|
|
6
12
|
LG = "lg",
|
|
13
|
+
/** Extra large modal: max height 95vh, max width 6xl */
|
|
7
14
|
XL = "xl",
|
|
15
|
+
/** Unset size: max height 95vh, full width responsive */
|
|
8
16
|
UNSET = "unset"
|
|
9
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Props for the Modal component
|
|
20
|
+
*/
|
|
10
21
|
type ModalProps = {
|
|
22
|
+
/** Content to be displayed inside the modal */
|
|
11
23
|
children: ReactNode;
|
|
24
|
+
/** Controls whether the modal is visible */
|
|
12
25
|
isOpen: boolean;
|
|
26
|
+
/** Callback function called when the modal should be closed */
|
|
13
27
|
onClose?: () => void;
|
|
28
|
+
/** Container element to render the modal into (defaults to document.body) */
|
|
14
29
|
container?: HTMLElement;
|
|
30
|
+
/** Whether to disable scrolling on the background content */
|
|
15
31
|
disableScroll?: boolean;
|
|
32
|
+
/** Whether to display a close button in the modal header */
|
|
16
33
|
hasCloseButton?: boolean;
|
|
34
|
+
/** Optional title displayed at the top of the modal */
|
|
17
35
|
title?: string;
|
|
36
|
+
/** Size variant for the modal */
|
|
18
37
|
size?: ModalSize | `${ModalSize}`;
|
|
19
38
|
} & Pick<ContainerProps, 'className' | 'transparency' | 'border' | 'background' | 'roundedSize' | 'borderColor' | 'padding' | 'separator' | 'gap'>;
|
|
20
39
|
/**
|
|
21
|
-
*
|
|
40
|
+
* Modal Component
|
|
41
|
+
*
|
|
42
|
+
* A highly customizable modal dialog component with portal rendering, Framer Motion animations,
|
|
43
|
+
* and comprehensive accessibility features. Supports multiple size variants and scroll management.
|
|
44
|
+
*
|
|
45
|
+
* Features:
|
|
46
|
+
* - Portal rendering to any container element (defaults to document.body)
|
|
47
|
+
* - Smooth animations with Framer Motion
|
|
48
|
+
* - Size variants: SM, MD, LG, XL, UNSET with responsive sizing
|
|
49
|
+
* - Optional title and close button
|
|
50
|
+
* - Background scroll prevention
|
|
51
|
+
* - Click-outside-to-close functionality
|
|
52
|
+
* - Full accessibility support with ARIA attributes
|
|
53
|
+
* - Keyboard navigation support (ESC to close)
|
|
54
|
+
* - Extensible styling with Container props
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* Basic usage:
|
|
58
|
+
* ```jsx
|
|
59
|
+
* <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
|
|
60
|
+
* <p>Modal content goes here</p>
|
|
61
|
+
* </Modal>
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* With title and close button:
|
|
66
|
+
* ```jsx
|
|
67
|
+
* <Modal
|
|
68
|
+
* isOpen={isOpen}
|
|
69
|
+
* onClose={onClose}
|
|
70
|
+
* title="Confirm Action"
|
|
71
|
+
* hasCloseButton
|
|
72
|
+
* size={ModalSize.LG}
|
|
73
|
+
* >
|
|
74
|
+
* <div>
|
|
75
|
+
* <p>Are you sure you want to continue?</p>
|
|
76
|
+
* <Button onClick={onConfirm}>Confirm</Button>
|
|
77
|
+
* </div>
|
|
78
|
+
* </Modal>
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* Custom container and styling:
|
|
22
83
|
* ```jsx
|
|
23
|
-
* <Modal
|
|
24
|
-
*
|
|
84
|
+
* <Modal
|
|
85
|
+
* isOpen={isOpen}
|
|
86
|
+
* onClose={onClose}
|
|
87
|
+
* container={customContainer}
|
|
88
|
+
* background="card"
|
|
89
|
+
* padding="lg"
|
|
90
|
+
* border="default"
|
|
91
|
+
* >
|
|
92
|
+
* Content with custom styling
|
|
25
93
|
* </Modal>
|
|
26
94
|
* ```
|
|
95
|
+
*
|
|
96
|
+
* Accessibility Notes:
|
|
97
|
+
* - Modal receives focus when opened
|
|
98
|
+
* - Background content is hidden from screen readers when modal is open
|
|
99
|
+
* - ESC key closes modal (handled by browser for role="dialog")
|
|
100
|
+
* - Click outside modal closes it
|
|
101
|
+
* - Close button has descriptive label for screen readers
|
|
102
|
+
*
|
|
103
|
+
* @param props - Modal component props
|
|
104
|
+
* @returns JSX element rendered via createPortal
|
|
27
105
|
*/
|
|
28
106
|
export declare const Modal: FC<ModalProps>;
|
|
29
107
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAK3C,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9D,oBAAY,SAAS;IACnB,EAAE,OAAO;IACT,EAAE,OAAO;IACT,EAAE,OAAO;IACT,EAAE,OAAO;IACT,KAAK,UAAU;CAChB;AAED,KAAK,UAAU,GAAG;IAChB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG,SAAS,EAAE,CAAC;CACnC,GAAG,IAAI,CACN,cAAc,EACZ,WAAW,GACX,cAAc,GACd,QAAQ,GACR,YAAY,GACZ,aAAa,GACb,aAAa,GACb,SAAS,GACT,WAAW,GACX,KAAK,CACR,CAAC;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAK3C,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9D;;GAEG;AACH,oBAAY,SAAS;IACnB,iDAAiD;IACjD,EAAE,OAAO;IACT,kDAAkD;IAClD,EAAE,OAAO;IACT,kDAAkD;IAClD,EAAE,OAAO;IACT,wDAAwD;IACxD,EAAE,OAAO;IACT,yDAAyD;IACzD,KAAK,UAAU;CAChB;AAED;;GAEG;AACH,KAAK,UAAU,GAAG;IAChB,+CAA+C;IAC/C,QAAQ,EAAE,SAAS,CAAC;IACpB,4CAA4C;IAC5C,MAAM,EAAE,OAAO,CAAC;IAChB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG,SAAS,EAAE,CAAC;CACnC,GAAG,IAAI,CACN,cAAc,EACZ,WAAW,GACX,cAAc,GACd,QAAQ,GACR,YAAY,GACZ,aAAa,GACb,aAAa,GACb,SAAS,GACT,WAAW,GACX,KAAK,CACR,CAAC;AAmCF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,eAAO,MAAM,KAAK,EAAE,EAAE,CAAC,UAAU,CAiGhC,CAAC"}
|
|
@@ -29,10 +29,15 @@ const modalVariants = cva(
|
|
|
29
29
|
{
|
|
30
30
|
variants: {
|
|
31
31
|
size: {
|
|
32
|
+
/** Small modal: height auto, max-height 30vh, width 95vw, max-width xl */
|
|
32
33
|
sm: "h-auto max-h-[30vh] w-[95vw] max-w-xl",
|
|
34
|
+
/** Medium modal: height auto, max-height 50vh, width 95vw, max-width xl */
|
|
33
35
|
md: "h-auto max-h-[50vh] w-[95vw] max-w-xl",
|
|
36
|
+
/** Large modal: height auto, max-height 70vh, width 95vw, max-width 2xl */
|
|
34
37
|
lg: "h-auto max-h-[70vh] w-[95vw] max-w-2xl",
|
|
38
|
+
/** Extra large modal: height auto, max-height 95vh, width 95vw, max-width 6xl */
|
|
35
39
|
xl: "h-auto max-h-[95vh] w-[95vw] max-w-6xl",
|
|
40
|
+
/** Unset modal: height auto, max-height 95vh, width 95vw, no max-width */
|
|
36
41
|
unset: "h-auto max-h-[95vh] w-[95vw]"
|
|
37
42
|
}
|
|
38
43
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.mjs","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { motion as m } from 'framer-motion';\nimport { X } from 'lucide-react';\nimport { ReactNode, type FC } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useGetElementOrWindow, useScrollBlockage } from '../../hooks/index';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container, type ContainerProps } from '../Container';\nimport { H3 } from '../Headers';\n\nexport enum ModalSize {\n SM = 'sm',\n MD = 'md',\n LG = 'lg',\n XL = 'xl',\n UNSET = 'unset',\n}\n\ntype ModalProps = {\n children: ReactNode;\n isOpen: boolean;\n onClose?: () => void;\n container?: HTMLElement;\n disableScroll?: boolean;\n hasCloseButton?: boolean;\n title?: string;\n size?: ModalSize | `${ModalSize}`;\n} & Pick<\n ContainerProps,\n | 'className'\n | 'transparency'\n | 'border'\n | 'background'\n | 'roundedSize'\n | 'borderColor'\n | 'padding'\n | 'separator'\n | 'gap'\n>;\n\nconst modalVariants = cva(\n 'cursor-default overflow-auto py-3 shadow-sm justify-center',\n {\n variants: {\n size: {\n sm: 'h-auto max-h-[30vh] w-[95vw] max-w-xl',\n md: 'h-auto max-h-[50vh] w-[95vw] max-w-xl',\n lg: 'h-auto max-h-[70vh] w-[95vw] max-w-2xl',\n xl: 'h-auto max-h-[95vh] w-[95vw] max-w-6xl',\n unset: 'h-auto max-h-[95vh] w-[95vw]',\n },\n },\n defaultVariants: {\n size: 'unset',\n },\n }\n);\n\nconst MotionModal = m.create(Container);\n\n/**\n * Usage example:\n * ```jsx\n * <Modal isOpen={isOpen} onClose={onClose}>\n * Modal content\n * </Modal>\n * ```\n */\nexport const Modal: FC<ModalProps> = ({\n children,\n isOpen,\n container,\n disableScroll = true,\n onClose,\n hasCloseButton = false,\n title,\n size = ModalSize.MD,\n className,\n ...props\n}) => {\n const containerElement = useGetElementOrWindow(container);\n\n useScrollBlockage({ key: 'modal', disableScroll: isOpen && disableScroll });\n\n if (!containerElement) return <></>;\n\n const hasTitle = typeof title === 'string';\n\n return createPortal(\n <m.div\n className=\"bg-background/40 /40 invisible fixed left-0 top-0 z-50 flex size-full cursor-pointer items-center justify-center overflow-auto backdrop-blur\"\n animate={isOpen ? 'visible' : 'invisible'}\n variants={{\n visible: {\n opacity: 1,\n visibility: 'visible',\n transition: { duration: 0.1, when: 'beforeChildren' },\n },\n invisible: {\n opacity: 0,\n visibility: 'hidden',\n transition: { duration: 0.1, when: 'afterChildren' },\n },\n }}\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n aria-hidden={!isOpen}\n >\n <div className=\"flex justify-center p-4\">\n <MotionModal\n onClick={(e) => e.stopPropagation()}\n initial={{ scale: isOpen ? 0.5 : 1 }}\n animate={{ scale: isOpen ? 1 : 0.5 }}\n transition={{ duration: 0.3 }}\n className={modalVariants({\n size,\n className,\n })}\n role=\"dialog\"\n aria-modal\n roundedSize=\"2xl\"\n {...props}\n >\n <div\n className={cn(\n 'cursor-default px-4',\n hasCloseButton && hasTitle\n ? `flex items-center justify-center`\n : hasCloseButton\n ? `flex items-center justify-end`\n : hasTitle\n ? `items-center`\n : `hidden`\n )}\n >\n {hasTitle && (\n <H3 className=\"ml-4 flex items-center justify-center text-lg font-bold\">\n {title}\n </H3>\n )}\n {hasCloseButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close modal\"\n className=\"ml-auto\"\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-center overflow-auto\">\n {children}\n </div>\n </MotionModal>\n </div>\n </m.div>,\n containerElement\n );\n};\n"],"names":["ModalSize","m"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Modal.mjs","sources":["../../../src/components/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { cva } from 'class-variance-authority';\nimport { motion as m } from 'framer-motion';\nimport { X } from 'lucide-react';\nimport { ReactNode, type FC } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useGetElementOrWindow, useScrollBlockage } from '../../hooks/index';\nimport { cn } from '../../utils/cn';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { Container, type ContainerProps } from '../Container';\nimport { H3 } from '../Headers';\n\n/**\n * Enumeration of available modal sizes\n */\nexport enum ModalSize {\n /** Small modal: max height 30vh, max width xl */\n SM = 'sm',\n /** Medium modal: max height 50vh, max width xl */\n MD = 'md',\n /** Large modal: max height 70vh, max width 2xl */\n LG = 'lg',\n /** Extra large modal: max height 95vh, max width 6xl */\n XL = 'xl',\n /** Unset size: max height 95vh, full width responsive */\n UNSET = 'unset',\n}\n\n/**\n * Props for the Modal component\n */\ntype ModalProps = {\n /** Content to be displayed inside the modal */\n children: ReactNode;\n /** Controls whether the modal is visible */\n isOpen: boolean;\n /** Callback function called when the modal should be closed */\n onClose?: () => void;\n /** Container element to render the modal into (defaults to document.body) */\n container?: HTMLElement;\n /** Whether to disable scrolling on the background content */\n disableScroll?: boolean;\n /** Whether to display a close button in the modal header */\n hasCloseButton?: boolean;\n /** Optional title displayed at the top of the modal */\n title?: string;\n /** Size variant for the modal */\n size?: ModalSize | `${ModalSize}`;\n} & Pick<\n ContainerProps,\n | 'className'\n | 'transparency'\n | 'border'\n | 'background'\n | 'roundedSize'\n | 'borderColor'\n | 'padding'\n | 'separator'\n | 'gap'\n>;\n\n/**\n * Class name variants for different modal sizes using class-variance-authority\n * Defines responsive sizing and scrollable content for modal containers\n */\nconst modalVariants = cva(\n 'cursor-default overflow-auto py-3 shadow-sm justify-center',\n {\n variants: {\n size: {\n /** Small modal: height auto, max-height 30vh, width 95vw, max-width xl */\n sm: 'h-auto max-h-[30vh] w-[95vw] max-w-xl',\n /** Medium modal: height auto, max-height 50vh, width 95vw, max-width xl */\n md: 'h-auto max-h-[50vh] w-[95vw] max-w-xl',\n /** Large modal: height auto, max-height 70vh, width 95vw, max-width 2xl */\n lg: 'h-auto max-h-[70vh] w-[95vw] max-w-2xl',\n /** Extra large modal: height auto, max-height 95vh, width 95vw, max-width 6xl */\n xl: 'h-auto max-h-[95vh] w-[95vw] max-w-6xl',\n /** Unset modal: height auto, max-height 95vh, width 95vw, no max-width */\n unset: 'h-auto max-h-[95vh] w-[95vw]',\n },\n },\n defaultVariants: {\n size: 'unset',\n },\n }\n);\n\n/**\n * Motion-enabled modal component with Framer Motion support\n * Extends Container component with motion capabilities for animations\n */\nconst MotionModal = m.create(Container);\n\n/**\n * Modal Component\n *\n * A highly customizable modal dialog component with portal rendering, Framer Motion animations,\n * and comprehensive accessibility features. Supports multiple size variants and scroll management.\n *\n * Features:\n * - Portal rendering to any container element (defaults to document.body)\n * - Smooth animations with Framer Motion\n * - Size variants: SM, MD, LG, XL, UNSET with responsive sizing\n * - Optional title and close button\n * - Background scroll prevention\n * - Click-outside-to-close functionality\n * - Full accessibility support with ARIA attributes\n * - Keyboard navigation support (ESC to close)\n * - Extensible styling with Container props\n *\n * @example\n * Basic usage:\n * ```jsx\n * <Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>\n * <p>Modal content goes here</p>\n * </Modal>\n * ```\n *\n * @example\n * With title and close button:\n * ```jsx\n * <Modal\n * isOpen={isOpen}\n * onClose={onClose}\n * title=\"Confirm Action\"\n * hasCloseButton\n * size={ModalSize.LG}\n * >\n * <div>\n * <p>Are you sure you want to continue?</p>\n * <Button onClick={onConfirm}>Confirm</Button>\n * </div>\n * </Modal>\n * ```\n *\n * @example\n * Custom container and styling:\n * ```jsx\n * <Modal\n * isOpen={isOpen}\n * onClose={onClose}\n * container={customContainer}\n * background=\"card\"\n * padding=\"lg\"\n * border=\"default\"\n * >\n * Content with custom styling\n * </Modal>\n * ```\n *\n * Accessibility Notes:\n * - Modal receives focus when opened\n * - Background content is hidden from screen readers when modal is open\n * - ESC key closes modal (handled by browser for role=\"dialog\")\n * - Click outside modal closes it\n * - Close button has descriptive label for screen readers\n *\n * @param props - Modal component props\n * @returns JSX element rendered via createPortal\n */\nexport const Modal: FC<ModalProps> = ({\n children,\n isOpen,\n container,\n disableScroll = true,\n onClose,\n hasCloseButton = false,\n title,\n size = ModalSize.MD,\n className,\n ...props\n}) => {\n const containerElement = useGetElementOrWindow(container);\n\n useScrollBlockage({ key: 'modal', disableScroll: isOpen && disableScroll });\n\n if (!containerElement) return <></>;\n\n const hasTitle = typeof title === 'string';\n\n return createPortal(\n <m.div\n className=\"bg-background/40 /40 invisible fixed left-0 top-0 z-50 flex size-full cursor-pointer items-center justify-center overflow-auto backdrop-blur\"\n animate={isOpen ? 'visible' : 'invisible'}\n variants={{\n visible: {\n opacity: 1,\n visibility: 'visible',\n transition: { duration: 0.1, when: 'beforeChildren' },\n },\n invisible: {\n opacity: 0,\n visibility: 'hidden',\n transition: { duration: 0.1, when: 'afterChildren' },\n },\n }}\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n aria-hidden={!isOpen}\n >\n <div className=\"flex justify-center p-4\">\n <MotionModal\n onClick={(e) => e.stopPropagation()}\n initial={{ scale: isOpen ? 0.5 : 1 }}\n animate={{ scale: isOpen ? 1 : 0.5 }}\n transition={{ duration: 0.3 }}\n className={modalVariants({\n size,\n className,\n })}\n role=\"dialog\"\n aria-modal\n roundedSize=\"2xl\"\n {...props}\n >\n <div\n className={cn(\n 'cursor-default px-4',\n hasCloseButton && hasTitle\n ? `flex items-center justify-center`\n : hasCloseButton\n ? `flex items-center justify-end`\n : hasTitle\n ? `items-center`\n : `hidden`\n )}\n >\n {hasTitle && (\n <H3 className=\"ml-4 flex items-center justify-center text-lg font-bold\">\n {title}\n </H3>\n )}\n {hasCloseButton && (\n <Button\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n label=\"Close modal\"\n className=\"ml-auto\"\n onClick={(e) => {\n e.stopPropagation();\n onClose?.();\n }}\n Icon={X}\n size={ButtonSize.ICON_MD}\n />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-center overflow-auto\">\n {children}\n </div>\n </MotionModal>\n </div>\n </m.div>,\n containerElement\n );\n};\n"],"names":["ModalSize","m"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Burger.cjs","sources":["../../../src/components/Navbar/Burger.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\n\ninterface BurgerProps extends HTMLAttributes<HTMLDivElement> {\n isActive?: boolean;\n}\n\nconst lineStyle =\n 'bg-text absolute top-1/2 block h-[2px] w-8 transition duration-300';\n\nexport const Burger = ({\n isActive = false,\n className,\n ...props\n}: BurgerProps) => (\n <div\n className={cn('relative mr-3 size-10 cursor-pointer', className)}\n aria-checked={isActive}\n aria-expanded={isActive}\n aria-controls=\"mobile-menu\"\n role=\"switch\"\n aria-label={isActive ? 'Close menu' : 'Open menu'}\n {...props}\n >\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[-45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? '-translate-y-3 opacity-0' : '-translate-y-2 opacity-100'\n )}\n />\n </div>\n\n <div>\n <div className={cn(lineStyle, isActive ? 'opacity-0' : 'opacity-100')} />\n </div>\n\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? 'translate-y-3 opacity-0' : 'translate-y-2 opacity-100'\n )}\n />\n </div>\n </div>\n);\n"],"names":["jsxs","cn","jsx"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Burger.cjs","sources":["../../../src/components/Navbar/Burger.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the Burger menu component\n */\ninterface BurgerProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether the burger menu is in active/open state */\n isActive?: boolean;\n}\n\n/**\n * Shared styles for burger menu lines\n * Creates the classic hamburger menu appearance with smooth transitions\n */\nconst lineStyle =\n 'bg-text absolute top-1/2 block h-[2px] w-8 transition duration-300';\n\n/**\n * Burger Menu Component\n *\n * An animated hamburger menu icon that transforms between closed and open states.\n * Commonly used in mobile navigation to toggle menu visibility.\n *\n * Features:\n * - Smooth CSS transitions between states (300ms duration)\n * - Accessible with proper ARIA attributes\n * - Screen reader support with descriptive labels\n * - Role-based interaction (switch role for toggle behavior)\n * - Responsive sizing (40px × 40px clickable area)\n * - Classic three-line hamburger design\n *\n * Animation States:\n * - Closed: Three horizontal parallel lines\n * - Open: Top and bottom lines rotate to form an X, middle line fades out\n *\n * Accessibility Features:\n * - `role=\"switch\"` indicates toggle behavior\n * - `aria-expanded` reflects current menu state\n * - `aria-checked` provides current selection state\n * - `aria-controls` links to controlled menu element\n * - Dynamic `aria-label` describes current action\n *\n * @example\n * Basic usage:\n * ```tsx\n * const [isMenuOpen, setIsMenuOpen] = useState(false);\n *\n * <Burger\n * isActive={isMenuOpen}\n * onClick={() => setIsMenuOpen(!isMenuOpen)}\n * />\n * ```\n *\n * @example\n * With custom styling:\n * ```tsx\n * <Burger\n * isActive={isMenuOpen}\n * onClick={toggleMenu}\n * className=\"lg:hidden\"\n * style={{ zIndex: 1000 }}\n * />\n * ```\n *\n * @param props - Burger component props\n * @returns Animated burger menu JSX element\n */\nexport const Burger = ({\n isActive = false,\n className,\n ...props\n}: BurgerProps) => (\n <div\n className={cn('relative mr-3 size-10 cursor-pointer', className)}\n aria-checked={isActive}\n aria-expanded={isActive}\n aria-controls=\"mobile-menu\"\n role=\"switch\"\n aria-label={isActive ? 'Close menu' : 'Open menu'}\n {...props}\n >\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[-45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? '-translate-y-3 opacity-0' : '-translate-y-2 opacity-100'\n )}\n />\n </div>\n\n <div>\n <div className={cn(lineStyle, isActive ? 'opacity-0' : 'opacity-100')} />\n </div>\n\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? 'translate-y-3 opacity-0' : 'translate-y-2 opacity-100'\n )}\n />\n </div>\n </div>\n);\n"],"names":["jsxs","cn","jsx"],"mappings":";;;;AAeA,MAAM,YACJ;AAoDK,MAAM,SAAS,CAAC;AAAA,EACrB,WAAW;AAAA,EACX;AAAA,EACA,GAAG;AACL,MACEA,2BAAAA;AAAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWC,SAAAA,GAAG,wCAAwC,SAAS;AAAA,IAC/D,gBAAc;AAAA,IACd,iBAAe;AAAA,IACf,iBAAc;AAAA,IACd,MAAK;AAAA,IACL,cAAY,WAAW,eAAe;AAAA,IACrC,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAAD,gCAAC,OAAA,EACC,UAAA;AAAA,QAAAE,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD,SAAAA,GAAG,WAAW,WAAW,oBAAoB,UAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEpEC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD,SAAAA;AAAAA,cACT;AAAA,cACA,WAAW,6BAA6B;AAAA,YAAA;AAAA,UAC1C;AAAA,QAAA;AAAA,MACF,GACF;AAAA,MAEAC,2BAAAA,IAAC,OAAA,EACC,UAAAA,2BAAAA,IAAC,OAAA,EAAI,WAAWD,SAAAA,GAAG,WAAW,WAAW,cAAc,aAAa,EAAA,CAAG,EAAA,CACzE;AAAA,sCAEC,OAAA,EACC,UAAA;AAAA,QAAAC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD,SAAAA,GAAG,WAAW,WAAW,mBAAmB,UAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEnEC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD,SAAAA;AAAAA,cACT;AAAA,cACA,WAAW,4BAA4B;AAAA,YAAA;AAAA,UACzC;AAAA,QAAA;AAAA,MACF,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AACF;;"}
|
|
@@ -1,7 +1,61 @@
|
|
|
1
1
|
import { HTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Props for the Burger menu component
|
|
4
|
+
*/
|
|
2
5
|
interface BurgerProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/** Whether the burger menu is in active/open state */
|
|
3
7
|
isActive?: boolean;
|
|
4
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Burger Menu Component
|
|
11
|
+
*
|
|
12
|
+
* An animated hamburger menu icon that transforms between closed and open states.
|
|
13
|
+
* Commonly used in mobile navigation to toggle menu visibility.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Smooth CSS transitions between states (300ms duration)
|
|
17
|
+
* - Accessible with proper ARIA attributes
|
|
18
|
+
* - Screen reader support with descriptive labels
|
|
19
|
+
* - Role-based interaction (switch role for toggle behavior)
|
|
20
|
+
* - Responsive sizing (40px × 40px clickable area)
|
|
21
|
+
* - Classic three-line hamburger design
|
|
22
|
+
*
|
|
23
|
+
* Animation States:
|
|
24
|
+
* - Closed: Three horizontal parallel lines
|
|
25
|
+
* - Open: Top and bottom lines rotate to form an X, middle line fades out
|
|
26
|
+
*
|
|
27
|
+
* Accessibility Features:
|
|
28
|
+
* - `role="switch"` indicates toggle behavior
|
|
29
|
+
* - `aria-expanded` reflects current menu state
|
|
30
|
+
* - `aria-checked` provides current selection state
|
|
31
|
+
* - `aria-controls` links to controlled menu element
|
|
32
|
+
* - Dynamic `aria-label` describes current action
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* Basic usage:
|
|
36
|
+
* ```tsx
|
|
37
|
+
* const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
38
|
+
*
|
|
39
|
+
* <Burger
|
|
40
|
+
* isActive={isMenuOpen}
|
|
41
|
+
* onClick={() => setIsMenuOpen(!isMenuOpen)}
|
|
42
|
+
* />
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* With custom styling:
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <Burger
|
|
49
|
+
* isActive={isMenuOpen}
|
|
50
|
+
* onClick={toggleMenu}
|
|
51
|
+
* className="lg:hidden"
|
|
52
|
+
* style={{ zIndex: 1000 }}
|
|
53
|
+
* />
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* @param props - Burger component props
|
|
57
|
+
* @returns Animated burger menu JSX element
|
|
58
|
+
*/
|
|
5
59
|
export declare const Burger: ({ isActive, className, ...props }: BurgerProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
60
|
export {};
|
|
7
61
|
//# sourceMappingURL=Burger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Burger.d.ts","sourceRoot":"","sources":["../../../src/components/Navbar/Burger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C,UAAU,WAAY,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"Burger.d.ts","sourceRoot":"","sources":["../../../src/components/Navbar/Burger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAG5C;;GAEG;AACH,UAAU,WAAY,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC1D,sDAAsD;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AASD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,MAAM,GAAI,mCAIpB,WAAW,4CAsCb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Burger.mjs","sources":["../../../src/components/Navbar/Burger.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\n\ninterface BurgerProps extends HTMLAttributes<HTMLDivElement> {\n isActive?: boolean;\n}\n\nconst lineStyle =\n 'bg-text absolute top-1/2 block h-[2px] w-8 transition duration-300';\n\nexport const Burger = ({\n isActive = false,\n className,\n ...props\n}: BurgerProps) => (\n <div\n className={cn('relative mr-3 size-10 cursor-pointer', className)}\n aria-checked={isActive}\n aria-expanded={isActive}\n aria-controls=\"mobile-menu\"\n role=\"switch\"\n aria-label={isActive ? 'Close menu' : 'Open menu'}\n {...props}\n >\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[-45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? '-translate-y-3 opacity-0' : '-translate-y-2 opacity-100'\n )}\n />\n </div>\n\n <div>\n <div className={cn(lineStyle, isActive ? 'opacity-0' : 'opacity-100')} />\n </div>\n\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? 'translate-y-3 opacity-0' : 'translate-y-2 opacity-100'\n )}\n />\n </div>\n </div>\n);\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"Burger.mjs","sources":["../../../src/components/Navbar/Burger.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * Props for the Burger menu component\n */\ninterface BurgerProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether the burger menu is in active/open state */\n isActive?: boolean;\n}\n\n/**\n * Shared styles for burger menu lines\n * Creates the classic hamburger menu appearance with smooth transitions\n */\nconst lineStyle =\n 'bg-text absolute top-1/2 block h-[2px] w-8 transition duration-300';\n\n/**\n * Burger Menu Component\n *\n * An animated hamburger menu icon that transforms between closed and open states.\n * Commonly used in mobile navigation to toggle menu visibility.\n *\n * Features:\n * - Smooth CSS transitions between states (300ms duration)\n * - Accessible with proper ARIA attributes\n * - Screen reader support with descriptive labels\n * - Role-based interaction (switch role for toggle behavior)\n * - Responsive sizing (40px × 40px clickable area)\n * - Classic three-line hamburger design\n *\n * Animation States:\n * - Closed: Three horizontal parallel lines\n * - Open: Top and bottom lines rotate to form an X, middle line fades out\n *\n * Accessibility Features:\n * - `role=\"switch\"` indicates toggle behavior\n * - `aria-expanded` reflects current menu state\n * - `aria-checked` provides current selection state\n * - `aria-controls` links to controlled menu element\n * - Dynamic `aria-label` describes current action\n *\n * @example\n * Basic usage:\n * ```tsx\n * const [isMenuOpen, setIsMenuOpen] = useState(false);\n *\n * <Burger\n * isActive={isMenuOpen}\n * onClick={() => setIsMenuOpen(!isMenuOpen)}\n * />\n * ```\n *\n * @example\n * With custom styling:\n * ```tsx\n * <Burger\n * isActive={isMenuOpen}\n * onClick={toggleMenu}\n * className=\"lg:hidden\"\n * style={{ zIndex: 1000 }}\n * />\n * ```\n *\n * @param props - Burger component props\n * @returns Animated burger menu JSX element\n */\nexport const Burger = ({\n isActive = false,\n className,\n ...props\n}: BurgerProps) => (\n <div\n className={cn('relative mr-3 size-10 cursor-pointer', className)}\n aria-checked={isActive}\n aria-expanded={isActive}\n aria-controls=\"mobile-menu\"\n role=\"switch\"\n aria-label={isActive ? 'Close menu' : 'Open menu'}\n {...props}\n >\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[-45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? '-translate-y-3 opacity-0' : '-translate-y-2 opacity-100'\n )}\n />\n </div>\n\n <div>\n <div className={cn(lineStyle, isActive ? 'opacity-0' : 'opacity-100')} />\n </div>\n\n <div>\n <div\n className={cn(lineStyle, isActive ? 'rotate-[45deg]' : 'rotate-0')}\n />\n <div\n className={cn(\n lineStyle,\n isActive ? 'translate-y-3 opacity-0' : 'translate-y-2 opacity-100'\n )}\n />\n </div>\n </div>\n);\n"],"names":[],"mappings":";;AAeA,MAAM,YACJ;AAoDK,MAAM,SAAS,CAAC;AAAA,EACrB,WAAW;AAAA,EACX;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAW,GAAG,wCAAwC,SAAS;AAAA,IAC/D,gBAAc;AAAA,IACd,iBAAe;AAAA,IACf,iBAAc;AAAA,IACd,MAAK;AAAA,IACL,cAAY,WAAW,eAAe;AAAA,IACrC,GAAG;AAAA,IAEJ,UAAA;AAAA,MAAA,qBAAC,OAAA,EACC,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,GAAG,WAAW,WAAW,oBAAoB,UAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEpE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,WAAW,6BAA6B;AAAA,YAAA;AAAA,UAC1C;AAAA,QAAA;AAAA,MACF,GACF;AAAA,MAEA,oBAAC,OAAA,EACC,UAAA,oBAAC,OAAA,EAAI,WAAW,GAAG,WAAW,WAAW,cAAc,aAAa,EAAA,CAAG,EAAA,CACzE;AAAA,2BAEC,OAAA,EACC,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,GAAG,WAAW,WAAW,mBAAmB,UAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEnE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,WAAW,4BAA4B;AAAA,YAAA;AAAA,UACzC;AAAA,QAAA;AAAA,MACF,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AACF;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DesktopNavbar.cjs","sources":["../../../src/components/Navbar/DesktopNavbar.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement, ReactNode } from 'react';\n\nimport { type TabProps, TabSelector, TabSelectorColor } from '../TabSelector';\n\ntype DesktopNavbarProps<T extends TabProps> = {\n logo: ReactNode;\n sections: ReactElement<T>[];\n rightItems?: ReactNode;\n selectedChoice: T['key'];\n};\n\nexport const DesktopNavbar = <T extends TabProps>({\n logo,\n sections,\n rightItems,\n selectedChoice,\n}: DesktopNavbarProps<T>) => (\n <nav className=\"bg-card/80 sticky top-0 z-50 flex w-full items-center px-4 py-3 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur\">\n {logo}\n\n <TabSelector\n selectedChoice={selectedChoice}\n className=\"text-neutral ml-[2vw] gap-3 overflow-x-auto tracking-wide lg:ml-[5vw] lg:gap-3 xl:ml-[10vw] xl:gap-6\"\n tabs={sections}\n hoverable\n color={TabSelectorColor.TEXT}\n />\n\n <div className=\"mr-4 flex items-center justify-end gap-2 md:gap-4\">\n {rightItems}\n </div>\n </nav>\n);\n"],"names":["jsxs","jsx","TabSelector","TabSelectorColor"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"DesktopNavbar.cjs","sources":["../../../src/components/Navbar/DesktopNavbar.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactElement, ReactNode } from 'react';\n\nimport { type TabProps, TabSelector, TabSelectorColor } from '../TabSelector';\n\n/**\n * Props for the DesktopNavbar component\n * @template T - The tab props type extending TabProps\n */\ntype DesktopNavbarProps<T extends TabProps> = {\n /** Logo component or element displayed on the left side */\n logo: ReactNode;\n /** Array of navigation sections as tab elements */\n sections: ReactElement<T>[];\n /** Right-aligned items (e.g., user menu, search, settings) */\n rightItems?: ReactNode;\n /** Currently selected tab key for highlighting active state */\n selectedChoice: T['key'];\n};\n\n/**\n * Desktop Navigation Bar Component\n *\n * A horizontal navigation bar optimized for desktop and tablet viewports.\n * Features a sticky header with backdrop blur, left-aligned logo, center navigation tabs,\n * and right-aligned utility items.\n *\n * Features:\n * - Sticky positioning with z-index layering (z-50)\n * - Semi-transparent backdrop with blur effect for modern glass-morphism design\n * - Responsive spacing that adapts across screen sizes\n * - Horizontal scrollable tabs for overflow content\n * - Left-to-right layout: Logo → Navigation → Utility Items\n * - Integrated with TabSelector for consistent tab behavior\n *\n * Layout Structure:\n * ```\n * [Logo] -------- [Nav Tab 1] [Nav Tab 2] [Nav Tab 3] -------- [Right Items]\n * ```\n *\n * Responsive Behavior:\n * - Base: 2vw margin-left, 3-unit gap between tabs\n * - Large (≥1024px): 5vw margin-left, 3-unit gap between tabs\n * - Extra Large (≥1280px): 10vw margin-left, 6-unit gap between tabs\n * - Right items: 2-unit gap on mobile, 4-unit gap on medium screens\n *\n * Styling Features:\n * - Semi-transparent card background (`bg-card/80`)\n * - Subtle shadow with controlled blur (`shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)]`)\n * - Backdrop blur effect for content behind navbar\n * - Horizontal overflow scrolling for tab content\n *\n * @example\n * Basic usage:\n * ```tsx\n * const navigationTabs = [\n * { key: 'home', label: 'Home', href: '/' },\n * { key: 'products', label: 'Products', href: '/products' },\n * { key: 'about', label: 'About', href: '/about' }\n * ];\n *\n * <DesktopNavbar\n * logo={<CompanyLogo />}\n * sections={navigationTabs}\n * selectedChoice=\"home\"\n * rightItems={<UserProfileMenu />}\n * />\n * ```\n *\n * @example\n * With multiple right items:\n * ```tsx\n * <DesktopNavbar\n * logo={<Logo />}\n * sections={navSections}\n * selectedChoice={currentPage}\n * rightItems={\n * <>\n * <SearchButton />\n * <NotificationBell />\n * <UserMenu />\n * </>\n * }\n * />\n * ```\n *\n * @template T - Tab properties type extending TabProps for type safety\n * @param props - DesktopNavbar component props\n * @returns Horizontal desktop navigation JSX element\n */\nexport const DesktopNavbar = <T extends TabProps>({\n logo,\n sections,\n rightItems,\n selectedChoice,\n}: DesktopNavbarProps<T>) => (\n <nav className=\"bg-card/80 sticky top-0 z-50 flex w-full items-center px-4 py-3 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur\">\n {logo}\n\n <TabSelector\n selectedChoice={selectedChoice}\n className=\"text-neutral ml-[2vw] gap-3 overflow-x-auto tracking-wide lg:ml-[5vw] lg:gap-3 xl:ml-[10vw] xl:gap-6\"\n tabs={sections}\n hoverable\n color={TabSelectorColor.TEXT}\n />\n\n <div className=\"mr-4 flex items-center justify-end gap-2 md:gap-4\">\n {rightItems}\n </div>\n </nav>\n);\n"],"names":["jsxs","jsx","TabSelector","TabSelectorColor"],"mappings":";;;;;AA2FO,MAAM,gBAAgB,CAAqB;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MACEA,2BAAAA,KAAC,OAAA,EAAI,WAAU,yHACZ,UAAA;AAAA,EAAA;AAAA,EAEDC,2BAAAA;AAAAA,IAACC,mCAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAU;AAAA,MACV,MAAM;AAAA,MACN,WAAS;AAAA,MACT,OAAOC,mCAAAA,iBAAiB;AAAA,IAAA;AAAA,EAAA;AAAA,EAG1BF,2BAAAA,IAAC,OAAA,EAAI,WAAU,qDACZ,UAAA,WAAA,CACH;AAAA,EAAA,CACF;;"}
|