ui-lab-registry 0.3.45 → 0.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Anchor/examples/index.d.ts +0 -8
- package/dist/components/Anchor/examples/index.d.ts.map +1 -1
- package/dist/components/Anchor/examples/index.js +1 -8
- package/dist/components/Anchor/examples/index.js.map +1 -1
- package/dist/components/Anchor/index.d.ts +0 -1
- package/dist/components/Anchor/index.d.ts.map +1 -1
- package/dist/components/Anchor/index.js +1 -15
- package/dist/components/Anchor/index.js.map +1 -1
- package/dist/components/Badge/examples/index.d.ts +0 -10
- package/dist/components/Badge/examples/index.d.ts.map +1 -1
- package/dist/components/Badge/examples/index.js +1 -10
- package/dist/components/Badge/examples/index.js.map +1 -1
- package/dist/components/Badge/index.d.ts +0 -1
- package/dist/components/Badge/index.d.ts.map +1 -1
- package/dist/components/Badge/index.js +1 -17
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/Banner/examples/index.d.ts +0 -10
- package/dist/components/Banner/examples/index.d.ts.map +1 -1
- package/dist/components/Banner/examples/index.js +1 -10
- package/dist/components/Banner/examples/index.js.map +1 -1
- package/dist/components/Banner/index.d.ts +0 -1
- package/dist/components/Banner/index.d.ts.map +1 -1
- package/dist/components/Banner/index.js +1 -17
- package/dist/components/Banner/index.js.map +1 -1
- package/dist/components/Button/examples/index.d.ts +0 -16
- package/dist/components/Button/examples/index.d.ts.map +1 -1
- package/dist/components/Button/examples/index.js +1 -16
- package/dist/components/Button/examples/index.js.map +1 -1
- package/dist/components/Button/index.d.ts +0 -1
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +0 -23
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Card/examples/index.d.ts +0 -6
- package/dist/components/Card/examples/index.d.ts.map +1 -1
- package/dist/components/Card/examples/index.js +1 -6
- package/dist/components/Card/examples/index.js.map +1 -1
- package/dist/components/Card/index.d.ts +0 -1
- package/dist/components/Card/index.d.ts.map +1 -1
- package/dist/components/Card/index.js +1 -13
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Checkbox/examples/index.d.ts +0 -12
- package/dist/components/Checkbox/examples/index.d.ts.map +1 -1
- package/dist/components/Checkbox/examples/index.js +1 -12
- package/dist/components/Checkbox/examples/index.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +0 -1
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +0 -18
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Color/examples/index.d.ts +0 -8
- package/dist/components/Color/examples/index.d.ts.map +1 -1
- package/dist/components/Color/examples/index.js +1 -8
- package/dist/components/Color/examples/index.js.map +1 -1
- package/dist/components/Color/index.d.ts +0 -1
- package/dist/components/Color/index.d.ts.map +1 -1
- package/dist/components/Color/index.js +1 -15
- package/dist/components/Color/index.js.map +1 -1
- package/dist/components/Command/examples/index.d.ts +0 -2
- package/dist/components/Command/examples/index.d.ts.map +1 -1
- package/dist/components/Command/examples/index.js +1 -2
- package/dist/components/Command/examples/index.js.map +1 -1
- package/dist/components/Command/index.d.ts +0 -1
- package/dist/components/Command/index.d.ts.map +1 -1
- package/dist/components/Command/index.js +1 -9
- package/dist/components/Command/index.js.map +1 -1
- package/dist/components/Confirm/examples/index.d.ts +0 -2
- package/dist/components/Confirm/examples/index.d.ts.map +1 -1
- package/dist/components/Confirm/examples/index.js +1 -2
- package/dist/components/Confirm/examples/index.js.map +1 -1
- package/dist/components/Confirm/index.d.ts +0 -1
- package/dist/components/Confirm/index.d.ts.map +1 -1
- package/dist/components/Confirm/index.js +1 -9
- package/dist/components/Confirm/index.js.map +1 -1
- package/dist/components/Date/examples/index.d.ts +0 -8
- package/dist/components/Date/examples/index.d.ts.map +1 -1
- package/dist/components/Date/examples/index.js +1 -8
- package/dist/components/Date/examples/index.js.map +1 -1
- package/dist/components/Date/index.d.ts.map +1 -1
- package/dist/components/Date/index.js +1 -10
- package/dist/components/Date/index.js.map +1 -1
- package/dist/components/Divider/examples/index.d.ts +0 -2
- package/dist/components/Divider/examples/index.d.ts.map +1 -1
- package/dist/components/Divider/examples/index.js +1 -2
- package/dist/components/Divider/examples/index.js.map +1 -1
- package/dist/components/Divider/index.d.ts +0 -1
- package/dist/components/Divider/index.d.ts.map +1 -1
- package/dist/components/Divider/index.js +1 -14
- package/dist/components/Divider/index.js.map +1 -1
- package/dist/components/Expand/examples/index.d.ts +0 -14
- package/dist/components/Expand/examples/index.d.ts.map +1 -1
- package/dist/components/Expand/examples/index.js +1 -14
- package/dist/components/Expand/examples/index.js.map +1 -1
- package/dist/components/Expand/index.d.ts +0 -1
- package/dist/components/Expand/index.d.ts.map +1 -1
- package/dist/components/Expand/index.js +0 -21
- package/dist/components/Expand/index.js.map +1 -1
- package/dist/components/Flex/index.d.ts.map +1 -1
- package/dist/components/Flex/index.js +19 -9
- package/dist/components/Flex/index.js.map +1 -1
- package/dist/components/Frame/examples/index.d.ts +0 -6
- package/dist/components/Frame/examples/index.d.ts.map +1 -1
- package/dist/components/Frame/examples/index.js +1 -6
- package/dist/components/Frame/examples/index.js.map +1 -1
- package/dist/components/Frame/index.d.ts +0 -1
- package/dist/components/Frame/index.d.ts.map +1 -1
- package/dist/components/Frame/index.js +1 -13
- package/dist/components/Frame/index.js.map +1 -1
- package/dist/components/Grid/examples/index.d.ts +0 -2
- package/dist/components/Grid/examples/index.d.ts.map +1 -1
- package/dist/components/Grid/examples/index.js +0 -2
- package/dist/components/Grid/examples/index.js.map +1 -1
- package/dist/components/Grid/examples.json +0 -5
- package/dist/components/Grid/index.d.ts.map +1 -1
- package/dist/components/Grid/index.js +40 -13
- package/dist/components/Grid/index.js.map +1 -1
- package/dist/components/Group/examples/index.d.ts +0 -16
- package/dist/components/Group/examples/index.d.ts.map +1 -1
- package/dist/components/Group/examples/index.js +1 -16
- package/dist/components/Group/examples/index.js.map +1 -1
- package/dist/components/Group/index.d.ts +0 -1
- package/dist/components/Group/index.d.ts.map +1 -1
- package/dist/components/Group/index.js +0 -22
- package/dist/components/Group/index.js.map +1 -1
- package/dist/components/Input/examples/index.d.ts +0 -16
- package/dist/components/Input/examples/index.d.ts.map +1 -1
- package/dist/components/Input/examples/index.js +1 -16
- package/dist/components/Input/examples/index.js.map +1 -1
- package/dist/components/Input/index.d.ts +0 -1
- package/dist/components/Input/index.d.ts.map +1 -1
- package/dist/components/Input/index.js +0 -22
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/Label/examples/index.d.ts +0 -2
- package/dist/components/Label/examples/index.d.ts.map +1 -1
- package/dist/components/Label/examples/index.js +1 -2
- package/dist/components/Label/examples/index.js.map +1 -1
- package/dist/components/Label/index.d.ts +0 -1
- package/dist/components/Label/index.d.ts.map +1 -1
- package/dist/components/Label/index.js +1 -9
- package/dist/components/Label/index.js.map +1 -1
- package/dist/components/List/examples/index.d.ts +0 -10
- package/dist/components/List/examples/index.d.ts.map +1 -1
- package/dist/components/List/examples/index.js +1 -10
- package/dist/components/List/examples/index.js.map +1 -1
- package/dist/components/List/index.d.ts +0 -1
- package/dist/components/List/index.d.ts.map +1 -1
- package/dist/components/List/index.js +0 -16
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Mask/examples/index.d.ts +0 -4
- package/dist/components/Mask/examples/index.d.ts.map +1 -1
- package/dist/components/Mask/examples/index.js +1 -4
- package/dist/components/Mask/examples/index.js.map +1 -1
- package/dist/components/Mask/index.d.ts +0 -1
- package/dist/components/Mask/index.d.ts.map +1 -1
- package/dist/components/Mask/index.js +1 -11
- package/dist/components/Mask/index.js.map +1 -1
- package/dist/components/Menu/examples/index.d.ts +0 -12
- package/dist/components/Menu/examples/index.d.ts.map +1 -1
- package/dist/components/Menu/examples/index.js +1 -12
- package/dist/components/Menu/examples/index.js.map +1 -1
- package/dist/components/Menu/index.d.ts +0 -1
- package/dist/components/Menu/index.d.ts.map +1 -1
- package/dist/components/Menu/index.js +1 -19
- package/dist/components/Menu/index.js.map +1 -1
- package/dist/components/Modal/examples/index.d.ts +0 -10
- package/dist/components/Modal/examples/index.d.ts.map +1 -1
- package/dist/components/Modal/examples/index.js +1 -10
- package/dist/components/Modal/examples/index.js.map +1 -1
- package/dist/components/Modal/index.d.ts +0 -1
- package/dist/components/Modal/index.d.ts.map +1 -1
- package/dist/components/Modal/index.js +1 -17
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Panel/examples/index.d.ts +0 -2
- package/dist/components/Panel/examples/index.d.ts.map +1 -1
- package/dist/components/Panel/examples/index.js +1 -2
- package/dist/components/Panel/examples/index.js.map +1 -1
- package/dist/components/Panel/index.d.ts +0 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +1 -9
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Path/examples/index.d.ts +0 -6
- package/dist/components/Path/examples/index.d.ts.map +1 -1
- package/dist/components/Path/examples/index.js +1 -6
- package/dist/components/Path/examples/index.js.map +1 -1
- package/dist/components/Path/index.d.ts +0 -1
- package/dist/components/Path/index.d.ts.map +1 -1
- package/dist/components/Path/index.js +1 -13
- package/dist/components/Path/index.js.map +1 -1
- package/dist/components/Popover/examples/index.d.ts +0 -10
- package/dist/components/Popover/examples/index.d.ts.map +1 -1
- package/dist/components/Popover/examples/index.js +1 -10
- package/dist/components/Popover/examples/index.js.map +1 -1
- package/dist/components/Popover/index.d.ts +0 -1
- package/dist/components/Popover/index.d.ts.map +1 -1
- package/dist/components/Popover/index.js +1 -17
- package/dist/components/Popover/index.js.map +1 -1
- package/dist/components/Progress/examples/index.d.ts +0 -10
- package/dist/components/Progress/examples/index.d.ts.map +1 -1
- package/dist/components/Progress/examples/index.js +1 -10
- package/dist/components/Progress/examples/index.js.map +1 -1
- package/dist/components/Progress/index.d.ts +0 -1
- package/dist/components/Progress/index.d.ts.map +1 -1
- package/dist/components/Progress/index.js +0 -16
- package/dist/components/Progress/index.js.map +1 -1
- package/dist/components/Radio/examples/index.d.ts +0 -4
- package/dist/components/Radio/examples/index.d.ts.map +1 -1
- package/dist/components/Radio/examples/index.js +1 -4
- package/dist/components/Radio/examples/index.js.map +1 -1
- package/dist/components/Radio/index.d.ts +0 -1
- package/dist/components/Radio/index.d.ts.map +1 -1
- package/dist/components/Radio/index.js +1 -11
- package/dist/components/Radio/index.js.map +1 -1
- package/dist/components/Scroll/examples/index.d.ts +0 -6
- package/dist/components/Scroll/examples/index.d.ts.map +1 -1
- package/dist/components/Scroll/examples/index.js +1 -6
- package/dist/components/Scroll/examples/index.js.map +1 -1
- package/dist/components/Scroll/index.d.ts +0 -1
- package/dist/components/Scroll/index.d.ts.map +1 -1
- package/dist/components/Scroll/index.js +1 -13
- package/dist/components/Scroll/index.js.map +1 -1
- package/dist/components/Select/examples/index.d.ts +0 -6
- package/dist/components/Select/examples/index.d.ts.map +1 -1
- package/dist/components/Select/examples/index.js +1 -6
- package/dist/components/Select/examples/index.js.map +1 -1
- package/dist/components/Select/index.d.ts +0 -1
- package/dist/components/Select/index.d.ts.map +1 -1
- package/dist/components/Select/index.js +1 -13
- package/dist/components/Select/index.js.map +1 -1
- package/dist/components/Slider/examples/index.d.ts +0 -12
- package/dist/components/Slider/examples/index.d.ts.map +1 -1
- package/dist/components/Slider/examples/index.js +1 -12
- package/dist/components/Slider/examples/index.js.map +1 -1
- package/dist/components/Slider/index.d.ts +0 -1
- package/dist/components/Slider/index.d.ts.map +1 -1
- package/dist/components/Slider/index.js +0 -18
- package/dist/components/Slider/index.js.map +1 -1
- package/dist/components/Switch/examples/index.d.ts +0 -10
- package/dist/components/Switch/examples/index.d.ts.map +1 -1
- package/dist/components/Switch/examples/index.js +1 -10
- package/dist/components/Switch/examples/index.js.map +1 -1
- package/dist/components/Switch/index.d.ts +0 -1
- package/dist/components/Switch/index.d.ts.map +1 -1
- package/dist/components/Switch/index.js +0 -16
- package/dist/components/Switch/index.js.map +1 -1
- package/dist/components/Table/examples/index.d.ts +0 -2
- package/dist/components/Table/examples/index.d.ts.map +1 -1
- package/dist/components/Table/examples/index.js +1 -2
- package/dist/components/Table/examples/index.js.map +1 -1
- package/dist/components/Table/index.d.ts +0 -1
- package/dist/components/Table/index.d.ts.map +1 -1
- package/dist/components/Table/index.js +1 -10
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Tabs/examples/index.d.ts +0 -8
- package/dist/components/Tabs/examples/index.d.ts.map +1 -1
- package/dist/components/Tabs/examples/index.js +1 -8
- package/dist/components/Tabs/examples/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +0 -1
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/Tabs/index.js +1 -15
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Textarea/examples/index.d.ts +0 -10
- package/dist/components/Textarea/examples/index.d.ts.map +1 -1
- package/dist/components/Textarea/examples/index.js +1 -10
- package/dist/components/Textarea/examples/index.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +0 -1
- package/dist/components/Textarea/index.d.ts.map +1 -1
- package/dist/components/Textarea/index.js +1 -17
- package/dist/components/Textarea/index.js.map +1 -1
- package/dist/components/Toast/examples/index.d.ts +0 -10
- package/dist/components/Toast/examples/index.d.ts.map +1 -1
- package/dist/components/Toast/examples/index.js +1 -10
- package/dist/components/Toast/examples/index.js.map +1 -1
- package/dist/components/Toast/index.d.ts +0 -1
- package/dist/components/Toast/index.d.ts.map +1 -1
- package/dist/components/Toast/index.js +1 -17
- package/dist/components/Toast/index.js.map +1 -1
- package/dist/components/Tooltip/examples/index.d.ts +0 -2
- package/dist/components/Tooltip/examples/index.d.ts.map +1 -1
- package/dist/components/Tooltip/examples/index.js +1 -2
- package/dist/components/Tooltip/examples/index.js.map +1 -1
- package/dist/components/Tooltip/index.d.ts +0 -1
- package/dist/components/Tooltip/index.d.ts.map +1 -1
- package/dist/components/Tooltip/index.js +1 -9
- package/dist/components/Tooltip/index.js.map +1 -1
- package/dist/demo-registry.d.ts.map +1 -1
- package/dist/demo-registry.js +1 -33
- package/dist/demo-registry.js.map +1 -1
- package/dist/elements/AI/AIChatInput/index.d.ts +0 -3
- package/dist/elements/AI/AIChatInput/index.d.ts.map +1 -1
- package/dist/elements/AI/AIChatInput/index.js +0 -2
- package/dist/elements/AI/AIChatInput/index.js.map +1 -1
- package/dist/elements/AI/ChainOfThought/index.d.ts +0 -3
- package/dist/elements/AI/ChainOfThought/index.d.ts.map +1 -1
- package/dist/elements/AI/ChainOfThought/index.js +0 -2
- package/dist/elements/AI/ChainOfThought/index.js.map +1 -1
- package/dist/elements/AI/Chat/index.d.ts +0 -3
- package/dist/elements/AI/Chat/index.d.ts.map +1 -1
- package/dist/elements/AI/Chat/index.js +0 -2
- package/dist/elements/AI/Chat/index.js.map +1 -1
- package/dist/elements/Documentation/CopyPage/index.d.ts +0 -3
- package/dist/elements/Documentation/CopyPage/index.d.ts.map +1 -1
- package/dist/elements/Documentation/CopyPage/index.js +0 -2
- package/dist/elements/Documentation/CopyPage/index.js.map +1 -1
- package/dist/elements/Documentation/NextArticle/index.d.ts +0 -3
- package/dist/elements/Documentation/NextArticle/index.d.ts.map +1 -1
- package/dist/elements/Documentation/NextArticle/index.js +0 -2
- package/dist/elements/Documentation/NextArticle/index.js.map +1 -1
- package/dist/elements/Documentation/TOC/index.d.ts +0 -3
- package/dist/elements/Documentation/TOC/index.d.ts.map +1 -1
- package/dist/elements/Documentation/TOC/index.js +0 -2
- package/dist/elements/Documentation/TOC/index.js.map +1 -1
- package/dist/elements/Elements/Carousel/index.d.ts +0 -3
- package/dist/elements/Elements/Carousel/index.d.ts.map +1 -1
- package/dist/elements/Elements/Carousel/index.js +0 -2
- package/dist/elements/Elements/Carousel/index.js.map +1 -1
- package/dist/elements/Elements/Rating/index.d.ts +0 -3
- package/dist/elements/Elements/Rating/index.d.ts.map +1 -1
- package/dist/elements/Elements/Rating/index.js +0 -2
- package/dist/elements/Elements/Rating/index.js.map +1 -1
- package/dist/elements/Elements/Timeline/index.d.ts +0 -3
- package/dist/elements/Elements/Timeline/index.d.ts.map +1 -1
- package/dist/elements/Elements/Timeline/index.js +0 -2
- package/dist/elements/Elements/Timeline/index.js.map +1 -1
- package/dist/elements/Elements/TreeView/index.d.ts +0 -3
- package/dist/elements/Elements/TreeView/index.d.ts.map +1 -1
- package/dist/elements/Elements/TreeView/index.js +0 -2
- package/dist/elements/Elements/TreeView/index.js.map +1 -1
- package/dist/elements/Elements/index.d.ts +0 -4
- package/dist/elements/Elements/index.d.ts.map +1 -1
- package/dist/elements/Elements/index.js +0 -4
- package/dist/elements/Elements/index.js.map +1 -1
- package/dist/elements/foundation/Header/index.d.ts +0 -3
- package/dist/elements/foundation/Header/index.d.ts.map +1 -1
- package/dist/elements/foundation/Header/index.js +0 -2
- package/dist/elements/foundation/Header/index.js.map +1 -1
- package/dist/elements/foundation/Page/index.d.ts +0 -3
- package/dist/elements/foundation/Page/index.d.ts.map +1 -1
- package/dist/elements/foundation/Page/index.js +0 -2
- package/dist/elements/foundation/Page/index.js.map +1 -1
- package/dist/elements/foundation/Sidebar/index.d.ts +0 -3
- package/dist/elements/foundation/Sidebar/index.d.ts.map +1 -1
- package/dist/elements/foundation/Sidebar/index.js +0 -2
- package/dist/elements/foundation/Sidebar/index.js.map +1 -1
- package/dist/elements/foundation/TestStructure/index.d.ts +19 -0
- package/dist/elements/foundation/TestStructure/index.d.ts.map +1 -0
- package/dist/elements/foundation/TestStructure/index.js +30 -0
- package/dist/elements/foundation/TestStructure/index.js.map +1 -0
- package/dist/elements/foundation/TestStructure/manifest.d.ts +8 -0
- package/dist/elements/foundation/TestStructure/manifest.d.ts.map +1 -0
- package/dist/elements/foundation/TestStructure/manifest.js +7 -0
- package/dist/elements/foundation/TestStructure/manifest.js.map +1 -0
- package/dist/elements/foundation/TestStructure/variations.json +16 -0
- package/dist/elements/foundation/index.d.ts +2 -4
- package/dist/elements/foundation/index.d.ts.map +1 -1
- package/dist/elements/foundation/index.js +2 -4
- package/dist/elements/foundation/index.js.map +1 -1
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +2 -0
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/packages.d.ts.map +1 -1
- package/dist/elements/packages.js +1 -59
- package/dist/elements/packages.js.map +1 -1
- package/dist/generated-data.d.ts.map +1 -1
- package/dist/generated-data.js +68 -155
- package/dist/generated-data.js.map +1 -1
- package/dist/generated-styles.d.ts.map +1 -1
- package/dist/generated-styles.js +249 -396
- package/dist/generated-styles.js.map +1 -1
- package/dist/generated-styles.json +249 -396
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +2 -89
- package/dist/registry.js.map +1 -1
- package/dist/sections/Hero/index.d.ts +0 -2
- package/dist/sections/Hero/index.d.ts.map +1 -1
- package/dist/sections/Hero/index.js +0 -2
- package/dist/sections/Hero/index.js.map +1 -1
- package/package.json +5 -5
- package/src/components/Anchor/examples/index.ts +1 -11
- package/src/components/Anchor/index.tsx +1 -15
- package/src/components/Badge/examples/index.ts +1 -14
- package/src/components/Badge/index.tsx +1 -17
- package/src/components/Banner/examples/index.ts +1 -14
- package/src/components/Banner/index.tsx +1 -17
- package/src/components/Button/examples/index.ts +1 -16
- package/src/components/Button/index.tsx +0 -24
- package/src/components/Card/examples/index.ts +1 -8
- package/src/components/Card/index.tsx +1 -13
- package/src/components/Checkbox/examples/index.ts +1 -17
- package/src/components/Checkbox/index.tsx +0 -20
- package/src/components/Color/examples/index.ts +1 -11
- package/src/components/Color/index.tsx +1 -15
- package/src/components/Command/examples/index.ts +1 -2
- package/src/components/Command/index.tsx +1 -9
- package/src/components/Confirm/examples/index.ts +1 -2
- package/src/components/Confirm/index.tsx +1 -9
- package/src/components/Date/examples/index.ts +1 -11
- package/src/components/Date/index.tsx +1 -11
- package/src/components/Divider/examples/index.ts +1 -2
- package/src/components/Divider/index.tsx +1 -21
- package/src/components/Expand/examples/index.ts +1 -20
- package/src/components/Expand/index.tsx +0 -23
- package/src/components/Flex/index.tsx +31 -21
- package/src/components/Frame/examples/index.ts +1 -6
- package/src/components/Frame/index.tsx +1 -13
- package/src/components/Grid/examples/index.ts +0 -2
- package/src/components/Grid/examples.json +0 -5
- package/src/components/Grid/index.tsx +51 -19
- package/src/components/Group/examples/index.ts +1 -16
- package/src/components/Group/index.tsx +1 -25
- package/src/components/Input/examples/index.ts +1 -16
- package/src/components/Input/index.tsx +0 -24
- package/src/components/Label/examples/index.ts +1 -2
- package/src/components/Label/index.tsx +1 -9
- package/src/components/List/examples/index.ts +1 -10
- package/src/components/List/index.tsx +0 -18
- package/src/components/Mask/examples/index.ts +1 -5
- package/src/components/Mask/index.tsx +1 -11
- package/src/components/Menu/examples/index.ts +1 -12
- package/src/components/Menu/index.tsx +1 -19
- package/src/components/Modal/examples/index.ts +1 -10
- package/src/components/Modal/index.tsx +1 -17
- package/src/components/Panel/examples/index.ts +1 -2
- package/src/components/Panel/index.tsx +1 -9
- package/src/components/Path/examples/index.ts +1 -6
- package/src/components/Path/index.tsx +1 -13
- package/src/components/Popover/examples/index.ts +1 -10
- package/src/components/Popover/index.tsx +1 -17
- package/src/components/Progress/examples/index.ts +1 -10
- package/src/components/Progress/index.tsx +0 -18
- package/src/components/Radio/examples/index.ts +1 -4
- package/src/components/Radio/index.tsx +1 -11
- package/src/components/Scroll/examples/index.ts +1 -6
- package/src/components/Scroll/index.tsx +1 -13
- package/src/components/Select/examples/index.ts +1 -6
- package/src/components/Select/index.tsx +1 -13
- package/src/components/Slider/examples/index.ts +1 -12
- package/src/components/Slider/index.tsx +0 -19
- package/src/components/Switch/examples/index.ts +1 -10
- package/src/components/Switch/index.tsx +0 -17
- package/src/components/Table/examples/index.ts +1 -2
- package/src/components/Table/index.tsx +1 -9
- package/src/components/Tabs/examples/index.ts +1 -8
- package/src/components/Tabs/index.tsx +1 -15
- package/src/components/Textarea/examples/index.ts +1 -10
- package/src/components/Textarea/index.tsx +1 -17
- package/src/components/Toast/examples/index.ts +1 -10
- package/src/components/Toast/index.tsx +1 -17
- package/src/components/Tooltip/examples/index.ts +1 -2
- package/src/components/Tooltip/index.tsx +1 -9
- package/src/demo-registry.ts +1 -31
- package/src/elements/AI/AIChatInput/index.tsx +0 -3
- package/src/elements/AI/ChainOfThought/index.tsx +0 -3
- package/src/elements/AI/Chat/index.tsx +0 -3
- package/src/elements/Documentation/CopyPage/index.tsx +0 -3
- package/src/elements/Documentation/NextArticle/index.tsx +0 -3
- package/src/elements/Documentation/TOC/index.tsx +0 -3
- package/src/elements/Elements/Carousel/index.tsx +0 -3
- package/src/elements/Elements/Rating/index.tsx +0 -3
- package/src/elements/Elements/Timeline/index.tsx +0 -3
- package/src/elements/Elements/TreeView/index.tsx +0 -3
- package/src/elements/Elements/index.ts +0 -24
- package/src/elements/foundation/Header/index.tsx +0 -3
- package/src/elements/foundation/Page/index.tsx +0 -3
- package/src/elements/foundation/Sidebar/index.tsx +0 -3
- package/src/elements/foundation/TestStructure/index.tsx +54 -0
- package/src/elements/foundation/TestStructure/manifest.ts +9 -0
- package/src/elements/foundation/TestStructure/metadata.json +7 -0
- package/src/elements/foundation/TestStructure/variations.json +16 -0
- package/src/elements/foundation/index.ts +3 -19
- package/src/elements/index.ts +2 -0
- package/src/elements/packages.ts +1 -61
- package/src/generated-data.ts +68 -155
- package/src/generated-styles.ts +249 -396
- package/src/index.ts +0 -18
- package/src/registry.ts +2 -89
- package/src/sections/Hero/index.tsx +0 -2
- package/dist/components/Anchor/examples/01-basic-anchor.d.ts +0 -6
- package/dist/components/Anchor/examples/01-basic-anchor.d.ts.map +0 -1
- package/dist/components/Anchor/examples/01-basic-anchor.js +0 -10
- package/dist/components/Anchor/examples/01-basic-anchor.js.map +0 -1
- package/dist/components/Anchor/examples/01-inline-text.d.ts +0 -6
- package/dist/components/Anchor/examples/01-inline-text.d.ts.map +0 -1
- package/dist/components/Anchor/examples/01-inline-text.js +0 -10
- package/dist/components/Anchor/examples/01-inline-text.js.map +0 -1
- package/dist/components/Anchor/examples/02-underline-variants.d.ts +0 -6
- package/dist/components/Anchor/examples/02-underline-variants.d.ts.map +0 -1
- package/dist/components/Anchor/examples/02-underline-variants.js +0 -10
- package/dist/components/Anchor/examples/02-underline-variants.js.map +0 -1
- package/dist/components/Anchor/examples/03-preview-tooltip.d.ts +0 -6
- package/dist/components/Anchor/examples/03-preview-tooltip.d.ts.map +0 -1
- package/dist/components/Anchor/examples/03-preview-tooltip.js +0 -10
- package/dist/components/Anchor/examples/03-preview-tooltip.js.map +0 -1
- package/dist/components/Anchor/examples/04-breadcrumb.d.ts +0 -6
- package/dist/components/Anchor/examples/04-breadcrumb.d.ts.map +0 -1
- package/dist/components/Anchor/examples/04-breadcrumb.js +0 -15
- package/dist/components/Anchor/examples/04-breadcrumb.js.map +0 -1
- package/dist/components/Anchor/examples.json +0 -22
- package/dist/components/Badge/examples/01-basic-badge.d.ts +0 -6
- package/dist/components/Badge/examples/01-basic-badge.d.ts.map +0 -1
- package/dist/components/Badge/examples/01-basic-badge.js +0 -10
- package/dist/components/Badge/examples/01-basic-badge.js.map +0 -1
- package/dist/components/Badge/examples/01-status-badges.d.ts +0 -6
- package/dist/components/Badge/examples/01-status-badges.d.ts.map +0 -1
- package/dist/components/Badge/examples/01-status-badges.js +0 -10
- package/dist/components/Badge/examples/01-status-badges.js.map +0 -1
- package/dist/components/Badge/examples/02-icon-position.d.ts +0 -6
- package/dist/components/Badge/examples/02-icon-position.d.ts.map +0 -1
- package/dist/components/Badge/examples/02-icon-position.js +0 -11
- package/dist/components/Badge/examples/02-icon-position.js.map +0 -1
- package/dist/components/Badge/examples/02-variants-and-sizes.d.ts +0 -6
- package/dist/components/Badge/examples/02-variants-and-sizes.d.ts.map +0 -1
- package/dist/components/Badge/examples/02-variants-and-sizes.js +0 -10
- package/dist/components/Badge/examples/02-variants-and-sizes.js.map +0 -1
- package/dist/components/Badge/examples/03-selectable-tags.d.ts +0 -6
- package/dist/components/Badge/examples/03-selectable-tags.d.ts.map +0 -1
- package/dist/components/Badge/examples/03-selectable-tags.js +0 -21
- package/dist/components/Badge/examples/03-selectable-tags.js.map +0 -1
- package/dist/components/Badge/examples/04-dismissible.d.ts +0 -6
- package/dist/components/Badge/examples/04-dismissible.d.ts.map +0 -1
- package/dist/components/Badge/examples/04-dismissible.js +0 -14
- package/dist/components/Badge/examples/04-dismissible.js.map +0 -1
- package/dist/components/Badge/examples/05-semantic-colors.d.ts +0 -6
- package/dist/components/Badge/examples/05-semantic-colors.d.ts.map +0 -1
- package/dist/components/Badge/examples/05-semantic-colors.js +0 -10
- package/dist/components/Badge/examples/05-semantic-colors.js.map +0 -1
- package/dist/components/Badge/examples.json +0 -27
- package/dist/components/Banner/examples/01-basic-banner.d.ts +0 -6
- package/dist/components/Banner/examples/01-basic-banner.d.ts.map +0 -1
- package/dist/components/Banner/examples/01-basic-banner.js +0 -10
- package/dist/components/Banner/examples/01-basic-banner.js.map +0 -1
- package/dist/components/Banner/examples/01-variants.d.ts +0 -6
- package/dist/components/Banner/examples/01-variants.d.ts.map +0 -1
- package/dist/components/Banner/examples/01-variants.js +0 -10
- package/dist/components/Banner/examples/01-variants.js.map +0 -1
- package/dist/components/Banner/examples/02-dismissible.d.ts +0 -6
- package/dist/components/Banner/examples/02-dismissible.d.ts.map +0 -1
- package/dist/components/Banner/examples/02-dismissible.js +0 -13
- package/dist/components/Banner/examples/02-dismissible.js.map +0 -1
- package/dist/components/Banner/examples/03-form-feedback.d.ts +0 -6
- package/dist/components/Banner/examples/03-form-feedback.d.ts.map +0 -1
- package/dist/components/Banner/examples/03-form-feedback.js +0 -21
- package/dist/components/Banner/examples/03-form-feedback.js.map +0 -1
- package/dist/components/Banner/examples/04-settings-panel.d.ts +0 -6
- package/dist/components/Banner/examples/04-settings-panel.d.ts.map +0 -1
- package/dist/components/Banner/examples/04-settings-panel.js +0 -10
- package/dist/components/Banner/examples/04-settings-panel.js.map +0 -1
- package/dist/components/Banner/examples/05-body-only.d.ts +0 -6
- package/dist/components/Banner/examples/05-body-only.d.ts.map +0 -1
- package/dist/components/Banner/examples/05-body-only.js +0 -10
- package/dist/components/Banner/examples/05-body-only.js.map +0 -1
- package/dist/components/Banner/examples.json +0 -27
- package/dist/components/Button/examples/01-variants.d.ts +0 -6
- package/dist/components/Button/examples/01-variants.d.ts.map +0 -1
- package/dist/components/Button/examples/01-variants.js +0 -18
- package/dist/components/Button/examples/01-variants.js.map +0 -1
- package/dist/components/Button/examples/02-multi-actions.d.ts +0 -6
- package/dist/components/Button/examples/02-multi-actions.d.ts.map +0 -1
- package/dist/components/Button/examples/02-multi-actions.js +0 -12
- package/dist/components/Button/examples/02-multi-actions.js.map +0 -1
- package/dist/components/Button/examples/03-joined-toggle.d.ts +0 -6
- package/dist/components/Button/examples/03-joined-toggle.d.ts.map +0 -1
- package/dist/components/Button/examples/03-joined-toggle.js +0 -15
- package/dist/components/Button/examples/03-joined-toggle.js.map +0 -1
- package/dist/components/Button/examples/04-sub-stack-actions.d.ts +0 -6
- package/dist/components/Button/examples/04-sub-stack-actions.d.ts.map +0 -1
- package/dist/components/Button/examples/04-sub-stack-actions.js +0 -15
- package/dist/components/Button/examples/04-sub-stack-actions.js.map +0 -1
- package/dist/components/Button/examples/05-split-action-button.d.ts +0 -6
- package/dist/components/Button/examples/05-split-action-button.d.ts.map +0 -1
- package/dist/components/Button/examples/05-split-action-button.js +0 -57
- package/dist/components/Button/examples/05-split-action-button.js.map +0 -1
- package/dist/components/Button/examples/06-icons.d.ts +0 -6
- package/dist/components/Button/examples/06-icons.d.ts.map +0 -1
- package/dist/components/Button/examples/06-icons.js +0 -11
- package/dist/components/Button/examples/06-icons.js.map +0 -1
- package/dist/components/Button/examples/07-split-button.d.ts +0 -6
- package/dist/components/Button/examples/07-split-button.d.ts.map +0 -1
- package/dist/components/Button/examples/07-split-button.js +0 -20
- package/dist/components/Button/examples/07-split-button.js.map +0 -1
- package/dist/components/Button/examples/08-button-group.d.ts +0 -6
- package/dist/components/Button/examples/08-button-group.d.ts.map +0 -1
- package/dist/components/Button/examples/08-button-group.js +0 -14
- package/dist/components/Button/examples/08-button-group.js.map +0 -1
- package/dist/components/Button/examples.json +0 -42
- package/dist/components/Card/examples/01-basic-card.d.ts +0 -6
- package/dist/components/Card/examples/01-basic-card.d.ts.map +0 -1
- package/dist/components/Card/examples/01-basic-card.js +0 -10
- package/dist/components/Card/examples/01-basic-card.js.map +0 -1
- package/dist/components/Card/examples/01-notification.d.ts +0 -6
- package/dist/components/Card/examples/01-notification.d.ts.map +0 -1
- package/dist/components/Card/examples/01-notification.js +0 -13
- package/dist/components/Card/examples/01-notification.js.map +0 -1
- package/dist/components/Card/examples/02-settings-panel.d.ts +0 -6
- package/dist/components/Card/examples/02-settings-panel.d.ts.map +0 -1
- package/dist/components/Card/examples/02-settings-panel.js +0 -18
- package/dist/components/Card/examples/02-settings-panel.js.map +0 -1
- package/dist/components/Card/examples/03-task-progress.d.ts +0 -6
- package/dist/components/Card/examples/03-task-progress.d.ts.map +0 -1
- package/dist/components/Card/examples/03-task-progress.js +0 -17
- package/dist/components/Card/examples/03-task-progress.js.map +0 -1
- package/dist/components/Card/examples.json +0 -17
- package/dist/components/Checkbox/examples/01-basic-checkbox.d.ts +0 -6
- package/dist/components/Checkbox/examples/01-basic-checkbox.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/01-basic-checkbox.js +0 -13
- package/dist/components/Checkbox/examples/01-basic-checkbox.js.map +0 -1
- package/dist/components/Checkbox/examples/01-basic-states.d.ts +0 -6
- package/dist/components/Checkbox/examples/01-basic-states.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/01-basic-states.js +0 -10
- package/dist/components/Checkbox/examples/01-basic-states.js.map +0 -1
- package/dist/components/Checkbox/examples/02-checkbox-group-with-descriptions.d.ts +0 -6
- package/dist/components/Checkbox/examples/02-checkbox-group-with-descriptions.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/02-checkbox-group-with-descriptions.js +0 -21
- package/dist/components/Checkbox/examples/02-checkbox-group-with-descriptions.js.map +0 -1
- package/dist/components/Checkbox/examples/02-helper-text.d.ts +0 -6
- package/dist/components/Checkbox/examples/02-helper-text.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/02-helper-text.js +0 -10
- package/dist/components/Checkbox/examples/02-helper-text.js.map +0 -1
- package/dist/components/Checkbox/examples/03-controlled.d.ts +0 -6
- package/dist/components/Checkbox/examples/03-controlled.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/03-controlled.js +0 -13
- package/dist/components/Checkbox/examples/03-controlled.js.map +0 -1
- package/dist/components/Checkbox/examples/04-group.d.ts +0 -6
- package/dist/components/Checkbox/examples/04-group.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/04-group.js +0 -25
- package/dist/components/Checkbox/examples/04-group.js.map +0 -1
- package/dist/components/Checkbox/examples/05-indeterminate.d.ts +0 -6
- package/dist/components/Checkbox/examples/05-indeterminate.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/05-indeterminate.js +0 -26
- package/dist/components/Checkbox/examples/05-indeterminate.js.map +0 -1
- package/dist/components/Checkbox/examples/06-consent-form.d.ts +0 -6
- package/dist/components/Checkbox/examples/06-consent-form.d.ts.map +0 -1
- package/dist/components/Checkbox/examples/06-consent-form.js +0 -14
- package/dist/components/Checkbox/examples/06-consent-form.js.map +0 -1
- package/dist/components/Checkbox/examples.json +0 -32
- package/dist/components/Color/examples/01-basic-color-picker.d.ts +0 -6
- package/dist/components/Color/examples/01-basic-color-picker.d.ts.map +0 -1
- package/dist/components/Color/examples/01-basic-color-picker.js +0 -11
- package/dist/components/Color/examples/01-basic-color-picker.js.map +0 -1
- package/dist/components/Color/examples/01-basic-color.d.ts +0 -6
- package/dist/components/Color/examples/01-basic-color.d.ts.map +0 -1
- package/dist/components/Color/examples/01-basic-color.js +0 -12
- package/dist/components/Color/examples/01-basic-color.js.map +0 -1
- package/dist/components/Color/examples/02-color-picker-opacity.d.ts +0 -6
- package/dist/components/Color/examples/02-color-picker-opacity.d.ts.map +0 -1
- package/dist/components/Color/examples/02-color-picker-opacity.js +0 -13
- package/dist/components/Color/examples/02-color-picker-opacity.js.map +0 -1
- package/dist/components/Color/examples/02-opacity-slider.d.ts +0 -6
- package/dist/components/Color/examples/02-opacity-slider.d.ts.map +0 -1
- package/dist/components/Color/examples/02-opacity-slider.js +0 -12
- package/dist/components/Color/examples/02-opacity-slider.js.map +0 -1
- package/dist/components/Color/examples/03-color-picker-preview.d.ts +0 -6
- package/dist/components/Color/examples/03-color-picker-preview.d.ts.map +0 -1
- package/dist/components/Color/examples/03-color-picker-preview.js +0 -13
- package/dist/components/Color/examples/03-color-picker-preview.js.map +0 -1
- package/dist/components/Color/examples/03-format-switching.d.ts +0 -2
- package/dist/components/Color/examples/03-format-switching.d.ts.map +0 -1
- package/dist/components/Color/examples/03-format-switching.js +0 -16
- package/dist/components/Color/examples/03-format-switching.js.map +0 -1
- package/dist/components/Color/examples/04-color-slider-primitive.d.ts +0 -6
- package/dist/components/Color/examples/04-color-slider-primitive.d.ts.map +0 -1
- package/dist/components/Color/examples/04-color-slider-primitive.js +0 -16
- package/dist/components/Color/examples/04-color-slider-primitive.js.map +0 -1
- package/dist/components/Color/examples.json +0 -22
- package/dist/components/Command/examples/01-basic-command.d.ts +0 -6
- package/dist/components/Command/examples/01-basic-command.d.ts.map +0 -1
- package/dist/components/Command/examples/01-basic-command.js +0 -36
- package/dist/components/Command/examples/01-basic-command.js.map +0 -1
- package/dist/components/Command/examples.json +0 -7
- package/dist/components/Confirm/examples/01-basic-confirm.d.ts +0 -6
- package/dist/components/Confirm/examples/01-basic-confirm.d.ts.map +0 -1
- package/dist/components/Confirm/examples/01-basic-confirm.js +0 -10
- package/dist/components/Confirm/examples/01-basic-confirm.js.map +0 -1
- package/dist/components/Confirm/examples.json +0 -7
- package/dist/components/Date/examples/01-basic-date.d.ts +0 -6
- package/dist/components/Date/examples/01-basic-date.d.ts.map +0 -1
- package/dist/components/Date/examples/01-basic-date.js +0 -12
- package/dist/components/Date/examples/01-basic-date.js.map +0 -1
- package/dist/components/Date/examples/02-with-disabled-dates.d.ts +0 -6
- package/dist/components/Date/examples/02-with-disabled-dates.d.ts.map +0 -1
- package/dist/components/Date/examples/02-with-disabled-dates.js +0 -16
- package/dist/components/Date/examples/02-with-disabled-dates.js.map +0 -1
- package/dist/components/Date/examples/03-controlled-mode.d.ts +0 -6
- package/dist/components/Date/examples/03-controlled-mode.d.ts.map +0 -1
- package/dist/components/Date/examples/03-controlled-mode.js +0 -28
- package/dist/components/Date/examples/03-controlled-mode.js.map +0 -1
- package/dist/components/Date/examples/04-date-range.d.ts +0 -6
- package/dist/components/Date/examples/04-date-range.d.ts.map +0 -1
- package/dist/components/Date/examples/04-date-range.js +0 -40
- package/dist/components/Date/examples/04-date-range.js.map +0 -1
- package/dist/components/Date/examples.json +0 -1
- package/dist/components/Divider/examples/01-basic-divider.d.ts +0 -6
- package/dist/components/Divider/examples/01-basic-divider.d.ts.map +0 -1
- package/dist/components/Divider/examples/01-basic-divider.js +0 -10
- package/dist/components/Divider/examples/01-basic-divider.js.map +0 -1
- package/dist/components/Divider/examples/02-pattern-variants.d.ts +0 -6
- package/dist/components/Divider/examples/02-pattern-variants.d.ts.map +0 -1
- package/dist/components/Divider/examples/02-pattern-variants.js +0 -10
- package/dist/components/Divider/examples/02-pattern-variants.js.map +0 -1
- package/dist/components/Divider/examples/03-vertical-divider.d.ts +0 -6
- package/dist/components/Divider/examples/03-vertical-divider.d.ts.map +0 -1
- package/dist/components/Divider/examples/03-vertical-divider.js +0 -10
- package/dist/components/Divider/examples/03-vertical-divider.js.map +0 -1
- package/dist/components/Divider/examples.json +0 -17
- package/dist/components/Expand/examples/01-basic-expand.d.ts +0 -6
- package/dist/components/Expand/examples/01-basic-expand.d.ts.map +0 -1
- package/dist/components/Expand/examples/01-basic-expand.js +0 -10
- package/dist/components/Expand/examples/01-basic-expand.js.map +0 -1
- package/dist/components/Expand/examples/01-basic.d.ts +0 -6
- package/dist/components/Expand/examples/01-basic.d.ts.map +0 -1
- package/dist/components/Expand/examples/01-basic.js +0 -10
- package/dist/components/Expand/examples/01-basic.js.map +0 -1
- package/dist/components/Expand/examples/02-accordion.d.ts +0 -6
- package/dist/components/Expand/examples/02-accordion.d.ts.map +0 -1
- package/dist/components/Expand/examples/02-accordion.js +0 -30
- package/dist/components/Expand/examples/02-accordion.js.map +0 -1
- package/dist/components/Expand/examples/03-custom-trigger.d.ts +0 -6
- package/dist/components/Expand/examples/03-custom-trigger.d.ts.map +0 -1
- package/dist/components/Expand/examples/03-custom-trigger.js +0 -11
- package/dist/components/Expand/examples/03-custom-trigger.js.map +0 -1
- package/dist/components/Expand/examples/04-directions.d.ts +0 -6
- package/dist/components/Expand/examples/04-directions.d.ts.map +0 -1
- package/dist/components/Expand/examples/04-directions.js +0 -10
- package/dist/components/Expand/examples/04-directions.js.map +0 -1
- package/dist/components/Expand/examples/05-settings-panel.d.ts +0 -6
- package/dist/components/Expand/examples/05-settings-panel.d.ts.map +0 -1
- package/dist/components/Expand/examples/05-settings-panel.js +0 -11
- package/dist/components/Expand/examples/05-settings-panel.js.map +0 -1
- package/dist/components/Expand/examples/06-disabled.d.ts +0 -6
- package/dist/components/Expand/examples/06-disabled.d.ts.map +0 -1
- package/dist/components/Expand/examples/06-disabled.js +0 -10
- package/dist/components/Expand/examples/06-disabled.js.map +0 -1
- package/dist/components/Expand/examples/07-inline-info.d.ts +0 -6
- package/dist/components/Expand/examples/07-inline-info.d.ts.map +0 -1
- package/dist/components/Expand/examples/07-inline-info.js +0 -11
- package/dist/components/Expand/examples/07-inline-info.js.map +0 -1
- package/dist/components/Expand/examples.json +0 -37
- package/dist/components/Flex/examples/01-basic-flex.d.ts +0 -6
- package/dist/components/Flex/examples/01-basic-flex.d.ts.map +0 -1
- package/dist/components/Flex/examples/01-basic-flex.js +0 -10
- package/dist/components/Flex/examples/01-basic-flex.js.map +0 -1
- package/dist/components/Frame/examples/01-default-frame.d.ts +0 -7
- package/dist/components/Frame/examples/01-default-frame.d.ts.map +0 -1
- package/dist/components/Frame/examples/01-default-frame.js +0 -14
- package/dist/components/Frame/examples/01-default-frame.js.map +0 -1
- package/dist/components/Frame/examples/02-tooltip-example.d.ts +0 -7
- package/dist/components/Frame/examples/02-tooltip-example.d.ts.map +0 -1
- package/dist/components/Frame/examples/02-tooltip-example.js +0 -13
- package/dist/components/Frame/examples/02-tooltip-example.js.map +0 -1
- package/dist/components/Frame/examples/03-sidebar-tab.d.ts +0 -7
- package/dist/components/Frame/examples/03-sidebar-tab.d.ts.map +0 -1
- package/dist/components/Frame/examples/03-sidebar-tab.js +0 -17
- package/dist/components/Frame/examples/03-sidebar-tab.js.map +0 -1
- package/dist/components/Frame/examples.json +0 -17
- package/dist/components/Gallery/examples/01-basic-gallery.d.ts +0 -6
- package/dist/components/Gallery/examples/01-basic-gallery.d.ts.map +0 -1
- package/dist/components/Gallery/examples/01-basic-gallery.js +0 -10
- package/dist/components/Gallery/examples/01-basic-gallery.js.map +0 -1
- package/dist/components/Grid/examples/01-basic-grid.d.ts +0 -6
- package/dist/components/Grid/examples/01-basic-grid.d.ts.map +0 -1
- package/dist/components/Grid/examples/01-basic-grid.js +0 -10
- package/dist/components/Grid/examples/01-basic-grid.js.map +0 -1
- package/dist/components/Group/examples/01-basic-group.d.ts +0 -6
- package/dist/components/Group/examples/01-basic-group.d.ts.map +0 -1
- package/dist/components/Group/examples/01-basic-group.js +0 -10
- package/dist/components/Group/examples/01-basic-group.js.map +0 -1
- package/dist/components/Group/examples/02-create-project.d.ts +0 -6
- package/dist/components/Group/examples/02-create-project.d.ts.map +0 -1
- package/dist/components/Group/examples/02-create-project.js +0 -11
- package/dist/components/Group/examples/02-create-project.js.map +0 -1
- package/dist/components/Group/examples/03-filter-bar.d.ts +0 -6
- package/dist/components/Group/examples/03-filter-bar.d.ts.map +0 -1
- package/dist/components/Group/examples/03-filter-bar.js +0 -14
- package/dist/components/Group/examples/03-filter-bar.js.map +0 -1
- package/dist/components/Group/examples/04-documentation-search.d.ts +0 -6
- package/dist/components/Group/examples/04-documentation-search.d.ts.map +0 -1
- package/dist/components/Group/examples/04-documentation-search.js +0 -11
- package/dist/components/Group/examples/04-documentation-search.js.map +0 -1
- package/dist/components/Group/examples/05-email-signup.d.ts +0 -6
- package/dist/components/Group/examples/05-email-signup.d.ts.map +0 -1
- package/dist/components/Group/examples/05-email-signup.js +0 -11
- package/dist/components/Group/examples/05-email-signup.js.map +0 -1
- package/dist/components/Group/examples/06-copy-command.d.ts +0 -6
- package/dist/components/Group/examples/06-copy-command.d.ts.map +0 -1
- package/dist/components/Group/examples/06-copy-command.js +0 -11
- package/dist/components/Group/examples/06-copy-command.js.map +0 -1
- package/dist/components/Group/examples/07-delete-confirmation.d.ts +0 -6
- package/dist/components/Group/examples/07-delete-confirmation.d.ts.map +0 -1
- package/dist/components/Group/examples/07-delete-confirmation.js +0 -11
- package/dist/components/Group/examples/07-delete-confirmation.js.map +0 -1
- package/dist/components/Group/examples/08-slider-integration.d.ts +0 -6
- package/dist/components/Group/examples/08-slider-integration.d.ts.map +0 -1
- package/dist/components/Group/examples/08-slider-integration.js +0 -19
- package/dist/components/Group/examples/08-slider-integration.js.map +0 -1
- package/dist/components/Group/examples.json +0 -42
- package/dist/components/Input/examples/01-basic-input.d.ts +0 -6
- package/dist/components/Input/examples/01-basic-input.d.ts.map +0 -1
- package/dist/components/Input/examples/01-basic-input.js +0 -10
- package/dist/components/Input/examples/01-basic-input.js.map +0 -1
- package/dist/components/Input/examples/02-validation.d.ts +0 -6
- package/dist/components/Input/examples/02-validation.d.ts.map +0 -1
- package/dist/components/Input/examples/02-validation.js +0 -11
- package/dist/components/Input/examples/02-validation.js.map +0 -1
- package/dist/components/Input/examples/03-sign-in.d.ts +0 -6
- package/dist/components/Input/examples/03-sign-in.d.ts.map +0 -1
- package/dist/components/Input/examples/03-sign-in.js +0 -22
- package/dist/components/Input/examples/03-sign-in.js.map +0 -1
- package/dist/components/Input/examples/04-search.d.ts +0 -6
- package/dist/components/Input/examples/04-search.d.ts.map +0 -1
- package/dist/components/Input/examples/04-search.js +0 -16
- package/dist/components/Input/examples/04-search.js.map +0 -1
- package/dist/components/Input/examples/05-user-handle.d.ts +0 -6
- package/dist/components/Input/examples/05-user-handle.d.ts.map +0 -1
- package/dist/components/Input/examples/05-user-handle.js +0 -27
- package/dist/components/Input/examples/05-user-handle.js.map +0 -1
- package/dist/components/Input/examples/06-api-key.d.ts +0 -6
- package/dist/components/Input/examples/06-api-key.d.ts.map +0 -1
- package/dist/components/Input/examples/06-api-key.js +0 -35
- package/dist/components/Input/examples/06-api-key.js.map +0 -1
- package/dist/components/Input/examples/07-url-validation.d.ts +0 -6
- package/dist/components/Input/examples/07-url-validation.d.ts.map +0 -1
- package/dist/components/Input/examples/07-url-validation.js +0 -23
- package/dist/components/Input/examples/07-url-validation.js.map +0 -1
- package/dist/components/Input/examples/08-quantity.d.ts +0 -6
- package/dist/components/Input/examples/08-quantity.d.ts.map +0 -1
- package/dist/components/Input/examples/08-quantity.js +0 -13
- package/dist/components/Input/examples/08-quantity.js.map +0 -1
- package/dist/components/Input/examples.json +0 -42
- package/dist/components/Label/examples/01-basic-label.d.ts +0 -6
- package/dist/components/Label/examples/01-basic-label.d.ts.map +0 -1
- package/dist/components/Label/examples/01-basic-label.js +0 -10
- package/dist/components/Label/examples/01-basic-label.js.map +0 -1
- package/dist/components/Label/examples.json +0 -7
- package/dist/components/List/examples/01-basic.d.ts +0 -6
- package/dist/components/List/examples/01-basic.d.ts.map +0 -1
- package/dist/components/List/examples/01-basic.js +0 -11
- package/dist/components/List/examples/01-basic.js.map +0 -1
- package/dist/components/List/examples/02-review-queue.d.ts +0 -6
- package/dist/components/List/examples/02-review-queue.d.ts.map +0 -1
- package/dist/components/List/examples/02-review-queue.js +0 -32
- package/dist/components/List/examples/02-review-queue.js.map +0 -1
- package/dist/components/List/examples/03-notification-rules.d.ts +0 -6
- package/dist/components/List/examples/03-notification-rules.d.ts.map +0 -1
- package/dist/components/List/examples/03-notification-rules.js +0 -40
- package/dist/components/List/examples/03-notification-rules.js.map +0 -1
- package/dist/components/List/examples/04-quota-editor.d.ts +0 -6
- package/dist/components/List/examples/04-quota-editor.d.ts.map +0 -1
- package/dist/components/List/examples/04-quota-editor.js +0 -40
- package/dist/components/List/examples/04-quota-editor.js.map +0 -1
- package/dist/components/List/examples/05-permissions-matrix.d.ts +0 -6
- package/dist/components/List/examples/05-permissions-matrix.d.ts.map +0 -1
- package/dist/components/List/examples/05-permissions-matrix.js +0 -39
- package/dist/components/List/examples/05-permissions-matrix.js.map +0 -1
- package/dist/components/List/examples.json +0 -27
- package/dist/components/Mask/examples/01-read-more-fade.d.ts +0 -6
- package/dist/components/Mask/examples/01-read-more-fade.d.ts.map +0 -1
- package/dist/components/Mask/examples/01-read-more-fade.js +0 -10
- package/dist/components/Mask/examples/01-read-more-fade.js.map +0 -1
- package/dist/components/Mask/examples/02-text-gradient.d.ts +0 -6
- package/dist/components/Mask/examples/02-text-gradient.d.ts.map +0 -1
- package/dist/components/Mask/examples/02-text-gradient.js +0 -10
- package/dist/components/Mask/examples/02-text-gradient.js.map +0 -1
- package/dist/components/Mask/examples.json +0 -12
- package/dist/components/Menu/examples/01-basic-menu.d.ts +0 -6
- package/dist/components/Menu/examples/01-basic-menu.d.ts.map +0 -1
- package/dist/components/Menu/examples/01-basic-menu.js +0 -10
- package/dist/components/Menu/examples/01-basic-menu.js.map +0 -1
- package/dist/components/Menu/examples/02-nested-menu.d.ts +0 -6
- package/dist/components/Menu/examples/02-nested-menu.d.ts.map +0 -1
- package/dist/components/Menu/examples/02-nested-menu.js +0 -10
- package/dist/components/Menu/examples/02-nested-menu.js.map +0 -1
- package/dist/components/Menu/examples/03-toolbar-dropdown.d.ts +0 -6
- package/dist/components/Menu/examples/03-toolbar-dropdown.d.ts.map +0 -1
- package/dist/components/Menu/examples/03-toolbar-dropdown.js +0 -11
- package/dist/components/Menu/examples/03-toolbar-dropdown.js.map +0 -1
- package/dist/components/Menu/examples/04-table-row-actions.d.ts +0 -6
- package/dist/components/Menu/examples/04-table-row-actions.d.ts.map +0 -1
- package/dist/components/Menu/examples/04-table-row-actions.js +0 -16
- package/dist/components/Menu/examples/04-table-row-actions.js.map +0 -1
- package/dist/components/Menu/examples/05-context-menu.d.ts +0 -6
- package/dist/components/Menu/examples/05-context-menu.d.ts.map +0 -1
- package/dist/components/Menu/examples/05-context-menu.js +0 -10
- package/dist/components/Menu/examples/05-context-menu.js.map +0 -1
- package/dist/components/Menu/examples/06-view-options.d.ts +0 -6
- package/dist/components/Menu/examples/06-view-options.d.ts.map +0 -1
- package/dist/components/Menu/examples/06-view-options.js +0 -15
- package/dist/components/Menu/examples/06-view-options.js.map +0 -1
- package/dist/components/Menu/examples.json +0 -32
- package/dist/components/Modal/examples/01-basic-modal.d.ts +0 -6
- package/dist/components/Modal/examples/01-basic-modal.d.ts.map +0 -1
- package/dist/components/Modal/examples/01-basic-modal.js +0 -13
- package/dist/components/Modal/examples/01-basic-modal.js.map +0 -1
- package/dist/components/Modal/examples/02-form-modal.d.ts +0 -6
- package/dist/components/Modal/examples/02-form-modal.d.ts.map +0 -1
- package/dist/components/Modal/examples/02-form-modal.js +0 -23
- package/dist/components/Modal/examples/02-form-modal.js.map +0 -1
- package/dist/components/Modal/examples/03-delete-confirmation.d.ts +0 -6
- package/dist/components/Modal/examples/03-delete-confirmation.d.ts.map +0 -1
- package/dist/components/Modal/examples/03-delete-confirmation.js +0 -13
- package/dist/components/Modal/examples/03-delete-confirmation.js.map +0 -1
- package/dist/components/Modal/examples/04-create-api-key.d.ts +0 -6
- package/dist/components/Modal/examples/04-create-api-key.d.ts.map +0 -1
- package/dist/components/Modal/examples/04-create-api-key.js +0 -14
- package/dist/components/Modal/examples/04-create-api-key.js.map +0 -1
- package/dist/components/Modal/examples/05-notification-settings.d.ts +0 -6
- package/dist/components/Modal/examples/05-notification-settings.d.ts.map +0 -1
- package/dist/components/Modal/examples/05-notification-settings.js +0 -19
- package/dist/components/Modal/examples/05-notification-settings.js.map +0 -1
- package/dist/components/Modal/examples.json +0 -27
- package/dist/components/Panel/examples/01-sidebar-toggle.d.ts +0 -6
- package/dist/components/Panel/examples/01-sidebar-toggle.d.ts.map +0 -1
- package/dist/components/Panel/examples/01-sidebar-toggle.js +0 -10
- package/dist/components/Panel/examples/01-sidebar-toggle.js.map +0 -1
- package/dist/components/Panel/examples.json +0 -7
- package/dist/components/Path/examples/01-basic-breadcrumbs.d.ts +0 -6
- package/dist/components/Path/examples/01-basic-breadcrumbs.d.ts.map +0 -1
- package/dist/components/Path/examples/01-basic-breadcrumbs.js +0 -10
- package/dist/components/Path/examples/01-basic-breadcrumbs.js.map +0 -1
- package/dist/components/Path/examples/01-basic-path.d.ts +0 -6
- package/dist/components/Path/examples/01-basic-path.d.ts.map +0 -1
- package/dist/components/Path/examples/01-basic-path.js +0 -10
- package/dist/components/Path/examples/01-basic-path.js.map +0 -1
- package/dist/components/Path/examples/02-custom-separator.d.ts +0 -6
- package/dist/components/Path/examples/02-custom-separator.d.ts.map +0 -1
- package/dist/components/Path/examples/02-custom-separator.js +0 -11
- package/dist/components/Path/examples/02-custom-separator.js.map +0 -1
- package/dist/components/Path/examples/03-collapsed-breadcrumb.d.ts +0 -6
- package/dist/components/Path/examples/03-collapsed-breadcrumb.d.ts.map +0 -1
- package/dist/components/Path/examples/03-collapsed-breadcrumb.js +0 -16
- package/dist/components/Path/examples/03-collapsed-breadcrumb.js.map +0 -1
- package/dist/components/Path/examples.json +0 -17
- package/dist/components/Popover/examples/01-basic-popover.d.ts +0 -6
- package/dist/components/Popover/examples/01-basic-popover.d.ts.map +0 -1
- package/dist/components/Popover/examples/01-basic-popover.js +0 -11
- package/dist/components/Popover/examples/01-basic-popover.js.map +0 -1
- package/dist/components/Popover/examples/02-toggleable-options.d.ts +0 -6
- package/dist/components/Popover/examples/02-toggleable-options.d.ts.map +0 -1
- package/dist/components/Popover/examples/02-toggleable-options.js +0 -23
- package/dist/components/Popover/examples/02-toggleable-options.js.map +0 -1
- package/dist/components/Popover/examples/03-table-row-actions.d.ts +0 -6
- package/dist/components/Popover/examples/03-table-row-actions.d.ts.map +0 -1
- package/dist/components/Popover/examples/03-table-row-actions.js +0 -17
- package/dist/components/Popover/examples/03-table-row-actions.js.map +0 -1
- package/dist/components/Popover/examples/04-input-form.d.ts +0 -6
- package/dist/components/Popover/examples/04-input-form.d.ts.map +0 -1
- package/dist/components/Popover/examples/04-input-form.js +0 -14
- package/dist/components/Popover/examples/04-input-form.js.map +0 -1
- package/dist/components/Popover/examples/05-arrow-positions.d.ts +0 -6
- package/dist/components/Popover/examples/05-arrow-positions.d.ts.map +0 -1
- package/dist/components/Popover/examples/05-arrow-positions.js +0 -11
- package/dist/components/Popover/examples/05-arrow-positions.js.map +0 -1
- package/dist/components/Popover/examples.json +0 -27
- package/dist/components/Progress/examples/01-basic-progress.d.ts +0 -6
- package/dist/components/Progress/examples/01-basic-progress.d.ts.map +0 -1
- package/dist/components/Progress/examples/01-basic-progress.js +0 -25
- package/dist/components/Progress/examples/01-basic-progress.js.map +0 -1
- package/dist/components/Progress/examples/02-storage-quota.d.ts +0 -6
- package/dist/components/Progress/examples/02-storage-quota.d.ts.map +0 -1
- package/dist/components/Progress/examples/02-storage-quota.js +0 -12
- package/dist/components/Progress/examples/02-storage-quota.js.map +0 -1
- package/dist/components/Progress/examples/03-onboarding-steps.d.ts +0 -6
- package/dist/components/Progress/examples/03-onboarding-steps.d.ts.map +0 -1
- package/dist/components/Progress/examples/03-onboarding-steps.js +0 -14
- package/dist/components/Progress/examples/03-onboarding-steps.js.map +0 -1
- package/dist/components/Progress/examples/04-indeterminate.d.ts +0 -6
- package/dist/components/Progress/examples/04-indeterminate.d.ts.map +0 -1
- package/dist/components/Progress/examples/04-indeterminate.js +0 -19
- package/dist/components/Progress/examples/04-indeterminate.js.map +0 -1
- package/dist/components/Progress/examples/05-skill-levels.d.ts +0 -6
- package/dist/components/Progress/examples/05-skill-levels.d.ts.map +0 -1
- package/dist/components/Progress/examples/05-skill-levels.js +0 -15
- package/dist/components/Progress/examples/05-skill-levels.js.map +0 -1
- package/dist/components/Progress/examples.json +0 -27
- package/dist/components/Radio/examples/01-basic-radio.d.ts +0 -6
- package/dist/components/Radio/examples/01-basic-radio.d.ts.map +0 -1
- package/dist/components/Radio/examples/01-basic-radio.js +0 -10
- package/dist/components/Radio/examples/01-basic-radio.js.map +0 -1
- package/dist/components/Radio/examples/02-radio-with-descriptions.d.ts +0 -6
- package/dist/components/Radio/examples/02-radio-with-descriptions.d.ts.map +0 -1
- package/dist/components/Radio/examples/02-radio-with-descriptions.js +0 -11
- package/dist/components/Radio/examples/02-radio-with-descriptions.js.map +0 -1
- package/dist/components/Radio/examples.json +0 -12
- package/dist/components/Scroll/examples/01-basic-scroll.d.ts +0 -6
- package/dist/components/Scroll/examples/01-basic-scroll.d.ts.map +0 -1
- package/dist/components/Scroll/examples/01-basic-scroll.js +0 -36
- package/dist/components/Scroll/examples/01-basic-scroll.js.map +0 -1
- package/dist/components/Scroll/examples/02-settings-panel.d.ts +0 -6
- package/dist/components/Scroll/examples/02-settings-panel.d.ts.map +0 -1
- package/dist/components/Scroll/examples/02-settings-panel.js +0 -21
- package/dist/components/Scroll/examples/02-settings-panel.js.map +0 -1
- package/dist/components/Scroll/examples/03-horizontal-tags.d.ts +0 -6
- package/dist/components/Scroll/examples/03-horizontal-tags.d.ts.map +0 -1
- package/dist/components/Scroll/examples/03-horizontal-tags.js +0 -24
- package/dist/components/Scroll/examples/03-horizontal-tags.js.map +0 -1
- package/dist/components/Scroll/examples.json +0 -17
- package/dist/components/Select/examples/01-basic-select.d.ts +0 -6
- package/dist/components/Select/examples/01-basic-select.d.ts.map +0 -1
- package/dist/components/Select/examples/01-basic-select.js +0 -10
- package/dist/components/Select/examples/01-basic-select.js.map +0 -1
- package/dist/components/Select/examples/02-searchable-select.d.ts +0 -6
- package/dist/components/Select/examples/02-searchable-select.d.ts.map +0 -1
- package/dist/components/Select/examples/02-searchable-select.js +0 -38
- package/dist/components/Select/examples/02-searchable-select.js.map +0 -1
- package/dist/components/Select/examples/03-country-select.d.ts +0 -6
- package/dist/components/Select/examples/03-country-select.d.ts.map +0 -1
- package/dist/components/Select/examples/03-country-select.js +0 -28
- package/dist/components/Select/examples/03-country-select.js.map +0 -1
- package/dist/components/Select/examples.json +0 -17
- package/dist/components/Slider/examples/01-basic-slider.d.ts +0 -6
- package/dist/components/Slider/examples/01-basic-slider.d.ts.map +0 -1
- package/dist/components/Slider/examples/01-basic-slider.js +0 -13
- package/dist/components/Slider/examples/01-basic-slider.js.map +0 -1
- package/dist/components/Slider/examples/02-settings-panel.d.ts +0 -6
- package/dist/components/Slider/examples/02-settings-panel.d.ts.map +0 -1
- package/dist/components/Slider/examples/02-settings-panel.js +0 -20
- package/dist/components/Slider/examples/02-settings-panel.js.map +0 -1
- package/dist/components/Slider/examples/03-price-range.d.ts +0 -6
- package/dist/components/Slider/examples/03-price-range.d.ts.map +0 -1
- package/dist/components/Slider/examples/03-price-range.js +0 -13
- package/dist/components/Slider/examples/03-price-range.js.map +0 -1
- package/dist/components/Slider/examples/04-step-slider.d.ts +0 -6
- package/dist/components/Slider/examples/04-step-slider.d.ts.map +0 -1
- package/dist/components/Slider/examples/04-step-slider.js +0 -13
- package/dist/components/Slider/examples/04-step-slider.js.map +0 -1
- package/dist/components/Slider/examples/05-disabled-state.d.ts +0 -6
- package/dist/components/Slider/examples/05-disabled-state.d.ts.map +0 -1
- package/dist/components/Slider/examples/05-disabled-state.js +0 -10
- package/dist/components/Slider/examples/05-disabled-state.js.map +0 -1
- package/dist/components/Slider/examples/06-vertical-mixer.d.ts +0 -6
- package/dist/components/Slider/examples/06-vertical-mixer.d.ts.map +0 -1
- package/dist/components/Slider/examples/06-vertical-mixer.js +0 -17
- package/dist/components/Slider/examples/06-vertical-mixer.js.map +0 -1
- package/dist/components/Slider/examples.json +0 -32
- package/dist/components/Switch/examples/01-basic-switch.d.ts +0 -6
- package/dist/components/Switch/examples/01-basic-switch.d.ts.map +0 -1
- package/dist/components/Switch/examples/01-basic-switch.js +0 -13
- package/dist/components/Switch/examples/01-basic-switch.js.map +0 -1
- package/dist/components/Switch/examples/02-settings-panel.d.ts +0 -6
- package/dist/components/Switch/examples/02-settings-panel.d.ts.map +0 -1
- package/dist/components/Switch/examples/02-settings-panel.js +0 -20
- package/dist/components/Switch/examples/02-settings-panel.js.map +0 -1
- package/dist/components/Switch/examples/03-disabled-state.d.ts +0 -6
- package/dist/components/Switch/examples/03-disabled-state.d.ts.map +0 -1
- package/dist/components/Switch/examples/03-disabled-state.js +0 -10
- package/dist/components/Switch/examples/03-disabled-state.js.map +0 -1
- package/dist/components/Switch/examples/04-small-size.d.ts +0 -6
- package/dist/components/Switch/examples/04-small-size.d.ts.map +0 -1
- package/dist/components/Switch/examples/04-small-size.js +0 -13
- package/dist/components/Switch/examples/04-small-size.js.map +0 -1
- package/dist/components/Switch/examples/05-controlled-toggle.d.ts +0 -6
- package/dist/components/Switch/examples/05-controlled-toggle.d.ts.map +0 -1
- package/dist/components/Switch/examples/05-controlled-toggle.js +0 -13
- package/dist/components/Switch/examples/05-controlled-toggle.js.map +0 -1
- package/dist/components/Switch/examples.json +0 -27
- package/dist/components/Table/examples/01-basic-table.d.ts +0 -6
- package/dist/components/Table/examples/01-basic-table.d.ts.map +0 -1
- package/dist/components/Table/examples/01-basic-table.js +0 -20
- package/dist/components/Table/examples/01-basic-table.js.map +0 -1
- package/dist/components/Table/examples.json +0 -7
- package/dist/components/Tabs/examples/01-basic-tabs.d.ts +0 -6
- package/dist/components/Tabs/examples/01-basic-tabs.d.ts.map +0 -1
- package/dist/components/Tabs/examples/01-basic-tabs.js +0 -10
- package/dist/components/Tabs/examples/01-basic-tabs.js.map +0 -1
- package/dist/components/Tabs/examples/02-vertical-tabs.d.ts +0 -6
- package/dist/components/Tabs/examples/02-vertical-tabs.d.ts.map +0 -1
- package/dist/components/Tabs/examples/02-vertical-tabs.js +0 -11
- package/dist/components/Tabs/examples/02-vertical-tabs.js.map +0 -1
- package/dist/components/Tabs/examples/03-underline-tabs.d.ts +0 -6
- package/dist/components/Tabs/examples/03-underline-tabs.d.ts.map +0 -1
- package/dist/components/Tabs/examples/03-underline-tabs.js +0 -13
- package/dist/components/Tabs/examples/03-underline-tabs.js.map +0 -1
- package/dist/components/Tabs/examples/04-vertical-underline-tabs.d.ts +0 -6
- package/dist/components/Tabs/examples/04-vertical-underline-tabs.d.ts.map +0 -1
- package/dist/components/Tabs/examples/04-vertical-underline-tabs.js +0 -13
- package/dist/components/Tabs/examples/04-vertical-underline-tabs.js.map +0 -1
- package/dist/components/Tabs/examples.json +0 -22
- package/dist/components/Textarea/examples/01-basic-textarea.d.ts +0 -6
- package/dist/components/Textarea/examples/01-basic-textarea.d.ts.map +0 -1
- package/dist/components/Textarea/examples/01-basic-textarea.js +0 -13
- package/dist/components/Textarea/examples/01-basic-textarea.js.map +0 -1
- package/dist/components/Textarea/examples/02-bio-settings.d.ts +0 -6
- package/dist/components/Textarea/examples/02-bio-settings.d.ts.map +0 -1
- package/dist/components/Textarea/examples/02-bio-settings.js +0 -13
- package/dist/components/Textarea/examples/02-bio-settings.js.map +0 -1
- package/dist/components/Textarea/examples/03-error-state.d.ts +0 -6
- package/dist/components/Textarea/examples/03-error-state.d.ts.map +0 -1
- package/dist/components/Textarea/examples/03-error-state.js +0 -14
- package/dist/components/Textarea/examples/03-error-state.js.map +0 -1
- package/dist/components/Textarea/examples/04-disabled-readonly.d.ts +0 -6
- package/dist/components/Textarea/examples/04-disabled-readonly.d.ts.map +0 -1
- package/dist/components/Textarea/examples/04-disabled-readonly.js +0 -10
- package/dist/components/Textarea/examples/04-disabled-readonly.js.map +0 -1
- package/dist/components/Textarea/examples/05-scrolling.d.ts +0 -6
- package/dist/components/Textarea/examples/05-scrolling.d.ts.map +0 -1
- package/dist/components/Textarea/examples/05-scrolling.js +0 -13
- package/dist/components/Textarea/examples/05-scrolling.js.map +0 -1
- package/dist/components/Textarea/examples.json +0 -27
- package/dist/components/Toast/examples/01-basic-toast.d.ts +0 -6
- package/dist/components/Toast/examples/01-basic-toast.d.ts.map +0 -1
- package/dist/components/Toast/examples/01-basic-toast.js +0 -10
- package/dist/components/Toast/examples/01-basic-toast.js.map +0 -1
- package/dist/components/Toast/examples/02-success-toast.d.ts +0 -6
- package/dist/components/Toast/examples/02-success-toast.d.ts.map +0 -1
- package/dist/components/Toast/examples/02-success-toast.js +0 -14
- package/dist/components/Toast/examples/02-success-toast.js.map +0 -1
- package/dist/components/Toast/examples/03-danger-toast.d.ts +0 -6
- package/dist/components/Toast/examples/03-danger-toast.d.ts.map +0 -1
- package/dist/components/Toast/examples/03-danger-toast.js +0 -14
- package/dist/components/Toast/examples/03-danger-toast.js.map +0 -1
- package/dist/components/Toast/examples/04-info-toast.d.ts +0 -6
- package/dist/components/Toast/examples/04-info-toast.d.ts.map +0 -1
- package/dist/components/Toast/examples/04-info-toast.js +0 -14
- package/dist/components/Toast/examples/04-info-toast.js.map +0 -1
- package/dist/components/Toast/examples/05-warning-toast.d.ts +0 -6
- package/dist/components/Toast/examples/05-warning-toast.d.ts.map +0 -1
- package/dist/components/Toast/examples/05-warning-toast.js +0 -14
- package/dist/components/Toast/examples/05-warning-toast.js.map +0 -1
- package/dist/components/Toast/examples.json +0 -27
- package/dist/components/Tooltip/examples/01-basic-tooltip.d.ts +0 -6
- package/dist/components/Tooltip/examples/01-basic-tooltip.d.ts.map +0 -1
- package/dist/components/Tooltip/examples/01-basic-tooltip.js +0 -10
- package/dist/components/Tooltip/examples/01-basic-tooltip.js.map +0 -1
- package/dist/components/Tooltip/examples.json +0 -7
- package/dist/design-tokens/index.d.ts +0 -52
- package/dist/design-tokens/index.d.ts.map +0 -1
- package/dist/design-tokens/index.js +0 -167
- package/dist/design-tokens/index.js.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/AI/AIChatInput/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/01-basic/index.js +0 -13
- package/dist/elements/AI/AIChatInput/variations/01-basic/index.js.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/01-basic/layout/PromptInput.d.ts +0 -9
- package/dist/elements/AI/AIChatInput/variations/01-basic/layout/PromptInput.d.ts.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/01-basic/layout/PromptInput.js +0 -25
- package/dist/elements/AI/AIChatInput/variations/01-basic/layout/PromptInput.js.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/index.d.ts +0 -2
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/index.d.ts.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/index.js +0 -25
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/index.js.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/layout/PromptInputWithSuggestions.d.ts +0 -9
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/layout/PromptInputWithSuggestions.d.ts.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/layout/PromptInputWithSuggestions.js +0 -25
- package/dist/elements/AI/AIChatInput/variations/02-with-suggestions/layout/PromptInputWithSuggestions.js.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/index.d.ts +0 -18
- package/dist/elements/AI/AIChatInput/variations/index.d.ts.map +0 -1
- package/dist/elements/AI/AIChatInput/variations/index.js +0 -14
- package/dist/elements/AI/AIChatInput/variations/index.js.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/AI/ChainOfThought/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/01-basic/index.js +0 -29
- package/dist/elements/AI/ChainOfThought/variations/01-basic/index.js.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/01-basic/layout/ThoughtStep.d.ts +0 -8
- package/dist/elements/AI/ChainOfThought/variations/01-basic/layout/ThoughtStep.d.ts.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/01-basic/layout/ThoughtStep.js +0 -5
- package/dist/elements/AI/ChainOfThought/variations/01-basic/layout/ThoughtStep.js.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/index.d.ts +0 -2
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/index.d.ts.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/index.js +0 -61
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/index.js.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/layout/ExpandableThoughtStep.d.ts +0 -11
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/layout/ExpandableThoughtStep.d.ts.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/layout/ExpandableThoughtStep.js +0 -5
- package/dist/elements/AI/ChainOfThought/variations/02-with-details/layout/ExpandableThoughtStep.js.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/index.d.ts +0 -18
- package/dist/elements/AI/ChainOfThought/variations/index.d.ts.map +0 -1
- package/dist/elements/AI/ChainOfThought/variations/index.js +0 -14
- package/dist/elements/AI/ChainOfThought/variations/index.js.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/AI/Chat/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/index.js +0 -31
- package/dist/elements/AI/Chat/variations/01-basic/index.js.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatContainer.d.ts +0 -7
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatContainer.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatContainer.js +0 -5
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatContainer.js.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatInput.d.ts +0 -6
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatInput.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatInput.js +0 -14
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatInput.js.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatMessage.d.ts +0 -7
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatMessage.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatMessage.js +0 -7
- package/dist/elements/AI/Chat/variations/01-basic/layout/ChatMessage.js.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/index.d.ts +0 -2
- package/dist/elements/AI/Chat/variations/02-with-actions/index.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/index.js +0 -39
- package/dist/elements/AI/Chat/variations/02-with-actions/index.js.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatContainerWithActions.d.ts +0 -7
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatContainerWithActions.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatContainerWithActions.js +0 -5
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatContainerWithActions.js.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatInputWithActions.d.ts +0 -6
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatInputWithActions.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatInputWithActions.js +0 -14
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatInputWithActions.js.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatMessage.d.ts +0 -7
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatMessage.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatMessage.js +0 -7
- package/dist/elements/AI/Chat/variations/02-with-actions/layout/ChatMessage.js.map +0 -1
- package/dist/elements/AI/Chat/variations/index.d.ts +0 -18
- package/dist/elements/AI/Chat/variations/index.d.ts.map +0 -1
- package/dist/elements/AI/Chat/variations/index.js +0 -14
- package/dist/elements/AI/Chat/variations/index.js.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Documentation/CopyPage/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/01-basic/index.js +0 -7
- package/dist/elements/Documentation/CopyPage/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/01-basic/layout/CopyButton.d.ts +0 -2
- package/dist/elements/Documentation/CopyPage/variations/01-basic/layout/CopyButton.d.ts.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/01-basic/layout/CopyButton.js +0 -20
- package/dist/elements/Documentation/CopyPage/variations/01-basic/layout/CopyButton.js.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/index.d.ts +0 -2
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/index.d.ts.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/index.js +0 -13
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/index.js.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/layout/CopyButtonWithToast.d.ts +0 -6
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/layout/CopyButtonWithToast.d.ts.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/layout/CopyButtonWithToast.js +0 -21
- package/dist/elements/Documentation/CopyPage/variations/02-with-success/layout/CopyButtonWithToast.js.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/index.d.ts +0 -18
- package/dist/elements/Documentation/CopyPage/variations/index.d.ts.map +0 -1
- package/dist/elements/Documentation/CopyPage/variations/index.js +0 -14
- package/dist/elements/Documentation/CopyPage/variations/index.js.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Documentation/NextArticle/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/01-basic/index.js +0 -19
- package/dist/elements/Documentation/NextArticle/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/01-basic/layout/NextArticleCard.d.ts +0 -8
- package/dist/elements/Documentation/NextArticle/variations/01-basic/layout/NextArticleCard.d.ts.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/01-basic/layout/NextArticleCard.js +0 -5
- package/dist/elements/Documentation/NextArticle/variations/01-basic/layout/NextArticleCard.js.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/index.d.ts +0 -2
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/index.d.ts.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/index.js +0 -23
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/index.js.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/layout/NextArticleWithIconCard.d.ts +0 -10
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/layout/NextArticleWithIconCard.d.ts.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/layout/NextArticleWithIconCard.js +0 -5
- package/dist/elements/Documentation/NextArticle/variations/02-with-icon/layout/NextArticleWithIconCard.js.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/index.d.ts +0 -18
- package/dist/elements/Documentation/NextArticle/variations/index.d.ts.map +0 -1
- package/dist/elements/Documentation/NextArticle/variations/index.js +0 -14
- package/dist/elements/Documentation/NextArticle/variations/index.js.map +0 -1
- package/dist/elements/Documentation/TOC/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Documentation/TOC/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Documentation/TOC/variations/01-basic/index.js +0 -7
- package/dist/elements/Documentation/TOC/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Documentation/TOC/variations/01-basic/layout/TableOfContents.d.ts +0 -11
- package/dist/elements/Documentation/TOC/variations/01-basic/layout/TableOfContents.d.ts.map +0 -1
- package/dist/elements/Documentation/TOC/variations/01-basic/layout/TableOfContents.js +0 -12
- package/dist/elements/Documentation/TOC/variations/01-basic/layout/TableOfContents.js.map +0 -1
- package/dist/elements/Documentation/TOC/variations/02-expanded/index.d.ts +0 -2
- package/dist/elements/Documentation/TOC/variations/02-expanded/index.d.ts.map +0 -1
- package/dist/elements/Documentation/TOC/variations/02-expanded/index.js +0 -9
- package/dist/elements/Documentation/TOC/variations/02-expanded/index.js.map +0 -1
- package/dist/elements/Documentation/TOC/variations/02-expanded/layout/ExpandableTableOfContents.d.ts +0 -6
- package/dist/elements/Documentation/TOC/variations/02-expanded/layout/ExpandableTableOfContents.d.ts.map +0 -1
- package/dist/elements/Documentation/TOC/variations/02-expanded/layout/ExpandableTableOfContents.js +0 -45
- package/dist/elements/Documentation/TOC/variations/02-expanded/layout/ExpandableTableOfContents.js.map +0 -1
- package/dist/elements/Documentation/TOC/variations/index.d.ts +0 -18
- package/dist/elements/Documentation/TOC/variations/index.d.ts.map +0 -1
- package/dist/elements/Documentation/TOC/variations/index.js +0 -14
- package/dist/elements/Documentation/TOC/variations/index.js.map +0 -1
- package/dist/elements/Elements/Carousel/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Elements/Carousel/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Elements/Carousel/variations/01-basic/index.js +0 -6
- package/dist/elements/Elements/Carousel/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Elements/Carousel/variations/index.d.ts +0 -12
- package/dist/elements/Elements/Carousel/variations/index.d.ts.map +0 -1
- package/dist/elements/Elements/Carousel/variations/index.js +0 -11
- package/dist/elements/Elements/Carousel/variations/index.js.map +0 -1
- package/dist/elements/Elements/Rating/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Elements/Rating/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Elements/Rating/variations/01-basic/index.js +0 -6
- package/dist/elements/Elements/Rating/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Elements/Rating/variations/index.d.ts +0 -12
- package/dist/elements/Elements/Rating/variations/index.d.ts.map +0 -1
- package/dist/elements/Elements/Rating/variations/index.js +0 -11
- package/dist/elements/Elements/Rating/variations/index.js.map +0 -1
- package/dist/elements/Elements/Timeline/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Elements/Timeline/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Elements/Timeline/variations/01-basic/index.js +0 -6
- package/dist/elements/Elements/Timeline/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Elements/Timeline/variations/index.d.ts +0 -12
- package/dist/elements/Elements/Timeline/variations/index.d.ts.map +0 -1
- package/dist/elements/Elements/Timeline/variations/index.js +0 -11
- package/dist/elements/Elements/Timeline/variations/index.js.map +0 -1
- package/dist/elements/Elements/TreeView/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/Elements/TreeView/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/Elements/TreeView/variations/01-basic/index.js +0 -6
- package/dist/elements/Elements/TreeView/variations/01-basic/index.js.map +0 -1
- package/dist/elements/Elements/TreeView/variations/index.d.ts +0 -12
- package/dist/elements/Elements/TreeView/variations/index.d.ts.map +0 -1
- package/dist/elements/Elements/TreeView/variations/index.js +0 -11
- package/dist/elements/Elements/TreeView/variations/index.js.map +0 -1
- package/dist/elements/foundation/Header/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/foundation/Header/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/foundation/Header/variations/01-basic/index.js +0 -7
- package/dist/elements/foundation/Header/variations/01-basic/index.js.map +0 -1
- package/dist/elements/foundation/Header/variations/01-basic/layout/Header.d.ts +0 -6
- package/dist/elements/foundation/Header/variations/01-basic/layout/Header.d.ts.map +0 -1
- package/dist/elements/foundation/Header/variations/01-basic/layout/Header.js +0 -5
- package/dist/elements/foundation/Header/variations/01-basic/layout/Header.js.map +0 -1
- package/dist/elements/foundation/Header/variations/index.d.ts +0 -12
- package/dist/elements/foundation/Header/variations/index.d.ts.map +0 -1
- package/dist/elements/foundation/Header/variations/index.js +0 -11
- package/dist/elements/foundation/Header/variations/index.js.map +0 -1
- package/dist/elements/foundation/Page/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/foundation/Page/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/foundation/Page/variations/01-basic/index.js +0 -7
- package/dist/elements/foundation/Page/variations/01-basic/index.js.map +0 -1
- package/dist/elements/foundation/Page/variations/01-basic/layout/Page.d.ts +0 -7
- package/dist/elements/foundation/Page/variations/01-basic/layout/Page.d.ts.map +0 -1
- package/dist/elements/foundation/Page/variations/01-basic/layout/Page.js +0 -5
- package/dist/elements/foundation/Page/variations/01-basic/layout/Page.js.map +0 -1
- package/dist/elements/foundation/Page/variations/index.d.ts +0 -12
- package/dist/elements/foundation/Page/variations/index.d.ts.map +0 -1
- package/dist/elements/foundation/Page/variations/index.js +0 -11
- package/dist/elements/foundation/Page/variations/index.js.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/01-basic/index.d.ts +0 -2
- package/dist/elements/foundation/Sidebar/variations/01-basic/index.d.ts.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/01-basic/index.js +0 -7
- package/dist/elements/foundation/Sidebar/variations/01-basic/index.js.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/01-basic/layout/Sidebar.d.ts +0 -6
- package/dist/elements/foundation/Sidebar/variations/01-basic/layout/Sidebar.d.ts.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/01-basic/layout/Sidebar.js +0 -48
- package/dist/elements/foundation/Sidebar/variations/01-basic/layout/Sidebar.js.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/index.d.ts +0 -12
- package/dist/elements/foundation/Sidebar/variations/index.d.ts.map +0 -1
- package/dist/elements/foundation/Sidebar/variations/index.js +0 -11
- package/dist/elements/foundation/Sidebar/variations/index.js.map +0 -1
- package/dist/generated-controls.d.ts +0 -3
- package/dist/generated-controls.d.ts.map +0 -1
- package/dist/generated-controls.js +0 -161
- package/dist/generated-controls.js.map +0 -1
- package/dist/providers/Theme/examples/01-provider-setup.d.ts +0 -28
- package/dist/providers/Theme/examples/01-provider-setup.d.ts.map +0 -1
- package/dist/providers/Theme/examples/01-provider-setup.js +0 -35
- package/dist/providers/Theme/examples/01-provider-setup.js.map +0 -1
- package/dist/providers/Theme/examples/02-toggle-component.d.ts +0 -32
- package/dist/providers/Theme/examples/02-toggle-component.d.ts.map +0 -1
- package/dist/providers/Theme/examples/02-toggle-component.js +0 -50
- package/dist/providers/Theme/examples/02-toggle-component.js.map +0 -1
- package/dist/providers/Theme/examples/03-advanced-patterns.d.ts +0 -134
- package/dist/providers/Theme/examples/03-advanced-patterns.d.ts.map +0 -1
- package/dist/providers/Theme/examples/03-advanced-patterns.js +0 -134
- package/dist/providers/Theme/examples/03-advanced-patterns.js.map +0 -1
- package/dist/providers/Theme/examples/index.d.ts +0 -4
- package/dist/providers/Theme/examples/index.d.ts.map +0 -1
- package/dist/providers/Theme/examples/index.js +0 -4
- package/dist/providers/Theme/examples/index.js.map +0 -1
- package/dist/sections/CTA/variations/01-banner/index.d.ts +0 -7
- package/dist/sections/CTA/variations/01-banner/index.d.ts.map +0 -1
- package/dist/sections/CTA/variations/01-banner/index.js +0 -13
- package/dist/sections/CTA/variations/01-banner/index.js.map +0 -1
- package/dist/sections/CTA/variations/02-split/index.d.ts +0 -7
- package/dist/sections/CTA/variations/02-split/index.d.ts.map +0 -1
- package/dist/sections/CTA/variations/02-split/index.js +0 -19
- package/dist/sections/CTA/variations/02-split/index.js.map +0 -1
- package/dist/sections/CTA/variations/index.d.ts +0 -13
- package/dist/sections/CTA/variations/index.d.ts.map +0 -1
- package/dist/sections/CTA/variations/index.js +0 -7
- package/dist/sections/CTA/variations/index.js.map +0 -1
- package/dist/sections/Features/variations/01-grid/index.d.ts +0 -7
- package/dist/sections/Features/variations/01-grid/index.d.ts.map +0 -1
- package/dist/sections/Features/variations/01-grid/index.js +0 -47
- package/dist/sections/Features/variations/01-grid/index.js.map +0 -1
- package/dist/sections/Features/variations/02-list/index.d.ts +0 -7
- package/dist/sections/Features/variations/02-list/index.d.ts.map +0 -1
- package/dist/sections/Features/variations/02-list/index.js +0 -52
- package/dist/sections/Features/variations/02-list/index.js.map +0 -1
- package/dist/sections/Features/variations/index.d.ts +0 -13
- package/dist/sections/Features/variations/index.d.ts.map +0 -1
- package/dist/sections/Features/variations/index.js +0 -7
- package/dist/sections/Features/variations/index.js.map +0 -1
- package/dist/sections/Hero/variations/01-simple/index.d.ts +0 -7
- package/dist/sections/Hero/variations/01-simple/index.d.ts.map +0 -1
- package/dist/sections/Hero/variations/01-simple/index.js +0 -12
- package/dist/sections/Hero/variations/01-simple/index.js.map +0 -1
- package/dist/sections/Hero/variations/02-with-cta/index.d.ts +0 -7
- package/dist/sections/Hero/variations/02-with-cta/index.d.ts.map +0 -1
- package/dist/sections/Hero/variations/02-with-cta/index.js +0 -12
- package/dist/sections/Hero/variations/02-with-cta/index.js.map +0 -1
- package/dist/sections/Hero/variations/03-with-stats/index.d.ts +0 -7
- package/dist/sections/Hero/variations/03-with-stats/index.d.ts.map +0 -1
- package/dist/sections/Hero/variations/03-with-stats/index.js +0 -18
- package/dist/sections/Hero/variations/03-with-stats/index.js.map +0 -1
- package/dist/sections/Hero/variations/04-with-features/index.d.ts +0 -7
- package/dist/sections/Hero/variations/04-with-features/index.d.ts.map +0 -1
- package/dist/sections/Hero/variations/04-with-features/index.js +0 -38
- package/dist/sections/Hero/variations/04-with-features/index.js.map +0 -1
- package/dist/sections/Hero/variations/index.d.ts +0 -23
- package/dist/sections/Hero/variations/index.d.ts.map +0 -1
- package/dist/sections/Hero/variations/index.js +0 -11
- package/dist/sections/Hero/variations/index.js.map +0 -1
- package/dist/sections/Pricing/variations/01-cards/index.d.ts +0 -7
- package/dist/sections/Pricing/variations/01-cards/index.d.ts.map +0 -1
- package/dist/sections/Pricing/variations/01-cards/index.js +0 -66
- package/dist/sections/Pricing/variations/01-cards/index.js.map +0 -1
- package/dist/sections/Pricing/variations/02-comparison/index.d.ts +0 -7
- package/dist/sections/Pricing/variations/02-comparison/index.d.ts.map +0 -1
- package/dist/sections/Pricing/variations/02-comparison/index.js +0 -53
- package/dist/sections/Pricing/variations/02-comparison/index.js.map +0 -1
- package/dist/sections/Pricing/variations/index.d.ts +0 -13
- package/dist/sections/Pricing/variations/index.d.ts.map +0 -1
- package/dist/sections/Pricing/variations/index.js +0 -7
- package/dist/sections/Pricing/variations/index.js.map +0 -1
- package/dist/sections/Testimonials/variations/01-cards/index.d.ts +0 -7
- package/dist/sections/Testimonials/variations/01-cards/index.d.ts.map +0 -1
- package/dist/sections/Testimonials/variations/01-cards/index.js +0 -38
- package/dist/sections/Testimonials/variations/01-cards/index.js.map +0 -1
- package/dist/sections/Testimonials/variations/02-featured/index.d.ts +0 -7
- package/dist/sections/Testimonials/variations/02-featured/index.d.ts.map +0 -1
- package/dist/sections/Testimonials/variations/02-featured/index.js +0 -53
- package/dist/sections/Testimonials/variations/02-featured/index.js.map +0 -1
- package/dist/sections/Testimonials/variations/index.d.ts +0 -13
- package/dist/sections/Testimonials/variations/index.d.ts.map +0 -1
- package/dist/sections/Testimonials/variations/index.js +0 -7
- package/dist/sections/Testimonials/variations/index.js.map +0 -1
- package/dist/src/generated-styles.d.ts +0 -7
- package/dist/src/generated-styles.d.ts.map +0 -1
- package/dist/src/generated-styles.js +0 -1360
- package/dist/src/generated-styles.js.map +0 -1
- package/src/components/Anchor/examples/01-inline-text.tsx +0 -22
- package/src/components/Anchor/examples/02-underline-variants.tsx +0 -24
- package/src/components/Anchor/examples/03-preview-tooltip.tsx +0 -27
- package/src/components/Anchor/examples/04-breadcrumb.tsx +0 -29
- package/src/components/Badge/examples/01-status-badges.tsx +0 -17
- package/src/components/Badge/examples/02-icon-position.tsx +0 -18
- package/src/components/Badge/examples/03-selectable-tags.tsx +0 -40
- package/src/components/Badge/examples/04-dismissible.tsx +0 -37
- package/src/components/Badge/examples/05-semantic-colors.tsx +0 -18
- package/src/components/Banner/examples/01-variants.tsx +0 -33
- package/src/components/Banner/examples/02-dismissible.tsx +0 -31
- package/src/components/Banner/examples/03-form-feedback.tsx +0 -47
- package/src/components/Banner/examples/04-settings-panel.tsx +0 -21
- package/src/components/Banner/examples/05-body-only.tsx +0 -22
- package/src/components/Button/examples/01-variants.tsx +0 -28
- package/src/components/Button/examples/02-multi-actions.tsx +0 -19
- package/src/components/Button/examples/03-joined-toggle.tsx +0 -32
- package/src/components/Button/examples/04-sub-stack-actions.tsx +0 -29
- package/src/components/Button/examples/05-split-action-button.tsx +0 -96
- package/src/components/Button/examples/06-icons.tsx +0 -25
- package/src/components/Button/examples/07-split-button.tsx +0 -47
- package/src/components/Button/examples/08-button-group.tsx +0 -30
- package/src/components/Button/examples.json +0 -42
- package/src/components/Card/examples/01-notification.tsx +0 -37
- package/src/components/Card/examples/02-settings-panel.tsx +0 -48
- package/src/components/Card/examples/03-task-progress.tsx +0 -43
- package/src/components/Checkbox/examples/01-basic-states.tsx +0 -17
- package/src/components/Checkbox/examples/02-helper-text.tsx +0 -26
- package/src/components/Checkbox/examples/03-controlled.tsx +0 -28
- package/src/components/Checkbox/examples/04-group.tsx +0 -49
- package/src/components/Checkbox/examples/05-indeterminate.tsx +0 -56
- package/src/components/Checkbox/examples/06-consent-form.tsx +0 -35
- package/src/components/Color/examples/01-basic-color-picker.tsx +0 -18
- package/src/components/Color/examples/02-color-picker-opacity.tsx +0 -29
- package/src/components/Color/examples/03-color-picker-preview.tsx +0 -27
- package/src/components/Color/examples/04-color-slider-primitive.tsx +0 -47
- package/src/components/Command/examples/01-basic-command.tsx +0 -79
- package/src/components/Confirm/examples/01-basic-confirm.tsx +0 -20
- package/src/components/Date/examples/01-basic-date.tsx +0 -12
- package/src/components/Date/examples/02-with-disabled-dates.tsx +0 -22
- package/src/components/Date/examples/03-controlled-mode.tsx +0 -46
- package/src/components/Date/examples/04-date-range.tsx +0 -82
- package/src/components/Divider/examples/01-basic-divider.tsx +0 -17
- package/src/components/Divider/examples/02-pattern-variants.tsx +0 -25
- package/src/components/Divider/examples/03-vertical-divider.tsx +0 -21
- package/src/components/Expand/examples/01-basic.tsx +0 -18
- package/src/components/Expand/examples/02-accordion.tsx +0 -46
- package/src/components/Expand/examples/03-custom-trigger.tsx +0 -30
- package/src/components/Expand/examples/04-directions.tsx +0 -33
- package/src/components/Expand/examples/05-settings-panel.tsx +0 -54
- package/src/components/Expand/examples/06-disabled.tsx +0 -19
- package/src/components/Expand/examples/07-inline-info.tsx +0 -29
- package/src/components/Frame/examples/01-default-frame.tsx +0 -33
- package/src/components/Frame/examples/02-tooltip-example.tsx +0 -35
- package/src/components/Frame/examples/03-sidebar-tab.tsx +0 -50
- package/src/components/Grid/examples/01-basic-grid.tsx +0 -20
- package/src/components/Group/examples/01-basic-group.tsx +0 -16
- package/src/components/Group/examples/02-create-project.tsx +0 -19
- package/src/components/Group/examples/03-filter-bar.tsx +0 -34
- package/src/components/Group/examples/04-documentation-search.tsx +0 -21
- package/src/components/Group/examples/05-email-signup.tsx +0 -21
- package/src/components/Group/examples/06-copy-command.tsx +0 -17
- package/src/components/Group/examples/07-delete-confirmation.tsx +0 -19
- package/src/components/Group/examples/08-slider-integration.tsx +0 -30
- package/src/components/Group/examples/examples.json +0 -10
- package/src/components/Group/examples.json +0 -42
- package/src/components/Input/examples/01-basic-input.tsx +0 -11
- package/src/components/Input/examples/02-validation.tsx +0 -53
- package/src/components/Input/examples/03-sign-in.tsx +0 -41
- package/src/components/Input/examples/04-search.tsx +0 -31
- package/src/components/Input/examples/05-user-handle.tsx +0 -40
- package/src/components/Input/examples/06-api-key.tsx +0 -48
- package/src/components/Input/examples/07-url-validation.tsx +0 -36
- package/src/components/Input/examples/08-quantity.tsx +0 -26
- package/src/components/Input/examples/examples.json +0 -16
- package/src/components/Label/examples/01-basic-label.tsx +0 -16
- package/src/components/List/examples/01-basic.tsx +0 -25
- package/src/components/List/examples/02-review-queue.tsx +0 -54
- package/src/components/List/examples/03-notification-rules.tsx +0 -80
- package/src/components/List/examples/04-quota-editor.tsx +0 -71
- package/src/components/List/examples/05-permissions-matrix.tsx +0 -91
- package/src/components/Mask/examples/01-read-more-fade.tsx +0 -33
- package/src/components/Mask/examples/02-text-gradient.tsx +0 -21
- package/src/components/Menu/examples/01-basic-menu.tsx +0 -22
- package/src/components/Menu/examples/02-nested-menu.tsx +0 -49
- package/src/components/Menu/examples/03-toolbar-dropdown.tsx +0 -35
- package/src/components/Menu/examples/04-table-row-actions.tsx +0 -60
- package/src/components/Menu/examples/05-context-menu.tsx +0 -36
- package/src/components/Menu/examples/06-view-options.tsx +0 -39
- package/src/components/Modal/examples/01-basic-modal.tsx +0 -24
- package/src/components/Modal/examples/02-form-modal.tsx +0 -88
- package/src/components/Modal/examples/03-delete-confirmation.tsx +0 -42
- package/src/components/Modal/examples/04-create-api-key.tsx +0 -54
- package/src/components/Modal/examples/05-notification-settings.tsx +0 -58
- package/src/components/Panel/examples/01-sidebar-toggle.tsx +0 -20
- package/src/components/Path/examples/01-basic-path.tsx +0 -17
- package/src/components/Path/examples/02-custom-separator.tsx +0 -17
- package/src/components/Path/examples/03-collapsed-breadcrumb.tsx +0 -37
- package/src/components/Popover/examples/01-basic-popover.tsx +0 -34
- package/src/components/Popover/examples/02-toggleable-options.tsx +0 -58
- package/src/components/Popover/examples/03-table-row-actions.tsx +0 -64
- package/src/components/Popover/examples/04-input-form.tsx +0 -46
- package/src/components/Popover/examples/05-arrow-positions.tsx +0 -27
- package/src/components/Progress/examples/01-basic-progress.tsx +0 -40
- package/src/components/Progress/examples/02-storage-quota.tsx +0 -22
- package/src/components/Progress/examples/03-onboarding-steps.tsx +0 -34
- package/src/components/Progress/examples/04-indeterminate.tsx +0 -33
- package/src/components/Progress/examples/05-skill-levels.tsx +0 -22
- package/src/components/Radio/examples/01-basic-radio.tsx +0 -13
- package/src/components/Radio/examples/02-radio-with-descriptions.tsx +0 -31
- package/src/components/Radio/examples/examples.json +0 -8
- package/src/components/Scroll/examples/01-basic-scroll.tsx +0 -55
- package/src/components/Scroll/examples/02-settings-panel.tsx +0 -40
- package/src/components/Scroll/examples/03-horizontal-tags.tsx +0 -38
- package/src/components/Select/examples/01-basic-select.tsx +0 -22
- package/src/components/Select/examples/02-searchable-select.tsx +0 -51
- package/src/components/Select/examples/03-country-select.tsx +0 -55
- package/src/components/Slider/examples/01-basic-slider.tsx +0 -26
- package/src/components/Slider/examples/02-settings-panel.tsx +0 -33
- package/src/components/Slider/examples/03-price-range.tsx +0 -34
- package/src/components/Slider/examples/04-step-slider.tsx +0 -35
- package/src/components/Slider/examples/05-disabled-state.tsx +0 -21
- package/src/components/Slider/examples/06-vertical-mixer.tsx +0 -34
- package/src/components/Switch/examples/01-basic-switch.tsx +0 -27
- package/src/components/Switch/examples/02-settings-panel.tsx +0 -32
- package/src/components/Switch/examples/03-disabled-state.tsx +0 -21
- package/src/components/Switch/examples/04-small-size.tsx +0 -25
- package/src/components/Switch/examples/05-controlled-toggle.tsx +0 -32
- package/src/components/Table/examples/01-basic-table.tsx +0 -27
- package/src/components/Tabs/examples/01-basic-tabs.tsx +0 -28
- package/src/components/Tabs/examples/02-vertical-tabs.tsx +0 -103
- package/src/components/Tabs/examples/03-underline-tabs.tsx +0 -23
- package/src/components/Tabs/examples/04-vertical-underline-tabs.tsx +0 -23
- package/src/components/Textarea/examples/01-basic-textarea.tsx +0 -29
- package/src/components/Textarea/examples/02-bio-settings.tsx +0 -30
- package/src/components/Textarea/examples/03-error-state.tsx +0 -31
- package/src/components/Textarea/examples/04-disabled-readonly.tsx +0 -25
- package/src/components/Textarea/examples/05-scrolling.tsx +0 -26
- package/src/components/Toast/examples/01-basic-toast.tsx +0 -20
- package/src/components/Toast/examples/02-success-toast.tsx +0 -27
- package/src/components/Toast/examples/03-danger-toast.tsx +0 -27
- package/src/components/Toast/examples/04-info-toast.tsx +0 -27
- package/src/components/Toast/examples/05-warning-toast.tsx +0 -27
- package/src/components/Tooltip/examples/01-basic-tooltip.tsx +0 -15
- package/src/design-tokens/index.ts +0 -196
- package/src/dist/generated-styles.json +0 -1358
- package/src/elements/AI/AIChatInput/variations/01-basic/index.tsx +0 -39
- package/src/elements/AI/AIChatInput/variations/01-basic/layout/PromptInput.tsx +0 -58
- package/src/elements/AI/AIChatInput/variations/02-with-suggestions/index.tsx +0 -67
- package/src/elements/AI/AIChatInput/variations/02-with-suggestions/layout/PromptInputWithSuggestions.tsx +0 -63
- package/src/elements/AI/AIChatInput/variations/index.ts +0 -18
- package/src/elements/AI/ChainOfThought/variations/01-basic/index.tsx +0 -49
- package/src/elements/AI/ChainOfThought/variations/01-basic/layout/ThoughtStep.tsx +0 -22
- package/src/elements/AI/ChainOfThought/variations/02-with-details/index.tsx +0 -80
- package/src/elements/AI/ChainOfThought/variations/02-with-details/layout/ExpandableThoughtStep.tsx +0 -48
- package/src/elements/AI/ChainOfThought/variations/index.ts +0 -18
- package/src/elements/AI/Chat/variations/01-basic/index.tsx +0 -54
- package/src/elements/AI/Chat/variations/01-basic/layout/ChatContainer.tsx +0 -13
- package/src/elements/AI/Chat/variations/01-basic/layout/ChatInput.tsx +0 -35
- package/src/elements/AI/Chat/variations/01-basic/layout/ChatMessage.tsx +0 -20
- package/src/elements/AI/Chat/variations/02-with-actions/index.tsx +0 -83
- package/src/elements/AI/Chat/variations/02-with-actions/layout/ChatContainerWithActions.tsx +0 -13
- package/src/elements/AI/Chat/variations/02-with-actions/layout/ChatInputWithActions.tsx +0 -35
- package/src/elements/AI/Chat/variations/02-with-actions/layout/ChatMessage.tsx +0 -20
- package/src/elements/AI/Chat/variations/index.ts +0 -18
- package/src/elements/Documentation/CopyPage/variations/01-basic/index.tsx +0 -55
- package/src/elements/Documentation/CopyPage/variations/01-basic/layout/CopyButton.tsx +0 -30
- package/src/elements/Documentation/CopyPage/variations/02-with-success/index.tsx +0 -63
- package/src/elements/Documentation/CopyPage/variations/02-with-success/layout/CopyButtonWithToast.tsx +0 -33
- package/src/elements/Documentation/CopyPage/variations/index.ts +0 -18
- package/src/elements/Documentation/NextArticle/variations/01-basic/index.tsx +0 -42
- package/src/elements/Documentation/NextArticle/variations/01-basic/layout/NextArticleCard.tsx +0 -27
- package/src/elements/Documentation/NextArticle/variations/02-with-icon/index.tsx +0 -44
- package/src/elements/Documentation/NextArticle/variations/02-with-icon/layout/NextArticleWithIconCard.tsx +0 -34
- package/src/elements/Documentation/NextArticle/variations/index.ts +0 -18
- package/src/elements/Documentation/TOC/variations/01-basic/index.tsx +0 -61
- package/src/elements/Documentation/TOC/variations/01-basic/layout/TableOfContents.tsx +0 -37
- package/src/elements/Documentation/TOC/variations/02-expanded/index.tsx +0 -67
- package/src/elements/Documentation/TOC/variations/02-expanded/layout/ExpandableTableOfContents.tsx +0 -91
- package/src/elements/Documentation/TOC/variations/index.ts +0 -18
- package/src/elements/Elements/Carousel/variations/01-basic/index.tsx +0 -4
- package/src/elements/Elements/Carousel/variations/index.ts +0 -15
- package/src/elements/Elements/Rating/variations/01-basic/index.tsx +0 -4
- package/src/elements/Elements/Rating/variations/index.ts +0 -15
- package/src/elements/Elements/Timeline/variations/01-basic/index.tsx +0 -4
- package/src/elements/Elements/Timeline/variations/index.ts +0 -15
- package/src/elements/Elements/TreeView/variations/01-basic/index.tsx +0 -4
- package/src/elements/Elements/TreeView/variations/index.ts +0 -15
- package/src/elements/foundation/Header/variations/01-basic/index.tsx +0 -46
- package/src/elements/foundation/Header/variations/01-basic/layout/Header.tsx +0 -21
- package/src/elements/foundation/Header/variations/index.ts +0 -15
- package/src/elements/foundation/Page/variations/01-basic/index.tsx +0 -40
- package/src/elements/foundation/Page/variations/01-basic/layout/Page.tsx +0 -29
- package/src/elements/foundation/Page/variations/index.ts +0 -15
- package/src/elements/foundation/Sidebar/variations/01-basic/index.tsx +0 -15
- package/src/elements/foundation/Sidebar/variations/01-basic/layout/Sidebar.tsx +0 -158
- package/src/elements/foundation/Sidebar/variations/index.ts +0 -15
- package/src/sections/CTA/variations/01-banner/index.tsx +0 -52
- package/src/sections/CTA/variations/02-split/index.tsx +0 -90
- package/src/sections/CTA/variations/index.ts +0 -7
- package/src/sections/Features/variations/01-grid/index.tsx +0 -91
- package/src/sections/Features/variations/02-list/index.tsx +0 -124
- package/src/sections/Features/variations/index.ts +0 -7
- package/src/sections/Hero/variations/01-simple/index.tsx +0 -46
- package/src/sections/Hero/variations/02-with-cta/index.tsx +0 -74
- package/src/sections/Hero/variations/03-with-stats/index.tsx +0 -63
- package/src/sections/Hero/variations/04-with-features/index.tsx +0 -87
- package/src/sections/Hero/variations/index.ts +0 -11
- package/src/sections/Pricing/variations/01-cards/index.tsx +0 -153
- package/src/sections/Pricing/variations/02-comparison/index.tsx +0 -150
- package/src/sections/Pricing/variations/index.ts +0 -7
- package/src/sections/Testimonials/variations/01-cards/index.tsx +0 -93
- package/src/sections/Testimonials/variations/02-featured/index.tsx +0 -155
- package/src/sections/Testimonials/variations/index.ts +0 -7
package/dist/generated-data.js
CHANGED
|
@@ -190,48 +190,7 @@ export const generatedAPI = {
|
|
|
190
190
|
"description": "Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those."
|
|
191
191
|
}
|
|
192
192
|
],
|
|
193
|
-
"examples": [
|
|
194
|
-
{
|
|
195
|
-
"title": "Button Variants",
|
|
196
|
-
"description": "All available button variants side by side in a single row.",
|
|
197
|
-
"code": "import React from 'react'\nimport { Button, Flex } from 'ui-lab-components'\n\nconst buttonVariants = [\n { label: \"Primary\", variant: \"primary\" },\n { label: \"Default\", variant: \"default\" },\n { label: \"Secondary\", variant: \"secondary\" },\n { label: \"Outline\", variant: \"outline\" },\n { label: \"Ghost\", variant: \"ghost\" },\n { label: \"Danger\", variant: \"danger\" },\n] as const;\n\nexport default function Example() {\n return (\n <Flex gap=\"xs\" align=\"center\" justify=\"center\" wrap=\"nowrap\">\n {buttonVariants.map((button) => (\n <Button key={button.variant} variant={button.variant}>\n {button.label}\n </Button>\n ))}\n </Flex>\n )\n}"
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
"title": "Multiple Actions",
|
|
201
|
-
"description": "A primary action button grouped with secondary actions and an options menu.",
|
|
202
|
-
"code": "\"use client\";\n\nimport { Button, Flex } from 'ui-lab-components'\nimport { FaEllipsisVertical } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Flex gap=\"xs\" className=\"w-110 *:not-last:flex-1\">\n <Button size=\"sm\" variant=\"primary\" >Subscribe</Button>\n <Button size=\"sm\" >Message</Button>\n <Button size=\"icon\" variant=\"outline\" icon={<FaEllipsisVertical />} />\n </Flex>\n );\n}"
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
"title": "Joined Toggle Buttons",
|
|
206
|
-
"description": "Multiple buttons grouped together for view/mode selection with active state indication.",
|
|
207
|
-
"code": "\"use client\";\n\nimport React, { useState } from 'react'\nimport { Button, Group, Divider, Input, Flex } from 'ui-lab-components'\nimport { FaList, FaGrip, FaTable, FaPlus } from \"react-icons/fa6\";\nimport { LuSearch } from \"react-icons/lu\";\n\nexport default function Example() {\n const [viewMode, setViewMode] = useState(\"list\");\n return (\n <Flex className=\"w-110\" gap=\"xs\" align=\"center\">\n <Input\n placeholder=\"Search items...\"\n icon={<LuSearch />}\n className=\"w-full\"\n />\n <Group orientation=\"horizontal\" value={viewMode} onChange={setViewMode}>\n <Group.Button size=\"icon\" value=\"list\"><FaList /></Group.Button>\n <Divider orientation=\"vertical\" />\n <Group.Button size=\"icon\" value=\"grid\"><FaGrip /></Group.Button>\n <Divider orientation=\"vertical\" />\n <Group.Button size=\"icon\" value=\"table\"><FaTable /></Group.Button>\n </Group>\n <Button size=\"sm\" icon={{ left: <FaPlus size={12} /> }} >New</Button>\n </Flex>\n );\n}"
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
"title": "Sub Stack Actions",
|
|
211
|
-
"description": "A collection of buttons and inputs arranged horizontally for grouped actions and filtering.",
|
|
212
|
-
"code": "\"use client\";\n\nimport React, { useState } from 'react'\nimport { Button, Group, Input, Badge, Flex } from 'ui-lab-components'\nimport { FaList, FaGrip, FaPlus } from \"react-icons/fa6\";\nimport { LuSearch } from \"react-icons/lu\";\n\nexport default function Example() {\n const [viewMode, setViewMode] = useState(\"list\");\n return (\n <Flex align=\"center\" gap=\"xs\" className=\"w-110\">\n <Group orientation=\"horizontal\" spacing=\"xs\" value={viewMode} onChange={setViewMode}>\n <Group.Button size=\"icon\" value=\"list\"><FaList /></Group.Button>\n <Group.Button size=\"icon\" value=\"grid\"><FaGrip /></Group.Button>\n </Group>\n <Input\n placeholder=\"Search...\"\n icon={<LuSearch />}\n hint={<Badge variant=\"secondary\" >Ctrl+K</Badge>}\n />\n <Button size=\"sm\" icon={{ right: <FaPlus size={12} /> }} >Upload</Button>\n </Flex>\n );\n}"
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
"title": "Split Action Button",
|
|
216
|
-
"description": "A split button for bulk actions with dynamic icons, variants, and async feedback while keeping the primary action easy to repeat.",
|
|
217
|
-
"code": "\"use client\";\n\nimport React, { useState } from 'react'\nimport { Button, Divider, Select, Badge, Flex } from 'ui-lab-components'\nimport { FaBox, FaSpinner, FaCheck, FaEllipsisVertical, FaCopy, FaTags, FaTrash } from \"react-icons/fa6\";\n\ntype BulkAction = \"archive\" | \"duplicate\" | \"tag\" | \"delete\";\n\nconst selectedCount: number = 12;\n\nconst bulkActions: Record<BulkAction, {\n label: string;\n loadingLabel: string;\n successLabel: string;\n variant: \"primary\" | \"outline\" | \"danger\";\n icon: React.ReactNode;\n}> = {\n archive: {\n label: \"Archive\",\n loadingLabel: \"Archiving...\",\n successLabel: \"Archived\",\n variant: \"primary\",\n icon: <FaBox />,\n },\n duplicate: {\n label: \"Duplicate\",\n loadingLabel: \"Duplicating...\",\n successLabel: \"Duplicated\",\n variant: \"outline\",\n icon: <FaCopy />,\n },\n tag: {\n label: \"Add Tags\",\n loadingLabel: \"Applying tags...\",\n successLabel: \"Tagged\",\n variant: \"outline\",\n icon: <FaTags />,\n },\n delete: {\n label: \"Delete\",\n loadingLabel: \"Deleting...\",\n successLabel: \"Deleted\",\n variant: \"danger\",\n icon: <FaTrash />,\n },\n};\n\nexport default function Example() {\n const [action, setAction] = useState<BulkAction>(\"archive\");\n const [status, setStatus] = useState<\"idle\" | \"loading\" | \"done\">(\"idle\");\n const cfg = bulkActions[action];\n const itemsLabel = `${selectedCount} ${selectedCount === 1 ? \"item\" : \"items\"}`;\n\n const handleExecute = () => {\n setStatus(\"loading\");\n setTimeout(() => {\n setStatus(\"done\");\n setTimeout(() => setStatus(\"idle\"), 2000);\n }, 1500);\n };\n\n const leftIcon = status === \"loading\" ? <FaSpinner className=\"animate-spin\" /> : status === \"done\" ? <FaCheck /> : cfg.icon;\n const label = status === \"loading\" ? cfg.loadingLabel : status === \"done\" ? cfg.successLabel : `${cfg.label} ${itemsLabel}`;\n\n return (\n <Flex gap=\"xs\" className=\"w-110\" align=\"center\">\n <Badge variant=\"secondary\">{selectedCount} selected</Badge>\n <Select className=\"flex h-10\" selectedKey={action} onSelectionChange={(key) => setAction(key as BulkAction)} isDisabled={status !== \"idle\"}>\n <Button\n onPress={handleExecute}\n variant={cfg.variant}\n size=\"sm\"\n className=\"w-full rounded-none justify-start\"\n isDisabled={status !== \"idle\" || selectedCount === 0}\n icon={leftIcon}\n >\n {label}\n </Button>\n <Divider orientation=\"vertical\" spacing=\"none\" />\n <Select.Trigger aria-label=\"Choose a bulk action\" />\n <Select.Content>\n <Select.Item value=\"archive\" textValue=\"Archive\" icon={<FaBox className=\"h-3 w-3\" />}>Archive</Select.Item>\n <Select.Item value=\"duplicate\" textValue=\"Duplicate\" icon={<FaCopy className=\"h-3 w-3\" />}>Duplicate</Select.Item>\n <Select.Item value=\"tag\" textValue=\"Add Tags\" icon={<FaTags className=\"h-3 w-3\" />}>Add Tags</Select.Item>\n <Select.Item value=\"delete\" textValue=\"Delete\" icon={<FaTrash className=\"h-3 w-3\" />}>Delete</Select.Item>\n </Select.Content>\n </Select>\n <Button size=\"icon\" variant=\"outline\" icon={<FaEllipsisVertical />} aria-label=\"More bulk actions\" />\n </Flex>\n );\n}"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
"title": "Icons",
|
|
221
|
-
"description": "Left, right, and icon-only button patterns.",
|
|
222
|
-
"code": "import React from 'react'\nimport { Button, Flex } from 'ui-lab-components'\nimport { FaArrowRight, FaDownload, FaEllipsisVertical, FaPlus } from 'react-icons/fa6'\n\nexport default function Example() {\n return (\n <Flex gap=\"xs\" align=\"center\" justify=\"center\" wrap=\"wrap\">\n <Button variant=\"primary\" icon={{ left: <FaPlus /> }}>\n New Project\n </Button>\n <Button variant=\"outline\" icon={{ right: <FaArrowRight /> }}>\n Continue\n </Button>\n <Button variant=\"secondary\" icon={<FaDownload />}>\n Download\n </Button>\n <Button size=\"icon\" variant=\"ghost\" aria-label=\"More actions\" icon={<FaEllipsisVertical />} />\n </Flex>\n )\n}"
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
"title": "Split Button",
|
|
226
|
-
"description": "Group + Select primitives for a classic split button with a primary action and a separate menu trigger.",
|
|
227
|
-
"code": "\"use client\";\n\nimport React, { useState } from 'react'\nimport { Button, Divider, Flex, Group, Select } from 'ui-lab-components'\nimport { FaChevronDown } from 'react-icons/fa6'\n\nconst splitActions = [\n { value: \"publish\", label: \"Publish now\" },\n { value: \"schedule\", label: \"Schedule publish\" },\n { value: \"save\", label: \"Save draft\" },\n] as const;\n\nexport default function Example() {\n const [action, setAction] = useState<string | number | null>(splitActions[0].value);\n const selectedAction = splitActions.find((item) => item.value === action) ?? splitActions[0];\n\n return (\n <Flex direction=\"column\" gap=\"sm\" align=\"center\">\n <Group orientation=\"horizontal\">\n <Group.Select className=\"w-full\" selectedKey={action} onSelectionChange={setAction}>\n <Select.Value>\n <Button variant=\"primary\">{selectedAction.label}</Button>\n </Select.Value>\n <Divider />\n <Select.Trigger\n chevron={<FaChevronDown className=\"h-3.5 w-3.5\" />}\n aria-label=\"Choose split action\"\n />\n <Select.Content>\n <Select.List>\n {splitActions.map((item) => (\n <Select.Item key={item.value} value={item.value} textValue={item.label}>\n {item.label}\n </Select.Item>\n ))}\n </Select.List>\n </Select.Content>\n </Group.Select>\n </Group>\n </Flex>\n )\n}"
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
"title": "Button Group",
|
|
231
|
-
"description": "Joined view switcher using the Group compound component with active state.",
|
|
232
|
-
"code": "\"use client\";\n\nimport React, { useState } from 'react'\nimport { Button, Divider, Group } from 'ui-lab-components'\nimport { FaGrip, FaList, FaTable } from 'react-icons/fa6'\n\nexport default function Example() {\n const [viewMode, setViewMode] = useState(\"list\");\n\n return (\n <Group orientation=\"horizontal\" spacing=\"xs\">\n <Group.Button active={viewMode === \"list\"} onPress={() => setViewMode(\"list\")}>\n <FaList className=\"mr-1.5 text-foreground-400\" /> List\n </Group.Button>\n <Divider orientation=\"vertical\" />\n <Group.Button active={viewMode === \"grid\"} onPress={() => setViewMode(\"grid\")}>\n <FaGrip className=\"mr-1.5 text-foreground-400\" /> Grid\n </Group.Button>\n <Divider orientation=\"vertical\" />\n <Group.Button active={viewMode === \"table\"} onPress={() => setViewMode(\"table\")}>\n <FaTable className=\"mr-1.5 text-foreground-400\" /> Table\n </Group.Button>\n </Group>\n )\n}"
|
|
233
|
-
}
|
|
234
|
-
]
|
|
193
|
+
"examples": []
|
|
235
194
|
},
|
|
236
195
|
"card": {
|
|
237
196
|
"props": [
|
|
@@ -1794,11 +1753,6 @@ export const generatedAPI = {
|
|
|
1794
1753
|
}
|
|
1795
1754
|
],
|
|
1796
1755
|
"examples": [
|
|
1797
|
-
{
|
|
1798
|
-
"title": "Basic Grid",
|
|
1799
|
-
"description": "A simple grid layout with multiple cells. Use this for organizing content in a responsive grid structure.",
|
|
1800
|
-
"code": "import React from 'react';\nimport { Grid } from 'ui-lab-components';\n\nexport default function Example() {\n return (\n <Grid columns={3} gap=\"md\">\n <div style={{ padding: '1rem', background: '#e0e0e0' }}>Cell 1</div>\n <div style={{ padding: '1rem', background: '#d0d0d0' }}>Cell 2</div>\n <div style={{ padding: '1rem', background: '#c0c0c0' }}>Cell 3</div>\n <div style={{ padding: '1rem', background: '#b0b0b0' }}>Cell 4</div>\n <div style={{ padding: '1rem', background: '#a0a0a0' }}>Cell 5</div>\n <div style={{ padding: '1rem', background: '#909090' }}>Cell 6</div>\n </Grid>\n );\n}"
|
|
1801
|
-
},
|
|
1802
1756
|
{
|
|
1803
1757
|
"title": "Track Placement",
|
|
1804
1758
|
"description": "Adjust columns, gap, alignment, and auto-placement flow to explore the CSS Grid track model.",
|
|
@@ -1873,48 +1827,7 @@ export const generatedAPI = {
|
|
|
1873
1827
|
"description": "Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those."
|
|
1874
1828
|
}
|
|
1875
1829
|
],
|
|
1876
|
-
"examples": [
|
|
1877
|
-
{
|
|
1878
|
-
"title": "Basic Group",
|
|
1879
|
-
"description": "A simple group container that arranges multiple elements together. Use this to organize related UI elements in a consistent layout.",
|
|
1880
|
-
"code": "import { Group } from 'ui-lab-components';\n\nexport default function Example() {\n return (\n <Group>\n <Group.Button>First</Group.Button>\n <Group.Button>Second</Group.Button>\n <Group.Button>Third</Group.Button>\n </Group>\n );\n}"
|
|
1881
|
-
},
|
|
1882
|
-
{
|
|
1883
|
-
"title": "Create Project",
|
|
1884
|
-
"description": "A primary grouped action for creating a named item.",
|
|
1885
|
-
"code": "import { Divider, Group } from \"ui-lab-components\";\nimport { FaPlus } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Group variant=\"primary\" orientation=\"horizontal\" spacing=\"xs\">\n <Group.Input aria-label=\"Project name\" placeholder=\"Untitled project\" className=\"w-56\" />\n <Divider orientation=\"vertical\" />\n <Group.Button>\n <FaPlus className=\"mr-1.5\" /> Create\n </Group.Button>\n </Group>\n );\n}"
|
|
1886
|
-
},
|
|
1887
|
-
{
|
|
1888
|
-
"title": "Filter Bar with Selects",
|
|
1889
|
-
"description": "Horizontal group combining Select dropdowns with action buttons for filtering interfaces.",
|
|
1890
|
-
"code": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Divider, Group, Select } from \"ui-lab-components\";\nimport { FaMagnifyingGlass, FaFilter } from \"react-icons/fa6\";\n\nexport default function Example() {\n const [status, setStatus] = useState<string | number | null>(\"active\");\n\n return (\n <Group variant=\"default\" orientation=\"horizontal\">\n <Group.Input icon={<FaMagnifyingGlass />} placeholder=\"Search...\">\n </Group.Input>\n <Divider />\n <Group.Select selectedKey={status} onSelectionChange={setStatus} className=\"w-36\">\n <Select.Trigger><Select.Value placeholder=\"Status\" /></Select.Trigger>\n <Select.Content>\n <Select.List>\n <Select.Item value=\"active\" textValue=\"Active\">Active</Select.Item>\n <Select.Item value=\"inactive\" textValue=\"Inactive\">Inactive</Select.Item>\n <Select.Item value=\"pending\" textValue=\"Pending\">Pending</Select.Item>\n </Select.List>\n </Select.Content>\n </Group.Select>\n <Divider />\n <Group.Button size=\"md\"><FaFilter className=\"mr-1.5\" /> Apply</Group.Button>\n </Group>\n );\n}"
|
|
1891
|
-
},
|
|
1892
|
-
{
|
|
1893
|
-
"title": "Documentation Search",
|
|
1894
|
-
"description": "A search input with an icon prefix and joined submit button.",
|
|
1895
|
-
"code": "import { Divider, Group } from \"ui-lab-components\";\nimport { FaMagnifyingGlass } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Group variant=\"secondary\">\n <div className=\"bg-background-800 flex items-center px-3 text-foreground-400\">\n <FaMagnifyingGlass />\n </div>\n <Divider />\n <Group.Input placeholder=\"Search documentation...\" className=\"w-64\" />\n <Divider />\n <Group.Button className=\"w-full\">Search</Group.Button>\n </Group>\n );\n}"
|
|
1896
|
-
},
|
|
1897
|
-
{
|
|
1898
|
-
"title": "Email Signup",
|
|
1899
|
-
"description": "An email input with a joined subscription action.",
|
|
1900
|
-
"code": "import { Divider, Group } from \"ui-lab-components\";\nimport { FaEnvelope } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Group variant=\"outline\">\n <div className=\"bg-background-800 flex items-center px-3 text-foreground-400\">\n <FaEnvelope />\n </div>\n <Divider />\n <Group.Input placeholder=\"you@example.com\" type=\"email\" className=\"w-64\" />\n <Divider />\n <Group.Button>Subscribe</Group.Button>\n </Group>\n );\n}"
|
|
1901
|
-
},
|
|
1902
|
-
{
|
|
1903
|
-
"title": "Copy Command",
|
|
1904
|
-
"description": "A read-only command field with a joined copy action.",
|
|
1905
|
-
"code": "import { Divider, Group } from \"ui-lab-components\";\nimport { FaCopy } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Group>\n <Group.Input defaultValue=\"npm install ui-lab\" readOnly className=\"w-full font-mono text-sm\" />\n <Divider />\n <Group.Button icon={{ left: <FaCopy className=\"mr-1.5 text-foreground-400\" /> }} />\n </Group>\n );\n}"
|
|
1906
|
-
},
|
|
1907
|
-
{
|
|
1908
|
-
"title": "Delete Confirmation",
|
|
1909
|
-
"description": "A danger variant group for destructive confirmation flows.",
|
|
1910
|
-
"code": "import { Divider, Group } from \"ui-lab-components\";\nimport { FaTrash } from \"react-icons/fa6\";\n\nexport default function Example() {\n return (\n <Group variant=\"danger\">\n <Group.Input aria-label=\"Confirmation\" placeholder=\"Type DELETE\" className=\"w-48\" />\n <Divider />\n <Group.Button>\n <FaTrash className=\"mr-1.5\" /> Delete\n </Group.Button>\n </Group>\n );\n}"
|
|
1911
|
-
},
|
|
1912
|
-
{
|
|
1913
|
-
"title": "Slider with Input Group",
|
|
1914
|
-
"description": "Numeric input synced with a slider for precise value selection.",
|
|
1915
|
-
"code": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Group, Slider } from \"ui-lab-components\";\nimport { FaPercent } from \"react-icons/fa6\";\n\nexport default function Example() {\n const [sliderValue, setSliderValue] = useState<number[]>([45]);\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const val = parseInt(e.target.value);\n if (!isNaN(val)) setSliderValue([Math.min(Math.max(val, 0), 100)]);\n };\n\n return (\n <div className=\"space-y-4 w-64\">\n <Group>\n <Group.Input type=\"number\" min={0} max={100} value={sliderValue[0]} onChange={handleInputChange} className=\"w-full\" />\n <div className=\"bg-background-800 flex items-center px-3 text-foreground-400 text-sm font-medium\">\n <FaPercent />\n </div>\n </Group>\n <Slider.Root value={sliderValue} onValueChange={setSliderValue} max={100} step={1} />\n </div>\n );\n}"
|
|
1916
|
-
}
|
|
1917
|
-
]
|
|
1830
|
+
"examples": []
|
|
1918
1831
|
},
|
|
1919
1832
|
"input": {
|
|
1920
1833
|
"props": [
|
|
@@ -4671,7 +4584,7 @@ export const generatedAPI = {
|
|
|
4671
4584
|
"type": "boolean",
|
|
4672
4585
|
"required": false,
|
|
4673
4586
|
"defaultValue": "true",
|
|
4674
|
-
"description": "Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis."
|
|
4587
|
+
"description": "Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis. Defaults to vertical resizing."
|
|
4675
4588
|
},
|
|
4676
4589
|
{
|
|
4677
4590
|
"name": "showCharacterCount",
|
|
@@ -4726,7 +4639,7 @@ export const generatedAPI = {
|
|
|
4726
4639
|
"type": "boolean",
|
|
4727
4640
|
"required": false,
|
|
4728
4641
|
"defaultValue": "true",
|
|
4729
|
-
"description": "Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis."
|
|
4642
|
+
"description": "Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis. Defaults to vertical resizing."
|
|
4730
4643
|
},
|
|
4731
4644
|
{
|
|
4732
4645
|
"name": "showCharacterCount",
|
|
@@ -4931,55 +4844,55 @@ export const generatedAPI = {
|
|
|
4931
4844
|
}
|
|
4932
4845
|
};
|
|
4933
4846
|
export const generatedStyles = {
|
|
4934
|
-
"anchor": "@reference \"tailwindcss\";\n\n@layer components {\n .preview, .anchor {\n display: inline\n }\n\n .root {\n @apply inline-block relative cursor-pointer;\n display: inline-block;\n color: var(--foreground, currentColor);\n text-decoration: none;\n\n
|
|
4935
|
-
"badge": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--
|
|
4847
|
+
"anchor": "@reference \"tailwindcss\";\n\n@layer components {\n .preview, .anchor {\n display: inline\n }\n\n .root {\n @apply inline-block relative cursor-pointer;\n display: inline-block;\n color: var(--foreground, currentColor);\n text-decoration: none;\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) .underline {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible, var(--focus-ring));\n outline-offset: 2px;\n border-radius: 2px;\n }\n }\n\n .underline {\n @apply absolute left-0 right-0 bottom-0 h-px;\n background-color: var(--underline-background, var(--background-600));\n transform-origin: right;\n transform: scaleX(1);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n pointer-events: none;\n }\n\n .preview {\n }\n}\n",
|
|
4848
|
+
"badge": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
|
|
4936
4849
|
"banner": "@reference \"tailwindcss\";\n\n@layer components {\n .banner {\n @apply flex w-full items-start gap-3 px-4 py-3;\n font-family: inherit;\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--leading-normal, 1.5);\n background-color: var(--background, var(--background-900));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--border, var(--background-700));\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .banner:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--background));\n border-color: var(--border-hover, var(--border));\n }\n\n .banner[data-pressed=\"true\"] {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n border-color: var(--border-pressed, var(--border-hover, var(--border)));\n }\n\n .content {\n @apply min-w-0 flex flex-col gap-1;\n }\n\n .iconContainer {\n @apply flex shrink-0 items-start justify-center pt-0.5;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--icon-color, currentColor);\n }\n\n .dismiss {\n @apply flex h-8 w-8 shrink-0 items-center justify-center p-0 cursor-pointer;\n background-color: transparent;\n color: currentColor;\n border: none;\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--dismiss-hover-background, transparent);\n }\n\n &[data-pressed=\"true\"] {\n background-color: var(--dismiss-pressed-background, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n }\n\n .title {\n font-weight: var(--font-weight-semibold, 600);\n font-size: inherit;\n line-height: var(--leading-tight, 1.25);\n @apply my-0;\n }\n\n .body {\n font-weight: var(--font-weight-medium, 500);\n font-size: inherit;\n line-height: var(--leading-normal, 1.5);\n @apply my-0;\n }\n}\n",
|
|
4937
|
-
"button": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n
|
|
4850
|
+
"button": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &:focus-visible {\n outline: none;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n filter: grayscale(0.5);\n }\n }\n}\n",
|
|
4938
4851
|
"card": "@reference \"tailwindcss\";\n\n@layer components {\n .card {\n @apply overflow-hidden;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, inherit);\n border: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .header {\n @apply p-4;\n color: var(--foreground, inherit);\n border-bottom: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n }\n\n .body {\n @apply px-4 py-2;\n color: var(--foreground, inherit);\n }\n\n .footer {\n @apply px-2 py-2;\n color: var(--foreground, inherit);\n background-color: var(--background, var(--background-800));\n border-top: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n }\n}\n",
|
|
4939
|
-
"checkbox": "@reference \"tailwindcss\";\n\n@layer components {\n .checkbox
|
|
4852
|
+
"checkbox": "@reference \"tailwindcss\";\n\n@layer components {\n .checkbox {\n @apply inline-grid gap-x-3;\n grid-template-columns: auto 1fr;\n grid-template-rows: auto auto;\n }\n\n .container {\n @apply relative inline-flex items-center justify-center;\n }\n\n .box {\n @apply relative h-5 w-5 cursor-pointer appearance-none;\n\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-xs, 0.25rem);\n outline: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:hover:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-invalid=\"true\"] {\n border-color: var(--background-error-border, var(--danger-600));\n }\n\n &[data-invalid=\"true\"][data-selected=\"true\"],\n &[data-invalid=\"true\"][data-indeterminate=\"true\"] {\n border-color: var(--background-border);\n }\n\n &[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n }\n\n .checkmark,\n .indeterminate {\n @apply absolute;\n inset: 50%;\n width: 65%;\n height: 65%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n animation: checkbox-icon-pop 200ms var(--ease-snappy-pop, ease-out);\n color: var(--foreground);\n pointer-events: none;\n }\n\n @keyframes checkbox-icon-pop {\n from {\n transform: translate(-50%, -50%) scale(0);\n }\n\n to {\n transform: translate(-50%, -50%) scale(1);\n }\n }\n\n .label {\n @apply cursor-pointer select-none;\n transition: color 200ms var(--ease-snappy-pop);\n\n &[data-disabled=\"true\"] {\n @apply opacity-60 cursor-not-allowed;\n }\n }\n\n .label-md {\n font-size: var(--text-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n }\n\n .helper-text {\n @apply text-xs;\n grid-column: 2;\n transition: color 200ms var(--ease-snappy-pop);\n color: var(--helper-foreground);\n\n &[data-error=\"true\"] {\n color: var(--helper-error-foreground, var(--foreground-error, var(--danger-600)));\n }\n }\n}\n",
|
|
4940
4853
|
"code": "@reference \"tailwindcss\";\n\n@layer components {\n .code {\n --border-color: var(--background-700);\n --header-bg: mix(var(--background-900) 90%, transparent);\n --scroll-track-bg: mix(var(--background-950) 50%, transparent);\n\n max-height: 52.5rem;\n border-radius: var(--radius-sm);\n border: 1px solid var(--border-color);\n @apply flex w-full min-w-0 flex-col overflow-hidden;\n }\n\n .header {\n flex: none;\n background-color: var(--header-bg);\n @apply flex items-center justify-between px-3 py-1.5;\n font-size: var(--text-sm);\n font-weight: var(--font-weight-semibold);\n border-bottom: 1px solid var(--border-color);\n color: var(--foreground-400);\n }\n\n\n .body {\n @apply relative flex min-h-0 flex-1 flex-col;\n flex: 1;\n }\n\n .viewport { @apply overflow-hidden; }\n\n .viewport :global(pre) {\n background: transparent;\n @apply m-0 p-0;\n width: fit-content;\n }\n\n .viewport :global(code) {\n color: var(--foreground-300);\n white-space: pre;\n }\n\n .viewport::-webkit-scrollbar {\n width: 0.5rem;\n }\n\n .viewport::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .viewport::-webkit-scrollbar-thumb {\n background-color: var(--background-700);\n border-radius: 9999px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .viewport::-webkit-scrollbar-thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-600);\n }\n\n .scroll-track {\n flex: none;\n @apply w-full;\n overflow-x: auto;\n background-color: var(--scroll-track-bg);\n backdrop-filter: blur(4px);\n }\n\n .expand-button {\n @apply flex w-full items-center gap-3 px-4 py-2 cursor-pointer;\n color: var(--foreground-300);\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n border-top: 1px solid var(--border-color);\n background: transparent;\n border-left: none;\n border-right: none;\n border-bottom: none;\n font-family: inherit;\n }\n\n .expand-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-800);\n }\n\n .expand-icon { @apply shrink-0; color: var(--foreground-400); }\n\n .copy-button {\n @apply absolute right-2 top-2 flex items-center justify-center p-1 cursor-pointer;\n border-radius: var(--radius-sm);\n color: var(--foreground-400);\n opacity: 0;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background: transparent;\n border: none;\n z-index: 1;\n }\n\n .copy-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-800);\n color: var(--foreground-300);\n }\n\n .copy-button:focus,\n .body:hover .copy-button {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n opacity: 1;\n }\n}\n",
|
|
4941
4854
|
"color": "@reference \"tailwindcss\";\n\n@layer components {\n .color {\n --background: color-mix(in srgb, var(--background-800) 30%, transparent);\n --background-border: var(--background-700);\n --focus-visible: var(--accent-500);\n\n display: flex;\n flex-direction: column;\n gap: 1rem;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n width: 260px;\n }\n\n .color[data-disabled=\"true\"] {\n opacity: 0.5;\n pointer-events: none;\n }\n\n .color[data-variant=\"popover\"] {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n .color-provider {\n display: inline-flex;\n width: fit-content;\n }\n\n .color-provider .color-trigger {\n --trigger-background: color-mix(in srgb, var(--background-800) 35%, transparent);\n --trigger-background-hover: color-mix(in srgb, var(--background-700) 45%, transparent);\n --trigger-border: var(--background-700);\n --trigger-text: var(--foreground-200);\n --background-border: var(--background-700);\n --focus-visible: var(--accent-500);\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n display: inline-flex;\n align-items: center;\n gap: 0.625rem;\n min-width: 170px;\n height: 40px;\n padding: 0 0.75rem;\n border: var(--border-width-base, 1px) solid var(--trigger-border);\n border-radius: var(--radius-sm, 0.375rem);\n background: var(--trigger-background);\n color: var(--trigger-text);\n cursor: pointer;\n font: inherit;\n font-size: 0.875rem;\n line-height: 1;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .color-provider .color-trigger:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background: var(--trigger-background-hover);\n }\n\n .color-provider .color-trigger:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .color-provider .color-trigger[data-disabled=\"true\"] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .color-provider .color-trigger[data-size=\"sm\"] {\n min-width: 150px;\n height: 34px;\n padding: 0 0.625rem;\n font-size: 0.8125rem;\n }\n\n .color-provider .color-trigger[data-size=\"lg\"] {\n min-width: 190px;\n height: 46px;\n padding: 0 0.875rem;\n font-size: 0.9375rem;\n }\n\n .color-provider .color-trigger-swatch {\n position: relative;\n width: 20px;\n height: 20px;\n flex: 0 0 auto;\n border-radius: var(--radius-xs, 0.25rem);\n border: var(--border-width-base, 1px) solid var(--background-border);\n overflow: hidden;\n }\n\n .color-provider .color-trigger-swatch::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 4px,\n var(--checkerboard-light) 4px,\n var(--checkerboard-light) 8px\n );\n }\n\n .color-provider .color-trigger-swatch::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-color: var(--preview-color, transparent);\n }\n\n .color-provider .color-trigger-value {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .color .controls {\n @apply pb-3 px-3 space-y-3;\n }\n\n .input-group {\n width: 100%;\n }\n\n .input-group > div:first-child {\n flex: 1;\n min-width: 0;\n }\n\n .input-group .input {\n width: 100%;\n }\n\n .input-group .format {\n flex-shrink: 0;\n width: 85px;\n }\n\n .color[data-size=\"sm\"] .format {\n width: 75px;\n }\n\n .canvas {\n position: relative;\n width: 96%;\n @apply mx-auto mt-2;\n cursor: crosshair;\n touch-action: none;\n display: flex;\n flex-direction: column;\n min-height: 160px;\n }\n\n .canvas[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .canvas .canvas-inner {\n position: relative;\n width: 100%;\n flex: 1;\n overflow: hidden;\n }\n\n .canvas .canvas-gradient-hue {\n position: absolute;\n inset: 0;\n overflow: hidden;\n }\n\n .canvas .canvas-gradient-saturation {\n position: absolute;\n inset: 0;\n background: linear-gradient(to right, rgb(255, 255, 255), transparent);\n }\n\n .canvas .canvas-gradient-brightness {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgb(0, 0, 0), transparent);\n }\n\n .canvas .canvas-pointer {\n --pointer-border: color-mix(in srgb, var(--foreground-200) 50%, transparent);\n\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: var(--radius-full);\n border: 2px solid var(--pointer-border);\n box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3), 0 2px 4px rgb(0 0 0 / 0.3);\n pointer-events: none;\n transform: translate(-50%, -50%);\n z-index: 10;\n }\n\n .hue-slider {\n --slider-track-size: 16px;\n --slider-thumb-size: 12px;\n --slider-hit-size: 16px;\n --slider-track-radius: var(--radius-full);\n --slider-track-border: var(--border-width-base, 1px) solid var(--background-border);\n --slider-track-background: linear-gradient(\n to right,\n hsl(0, 100%, 50%),\n hsl(60, 100%, 50%),\n hsl(120, 100%, 50%),\n hsl(180, 100%, 50%),\n hsl(240, 100%, 50%),\n hsl(300, 100%, 50%),\n hsl(360, 100%, 50%)\n );\n --slider-range-display: none;\n --slider-thumb-scale-active: 1;\n\n width: 100%;\n min-height: 16px;\n border-radius: var(--radius-full);\n }\n\n .hue-slider .hue-track {\n position: relative;\n width: 100%;\n }\n\n .hue-slider .hue-thumb {\n --thumb-border: white;\n --thumb-background: white;\n --slider-thumb-background: var(--thumb-background);\n --slider-thumb-border: 2px solid var(--thumb-border);\n --slider-thumb-shadow: 0 2px 4px rgb(0 0 0 / 0.3);\n --slider-thumb-shadow-hover: 0 2px 6px rgb(0 0 0 / 0.4);\n --slider-thumb-shadow-active: 0 1px 3px rgb(0 0 0 / 0.3);\n\n border-radius: var(--radius-full);\n }\n\n .hue-slider .hue-thumb[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .hue-slider .hue-thumb[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n box-shadow: var(--slider-thumb-shadow-hover);\n }\n\n .hue-slider .hue-thumb[data-pressed=\"true\"] {\n box-shadow: var(--slider-thumb-shadow-active);\n }\n\n .opacity-slider {\n --slider-track-size: 12px;\n --slider-thumb-size: 10px;\n --slider-hit-size: 12px;\n --slider-track-radius: var(--radius-full);\n --slider-track-border: var(--border-width-base, 1px) solid var(--background-border);\n --slider-range-display: none;\n --slider-thumb-scale-active: 1;\n --checkerboard-dark: var(--background-800);\n --checkerboard-light: var(--background-700);\n --slider-track-background:\n linear-gradient(to right, transparent, var(--color-slider-opacity-color, rgb(0, 0, 0))),\n repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 10px,\n var(--checkerboard-light) 10px,\n var(--checkerboard-light) 20px\n );\n\n width: 100%;\n min-height: 12px;\n border-radius: var(--radius-full);\n }\n\n .opacity-slider .opacity-track {\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n .opacity-slider .opacity-thumb {\n --thumb-border: white;\n --thumb-background: white;\n --slider-thumb-background: var(--thumb-background);\n --slider-thumb-border: 2px solid var(--thumb-border);\n --slider-thumb-shadow: 0 2px 4px rgb(0 0 0 / 0.3);\n --slider-thumb-shadow-hover: 0 2px 6px rgb(0 0 0 / 0.4);\n --slider-thumb-shadow-active: 0 1px 3px rgb(0 0 0 / 0.3);\n\n border-radius: var(--radius-full);\n }\n\n .opacity-slider .opacity-thumb[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .opacity-slider .opacity-thumb[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n box-shadow: var(--slider-thumb-shadow-hover);\n }\n\n .opacity-slider .opacity-thumb[data-pressed=\"true\"] {\n box-shadow: var(--slider-thumb-shadow-active);\n }\n\n .recent-colors {\n display: flex;\n gap: 0.5rem;\n overflow-x: auto;\n padding-bottom: 0.25rem;\n }\n\n .recent-colors .recent-color-swatch {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n cursor: pointer;\n background: none;\n padding: 0;\n outline: none;\n transition:\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .recent-colors .recent-color-swatch:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n transform: scale(1.1);\n box-shadow: 0 0 0 2px var(--focus-visible);\n }\n\n .recent-colors .recent-color-swatch:active {\n transform: scale(0.95);\n }\n\n .recent-colors .recent-color-swatch:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .preview-swatch {\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n position: relative;\n width: 36px;\n height: 36px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .preview-swatch::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 6px,\n var(--checkerboard-light) 6px,\n var(--checkerboard-light) 12px\n );\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 1;\n }\n\n .preview-swatch::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-color: var(--preview-color, transparent);\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 2;\n }\n\n .preview {\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n position: relative;\n width: 64px;\n height: 64px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n box-shadow: 0 2px 8px rgb(0 0 0 / 0.2);\n overflow: hidden;\n }\n\n .preview::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 10px,\n var(--checkerboard-light) 10px,\n var(--checkerboard-light) 20px\n );\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 1;\n }\n}\n",
|
|
4942
|
-
"command": "@reference \"tailwindcss\";\n\n@layer components {\n /* Overlay Container */\n .overlay {\n @apply fixed inset-0 flex items-start justify-center overflow-hidden;\n z-index: 999;\n padding-top: 20vh;\n /* Apply backdrop styles directly to avoid creating a containing block that disrupts sticky elements */\n background-color: var(--overlay);\n backdrop-filter: var(--overlay-backdrop);\n }\n\n /* Content */\n .content {\n @apply relative m-2 w-full max-w-[28rem];\n border-radius: var(--radius-sm);\n background: var(--background);\n margin-inline: 1rem;\n box-shadow: var(--shadow);\n animation: fade-in-zoom-in 0.2s ease-out;\n }\n\n .inner {\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n border-top: var(--border-width-base) solid var(--border);\n @apply overflow-hidden;\n }\n\n /* Search Section */\n .search {\n @apply border-none flex p-1.5;\n --input-active-border-color: transparent;\n --input-active-box-shadow: none;\n }\n\n .input {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n\n &[data-active],\n &[data-focus-visible] {\n border-color: transparent;\n box-shadow: none;\n }\n }\n\n /* List Section */\n .list {\n @apply py-0.5 px-2 space-y-2;\n background-color: var(--background-list);\n }\n\n .list :global([role=\"listbox\"]) {\n @apply flex w-full flex-col;\n }\n\n .item {\n @apply flex items-center justify-between rounded-sm px-2 py-0.5 cursor-pointer;\n border-radius: 0.375rem;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n color: var(--foreground);\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n
|
|
4855
|
+
"command": "@reference \"tailwindcss\";\n\n@layer components {\n /* Overlay Container */\n .overlay {\n @apply fixed inset-0 flex items-start justify-center overflow-hidden;\n z-index: 999;\n padding-top: 20vh;\n /* Apply backdrop styles directly to avoid creating a containing block that disrupts sticky elements */\n background-color: var(--overlay);\n backdrop-filter: var(--overlay-backdrop);\n }\n\n /* Content */\n .content {\n @apply relative m-2 w-full max-w-[28rem];\n border-radius: var(--radius-sm);\n background: var(--background);\n margin-inline: 1rem;\n box-shadow: var(--shadow);\n animation: fade-in-zoom-in 0.2s ease-out;\n }\n\n .inner {\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n border-top: var(--border-width-base) solid var(--border);\n @apply overflow-hidden;\n }\n\n /* Search Section */\n .search {\n @apply border-none flex p-1.5;\n --input-active-border-color: transparent;\n --input-active-box-shadow: none;\n }\n\n .input {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n\n &[data-active],\n &[data-focus-visible] {\n border-color: transparent;\n box-shadow: none;\n }\n }\n\n /* List Section */\n .list {\n @apply py-0.5 px-2 space-y-2;\n background-color: var(--background-list);\n }\n\n .list :global([role=\"listbox\"]) {\n @apply flex w-full flex-col;\n }\n\n .item {\n @apply flex items-center justify-between rounded-sm px-2 py-0.5 cursor-pointer;\n border-radius: 0.375rem;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item-content {\n @apply flex min-w-0 flex-1 items-center gap-2.5;\n flex: 1;\n }\n\n .item-icon {\n @apply flex h-6 w-6 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .item-labels {\n flex: 1;\n @apply min-w-0;\n }\n\n .item-label {\n font-size: var(--text-sm);\n color: var(--foreground);\n font-weight: var(--font-weight-medium);\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n color: var(--foreground-muted);\n font-size: 0.875rem;\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .hint-wrapper {\n @apply flex items-center;\n }\n\n .category-header {\n @apply px-2 py-1.5 mt-2 first:mt-0;\n font-size: var(--text-sm);\n font-weight: var(--font-weight-semibold);\n color: var(--foreground-muted);\n }\n\n /* Empty State */\n .empty {\n padding: 1.5rem 1rem;\n text-align: center;\n font-size: 0.875rem;\n color: var(--foreground-muted);\n }\n\n /* Footer */\n .footer {\n @apply flex w-full items-center gap-2 px-1.5 py-2;\n background-color: var(--background-footer);\n border-top: 1px solid var(--border);\n justify-content: flex-between;\n }\n\n /* Animations */\n @keyframes fade-in-zoom-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }\n}\n",
|
|
4943
4856
|
"confirm": "@reference \"tailwindcss\";\n\n@layer components {\n .confirm {\n --overlay-background: mix(var(--background-950) 50%, transparent);\n --header-foreground: var(--foreground-100);\n --description-foreground: var(--foreground-300);\n --error-foreground: var(--foreground-danger);\n --countdown-foreground: var(--foreground-400);\n --label-foreground: var(--foreground-300);\n --input-background: var(--background-800);\n --input-border-color: var(--background-700);\n --input-foreground: var(--foreground-100);\n --input-focus-visible: var(--accent-500);\n }\n\n .container {\n @apply flex flex-col;\n }\n\n .card {\n @apply max-w-[28rem];\n }\n\n .body {\n @apply flex flex-col gap-4;\n }\n\n .body-compact {\n @apply gap-3;\n }\n\n .dialog-overlay {\n @apply fixed inset-0 z-50 flex items-center justify-center;\n background-color: var(--overlay-background);\n }\n\n .dialog-card {\n @apply max-w-[28rem];\n margin: 0 1rem;\n }\n\n .header {\n @apply flex items-start gap-3;\n }\n\n .header-content {\n @apply flex-1;\n }\n\n .header-title {\n @apply font-semibold;\n color: var(--header-foreground);\n }\n\n .description {\n font-size: var(--text-sm);\n color: var(--description-foreground);\n }\n\n .error-message {\n font-size: var(--text-sm);\n color: var(--error-foreground);\n }\n\n .warning-box {\n @apply p-3 rounded-sm;\n border: var(--border-width-base, 1px) solid var(--warning-border-color);\n background-color: var(--warning-background);\n color: var(--warning-foreground);\n font-size: var(--text-sm);\n }\n\n .warning-box-low {\n --warning-background: var(--warning-background-low);\n --warning-border-color: var(--warning-border-color-low);\n --warning-foreground: var(--warning-foreground-low);\n }\n\n .warning-box-medium {\n --warning-background: var(--warning-background-medium);\n --warning-border-color: var(--warning-border-color-medium);\n --warning-foreground: var(--warning-foreground-medium);\n }\n\n .warning-box-high {\n --warning-background: var(--warning-background-high);\n --warning-border-color: var(--warning-border-color-high);\n --warning-foreground: var(--warning-foreground-high);\n }\n\n .warning-box-critical {\n --warning-background: var(--warning-background-critical);\n --warning-border-color: var(--warning-border-color-critical);\n --warning-foreground: var(--warning-foreground-critical);\n }\n\n .countdown-text {\n font-size: var(--text-sm);\n color: var(--countdown-foreground);\n }\n\n .input-label {\n font-size: var(--text-sm);\n margin-left: 0.25rem;\n color: var(--label-foreground);\n }\n\n .input {\n @apply w-full mt-2 px-3 py-2 rounded-sm transition-all duration-200;\n background-color: var(--input-background);\n border: var(--border-width-base, 1px) solid var(--input-border-color);\n color: var(--input-foreground);\n font-size: var(--text-sm);\n\n &:focus-visible {\n outline: 2px solid var(--input-focus-visible);\n outline-offset: 2px;\n }\n }\n\n .actions {\n @apply flex gap-2;\n }\n\n .actions-inline {\n @apply flex-row;\n }\n\n .actions-dialog {\n @apply flex-row justify-end;\n }\n}\n",
|
|
4944
|
-
"date": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-
|
|
4857
|
+
"date": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-xs);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-xs) var(--radius-xs) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-xs);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-xs);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-xs) var(--radius-xs);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-xs);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
|
|
4945
4858
|
"divider": "@reference \"tailwindcss\";\n\n@layer components {\n .divider {\n --divider-background: var(--group-divider-background, var(--background-border, var(--background)));\n }\n}\n",
|
|
4946
|
-
"expand": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n position: relative;\n display: block;\n width: 100%;\n }\n\n .expand {\n --expand-disabled-opacity: 0.6;\n --expand-trigger-padding-x: 0.75rem;\n --expand-trigger-padding-y: 0.5rem;\n
|
|
4859
|
+
"expand": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n position: relative;\n display: block;\n width: 100%;\n }\n\n .expand {\n --expand-disabled-opacity: 0.6;\n --expand-trigger-padding-x: 0.75rem;\n --expand-trigger-padding-y: 0.5rem;\n\n @apply flex w-full flex-col;\n }\n\n .expand[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .trigger {\n @apply flex w-full items-stretch justify-between border-0 p-0 text-left;\n\n appearance: none;\n color: var(--foreground);\n background-color: var(--background);\n cursor: pointer;\n border-radius: 0;\n font-size: var(--text-sm);\n line-height: var(--leading-snug);\n outline: none;\n box-shadow: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out));\n }\n\n .trigger:focus,\n .trigger:focus-visible {\n outline: none;\n box-shadow: none;\n }\n\n .trigger[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .title {\n @apply flex min-w-0 flex-1 items-center overflow-hidden;\n\n padding: var(--expand-trigger-padding-y) 0 var(--expand-trigger-padding-y)\n var(--expand-trigger-padding-x);\n font-weight: var(--font-weight-medium);\n border-radius: 0;\n color: inherit;\n background-color: transparent;\n }\n\n .icon {\n @apply flex shrink-0 items-center justify-center;\n\n padding: var(--expand-trigger-padding-y) var(--expand-trigger-padding-x);\n color: inherit;\n background-color: transparent;\n border-radius: 0;\n }\n\n @media (hover: hover) {\n .trigger:not([data-disabled=\"true\"]):hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .trigger:not([data-disabled=\"true\"]) .icon:hover {\n border-radius: 0;\n }\n }\n\n .icon > * {\n transition: transform 250ms var(--ease-smooth-settle);\n }\n\n .icon[data-selected=\"true\"] > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) {\n flex-direction: column-reverse;\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(0deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) {\n @apply flex-row-reverse items-start;\n }\n\n .expand:has(.content[data-from=\"left\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon > * {\n transform: rotate(-90deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) {\n @apply flex-row items-start;\n }\n\n .expand:has(.content[data-from=\"right\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(-90deg);\n }\n\n .content {\n display: grid;\n overflow: hidden;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms var(--ease-smooth-settle);\n }\n\n .content[data-selected=\"true\"] {\n grid-template-rows: 1fr;\n }\n\n .content[data-from=\"left\"],\n .content[data-from=\"right\"] {\n grid-template-rows: 1fr;\n grid-template-columns: 0fr;\n transition: grid-template-columns 300ms var(--ease-smooth-settle);\n }\n\n .content[data-from=\"left\"][data-selected=\"true\"],\n .content[data-from=\"right\"][data-selected=\"true\"] {\n grid-template-columns: 1fr;\n }\n\n .content-inner {\n @apply min-h-0 overflow-hidden;\n\n min-width: 0;\n color: var(--foreground);\n background-color: var(--background);\n }\n\n .divider {\n margin: 0;\n }\n}\n",
|
|
4947
4860
|
"flex": "@reference \"tailwindcss\";\n\n@layer components {\n .flex {\n --gap-scale: 0.5;\n\n @apply flex w-full;\n gap: calc(var(--spacing, 0.25rem) * var(--flex-gap-step, 4) * var(--gap-scale, 1));\n }\n\n /* Direction variants */\n .flex.row { flex-direction: row; }\n .flex.column { flex-direction: column; }\n\n /* Wrap variants */\n .flex.wrap { flex-wrap: wrap; }\n .flex.nowrap { flex-wrap: nowrap; }\n\n /* Justify-content variants */\n .flex.justify-start { justify-content: flex-start; }\n .flex.justify-end { justify-content: flex-end; }\n .flex.justify-center { justify-content: center; }\n .flex.justify-between { justify-content: space-between; }\n .flex.justify-around { justify-content: space-around; }\n .flex.justify-evenly { justify-content: space-evenly; }\n\n /* Align-items variants */\n .flex.align-start { align-items: flex-start; }\n .flex.align-end { align-items: flex-end; }\n .flex.align-center { align-items: center; }\n .flex.align-stretch { align-items: stretch; }\n .flex.align-baseline { align-items: baseline; }\n\n /* Container query parent - establishes containment context */\n .container-query-parent {\n container-type: inline-size;\n container-name: flex-parent;\n @apply w-full;\n }\n\n /* Container query responsive behavior - use .flex.container-responsive for specificity parity with base variants */\n @container flex-parent (width < 400px) {\n .flex.container-responsive {\n flex-direction: column;\n flex-wrap: wrap;\n justify-content: flex-start;\n --flex-gap-step: 2;\n }\n }\n\n @container flex-parent (400px <= width < 500px) {\n .flex.container-responsive {\n flex-wrap: wrap;\n --flex-gap-step: 2;\n }\n }\n\n @container flex-parent (500px <= width < 900px) {\n .flex.container-responsive {\n --flex-gap-step: 4;\n }\n }\n\n @container flex-parent (width >= 900px) {\n .flex.container-responsive {\n --flex-gap-step: 6;\n }\n }\n}\n",
|
|
4948
4861
|
"frame": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n --frame-radius: var(--radius-sm, 24px);\n --frame-stroke-width: var(--border-width-base, 1px);\n }\n\n .shape {\n rx: var(--frame-radius);\n }\n\n .stroke {\n stroke-width: var(--frame-stroke-width);\n vector-effect: non-scaling-stroke;\n }\n\n}\n",
|
|
4949
4862
|
"gallery": "@reference \"tailwindcss\";\n\n@layer components {\n .item-scope {\n @apply block min-w-0 h-full;\n }\n\n .item {\n --border-width: var(--border-width-base, 1px);\n --radius: var(--radius-sm, 0.375rem);\n --transition: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n --view-width: 200px;\n\n @apply flex flex-col overflow-hidden no-underline cursor-pointer w-full h-full;\n\n color: inherit;\n background: var(--background);\n border: var(--border-width) solid var(--background-border);\n border-radius: var(--radius);\n transition:\n border-color var(--transition),\n transform var(--transition),\n background-color var(--transition),\n box-shadow var(--transition);\n }\n\n .item:focus {\n outline: none;\n }\n\n .item[data-disabled=\"true\"] {\n @apply cursor-not-allowed;\n }\n\n .item[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n border-color: var(--background-hover-border);\n }\n\n .item[data-pressed=\"true\"] {\n border-color: var(--background-pressed-border, var(--background-hover-border));\n }\n\n .item[data-orientation=\"horizontal\"] {\n @apply flex-row;\n }\n\n .item[data-orientation=\"horizontal\"] .view {\n width: var(--view-width);\n }\n\n .view {\n --aspect-ratio: 16/9;\n --background: transparent;\n\n @apply relative overflow-hidden;\n\n aspect-ratio: var(--aspect-ratio);\n background: var(--background);\n }\n\n .view > img,\n .view > video {\n @apply w-full h-full object-cover;\n }\n\n .body {\n --gap: calc(var(--spacing, 0.25rem) * 1);\n --padding: calc(var(--spacing, 0.25rem) * 3);\n --title-color: var(--foreground);\n --description-color: var(--foreground-muted, var(--foreground));\n\n @apply flex flex-col self-start min-w-0;\n\n gap: var(--gap);\n padding: var(--padding);\n }\n\n .item[data-orientation=\"horizontal\"] .body {\n flex: 1;\n align-self: stretch;\n }\n\n .body > :first-child {\n color: var(--title-color);\n font-weight: var(--font-weight-medium, 500);\n }\n\n .body > :not(:first-child) {\n color: var(--description-color);\n font-size: var(--text-sm, 0.875rem);\n }\n}\n",
|
|
4950
4863
|
"grid": "@reference \"tailwindcss\";\n\n@layer components {\n .grid {\n --gap-scale: 1;\n\n --background: transparent;\n --foreground: inherit;\n\n @apply grid w-full;\n background-color: var(--background);\n color: var(--foreground);\n grid-template-columns: var(--grid-tpl, repeat(3, 1fr));\n grid-template-rows: var(--grid-rows, auto);\n gap: calc(var(--spacing, 0.25rem) * var(--grid-gap-step, 4) * var(--gap-scale, 1));\n row-gap: calc(var(--spacing, 0.25rem) * var(--grid-row-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n column-gap: calc(var(--spacing, 0.25rem) * var(--grid-col-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n justify-items: var(--grid-ji, stretch);\n align-items: var(--grid-ai, stretch);\n justify-content: var(--grid-jc, start);\n align-content: var(--grid-ac, start);\n grid-auto-flow: var(--grid-flow, row);\n }\n\n .container {\n container-type: inline-size;\n container-name: grid-ctx;\n @apply w-full;\n }\n\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-sm, 1fr);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-md, var(--grid-tpl-sm, 1fr));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-lg, var(--grid-tpl-md, var(--grid-tpl-sm, 1fr)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-xl, var(--grid-tpl-lg, var(--grid-tpl-md, var(--grid-tpl-sm, 1fr))));\n }\n }\n\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-sm, 2);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-md, var(--grid-gap-step-sm, 4));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-lg, var(--grid-gap-step-md, var(--grid-gap-step-sm, 4)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-xl, var(--grid-gap-step-lg, var(--grid-gap-step-md, var(--grid-gap-step-sm, 4))));\n }\n }\n\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-sm, auto);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-md, var(--grid-rows-sm, auto));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-lg, var(--grid-rows-md, var(--grid-rows-sm, auto)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-xl, var(--grid-rows-lg, var(--grid-rows-md, var(--grid-rows-sm, auto))));\n }\n }\n\n .grid.has-row-gap {\n row-gap: calc(var(--spacing, 0.25rem) * var(--grid-row-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n }\n\n .grid.has-col-gap {\n column-gap: calc(var(--spacing, 0.25rem) * var(--grid-col-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n }\n\n @container grid-ctx (width < 400px) {\n .container .grid {\n grid-template-columns: 1fr;\n --grid-gap-step: 2;\n }\n }\n}\n",
|
|
4951
|
-
"group": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --
|
|
4952
|
-
"input": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .
|
|
4864
|
+
"group": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item .button {\n @apply w-full;\n }\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
|
|
4865
|
+
"input": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .input {\n height: fit-content;\n flex: 1;\n min-width: 0;\n @apply py-1.5 px-3;\n font-family: inherit;\n font-size: var(--text-xs);\n line-height: var(--leading-snug);\n color: var(--foreground);\n background-color: transparent;\n border: none;\n outline: none;\n box-sizing: border-box;\n\n &::placeholder {\n color: var(--placeholder);\n }\n\n &[data-disabled] {\n color: var(--disabled-foreground);\n cursor: not-allowed;\n }\n\n /* Hide default browser spinners for number inputs */\n &[type=\"number\"] {\n\n &::-webkit-outer-spin-button,\n &::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n display: none;\n }\n\n /* Firefox */\n &[type=\"number\"] {\n -moz-appearance: textfield;\n }\n }\n }\n\n .icon-wrapper {\n @apply z-10 flex items-center;\n pointer-events: none;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n color: var(--foreground, currentColor);\n }\n\n .icon-left {\n @apply relative;\n }\n\n .icon-right {\n @apply relative;\n }\n\n .container {\n --adornment-offset: calc(var(--spacing, 0.25rem) * 1.5);\n\n display: flex;\n align-items: center;\n width: 100%;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-sizing: border-box;\n overflow: hidden;\n\n &[data-disabled] {\n background-color: var(--disabled-background);\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n &[data-variant=\"ghost\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n\n background-color: transparent;\n border-color: transparent;\n }\n }\n\n .start-adornments,\n .end-adornments {\n @apply flex items-center gap-1;\n align-self: stretch;\n flex-shrink: 0;\n pointer-events: none;\n }\n\n .start-adornments {\n @apply pl-2.5;\n }\n\n .end-adornments {\n padding-right: var(--adornment-offset);\n\n &:has(.controls) {\n padding-right: 0;\n }\n\n &:has([data-hint]) {\n padding-right: 0;\n }\n }\n\n .actions {\n @apply flex items-center gap-1;\n pointer-events: auto;\n }\n\n .action {\n @apply flex items-center justify-center p-2;\n border-radius: 0.25rem;\n color: var(--action-foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--action-background-hover);\n color: var(--action-foreground-hover);\n }\n\n .hint {\n @apply inline-flex items-center justify-center whitespace-nowrap;\n flex-shrink: 0;\n margin-inline-start: calc(var(--spacing, 0.25rem) * 0.5);\n margin-inline-end: var(--adornment-offset);\n font-size: var(--text-sm);\n line-height: 1;\n color: var(--foreground);\n background-color: var(--background);\n pointer-events: auto;\n }\n\n .controls {\n @apply flex w-7.5 flex-col;\n align-self: stretch;\n min-height: 100%;\n border-left: var(--border-width-base, 1px) solid var(--background-border);\n pointer-events: auto;\n }\n\n .controls[data-disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .stepper {\n @apply flex w-full flex-1 items-center justify-center p-0 cursor-pointer;\n flex: 1;\n background-color: transparent;\n border: none;\n color: var(--foreground);\n --active-background: var(--background-700);\n --active-color: var(--foreground-100);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &+.stepper {\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n &:hover:not(:disabled) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--hover-background);\n color: var(--hover-color);\n }\n\n &:active:not(:disabled) {\n background-color: var(--active-background);\n color: var(--active-color);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n }\n}\n",
|
|
4953
4866
|
"label": "@reference \"tailwindcss\";\n\n@layer components {\n .label {\n --background: transparent;\n --foreground: var(--foreground-primary);\n --foreground-disabled: var(--foreground-secondary);\n --foreground-error: var(--danger-600);\n }\n\n .label > label {\n display: block;\n font-family: inherit;\n font-size: var(--text-sm);\n color: var(--foreground);\n transition: color 150ms ease;\n\n &[data-size=\"sm\"] { font-size: var(--text-sm); }\n &[data-size=\"lg\"] { font-size: var(--text-md); }\n\n &[data-disabled] {\n color: var(--foreground-disabled);\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n &[data-error] {\n color: var(--foreground-error);\n }\n }\n\n .label > .required-indicator {\n margin-left: 0.25rem;\n color: var(--required-color);\n }\n\n .label > .helper-text {\n --helper-foreground: var(--foreground-secondary);\n --helper-foreground-error: var(--danger-600);\n\n display: block;\n font-size: var(--text-sm);\n margin-top: 0.25rem;\n transition: color 150ms ease;\n color: var(--helper-foreground);\n\n &[data-error] {\n color: var(--helper-foreground-error);\n }\n }\n}\n",
|
|
4954
|
-
"list": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--
|
|
4867
|
+
"list": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
|
|
4955
4868
|
"mask": "@reference \"tailwindcss\";\n\n@layer components {\n .mask {\n @apply relative h-full w-full;\n }\n}\n\n.mask[style*=\"mask-image\"],\n.mask[style*=\"-webkit-mask-image\"] {\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n}\n\n.mask[style*=\"--mask-clip-path\"] {\n clip-path: var(--mask-clip-path);\n}\n\n.mask-gradient {\n background: var(--mask-gradient);\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n color: transparent;\n}\n",
|
|
4956
|
-
"menu": "@reference \"tailwindcss\";\n\n@layer components {\n :global(.menu) {\n display: contents;\n\n .content,\n .sub-content {\n --content-padding: calc(var(--spacing) * 1.5);\n --content-radius: var(--radius-sm, 0.375rem);\n --content-inner-radius: calc(var(--content-radius) - var(--border-width-base, 1px));\n --
|
|
4957
|
-
"modal": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--
|
|
4869
|
+
"menu": "@reference \"tailwindcss\";\n\n@layer components {\n :global(.menu) {\n display: contents;\n\n .content,\n .sub-content {\n --content-padding: calc(var(--spacing) * 1.5);\n --content-radius: var(--radius-sm, 0.375rem);\n --content-inner-radius: calc(var(--content-radius) - var(--border-width-base, 1px));\n --open-animation: slide-in-from-top 0.15s var(--ease-snappy-pop);\n --closed-animation: slide-out-to-top 0.15s var(--ease-snappy-pop);\n --disabled-opacity: 0.5;\n\n @apply absolute min-w-40 max-w-80 overflow-hidden;\n z-index: 50000;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--content-radius);\n }\n\n .trigger {\n &[data-type=\"pop-over\"][data-pressed=\"true\"] {\n opacity: 1;\n background-color: var(--background-pressed);\n border-radius: var(--radius-sm, 0.375rem);\n }\n }\n\n .content[data-state=\"open\"],\n .sub-content[data-state=\"open\"] {\n animation: var(--open-animation);\n }\n\n .content[data-state=\"closed\"],\n .sub-content[data-state=\"closed\"] {\n animation: var(--closed-animation);\n }\n\n .list {\n @apply space-y-1;\n max-height: 24rem;\n overflow-y: auto;\n }\n\n .item {\n @apply flex min-w-0 items-center gap-2;\n padding: var(--item-padding, var(--content-padding));\n border-radius: var(--item-radius, var(--content-inner-radius));\n cursor: pointer;\n user-select: none;\n outline: none;\n color: var(--foreground);\n\n &[data-focused=\"true\"] {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n pointer-events: none;\n }\n }\n\n .item {\n &[data-inset=\"true\"] {\n padding-left: calc(var(--item-padding, var(--content-padding)) * 2.67);\n }\n }\n\n .item-indicator {\n @apply ml-auto flex h-4 w-4 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .sub-trigger[data-state=\"open\"]:not([data-focused=\"true\"]) {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n .sub-trigger-chevron {\n @apply ml-auto h-4 w-4 shrink-0;\n color: var(--chevron-foreground, currentColor);\n }\n\n .label {\n padding: var(--content-padding);\n color: var(--foreground-muted);\n\n &[data-inset=\"true\"] {\n padding-left: calc(var(--content-padding) * 2.67);\n }\n }\n\n .separator {\n @apply -mx-1 my-1 h-px;\n background-color: var(--background-border);\n }\n\n .shortcut {\n margin-left: auto;\n color: var(--foreground-muted);\n }\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-to-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n}\n",
|
|
4870
|
+
"modal": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--foreground);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-pressed=\"true\"] {\n transform: scale(0.92);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n border-radius: var(--radius-xs, 0.25rem);\n }\n }\n\n .close-icon {\n @apply h-5 w-5;\n }\n\n .content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n color: var(--foreground);\n }\n\n .content::-webkit-scrollbar {\n width: 6px;\n }\n\n .content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .content::-webkit-scrollbar-thumb {\n background-color: var(--background);\n border-radius: 3px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .content::-webkit-scrollbar-thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex shrink-0 items-center justify-between gap-4 px-6 py-4;\n background-color: var(--footer-background, var(--background));\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n /* Size variants */\n .panel[data-size=\"fit\"] {\n width: fit-content;\n }\n\n .panel[data-size=\"auto\"] {\n max-width: min(90vw, 28rem);\n }\n\n /* Media queries for smaller screens */\n @media (max-width: 640px) {\n .panel {\n margin: 1rem;\n }\n\n .content {\n max-height: calc(100vh - 10rem);\n }\n }\n}\n",
|
|
4958
4871
|
"page": "@reference \"tailwindcss\";\n\n@layer components {\n .page {\n --padding: var(--page-padding-md, 1rem);\n\n @apply flex flex-col w-full relative;\n }\n\n .page[data-centered=\"true\"] {\n @apply items-center;\n }\n\n .page[data-fullscreen=\"false\"] {\n margin-left: auto;\n margin-right: auto;\n }\n\n .padding-none { --padding: 0; padding: 0; }\n\n .padding-sm { --padding: var(--page-padding-sm, 0.5rem); padding: var(--padding); }\n\n .padding-md { --padding: var(--page-padding-md, 1rem); padding: var(--padding); }\n\n .padding-lg { --padding: var(--page-padding-lg, 1.5rem); padding: var(--padding); }\n\n .padding-xl { --padding: var(--page-padding-xl, 2rem); padding: var(--padding); }\n}\n",
|
|
4959
4872
|
"panel": "@reference \"tailwindcss\";\n\n@layer components {\n .panel {\n @apply flex h-full w-full min-h-0 min-w-0 flex-row;\n background: inherit;\n }\n\n .panel[data-stacked=\"true\"] { flex-direction: column; }\n\n .header,\n .footer {\n @apply shrink-0;\n background: inherit;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n z-index: 10;\n }\n\n .content {\n @apply flex min-h-0 min-w-0;\n flex: 1;\n overflow: auto;\n }\n\n .fixed {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 5;\n }\n\n /* Sidebar */\n .sidebar {\n @apply shrink-0 overflow-hidden;\n overflow: hidden;\n transition: width 0.2s ease;\n border-right: var(--border-width-base) solid var(--panel-border-color);\n }\n\n .sidebar[data-side=\"right\"] {\n border-right: none;\n border-left: var(--border-width-base) solid var(--panel-border-color);\n }\n\n /* Toggle */\n .toggle {\n @apply flex items-center;\n }\n\n /* Group */\n .group {\n @apply flex w-full h-full;\n background: inherit;\n }\n\n .group[data-direction=\"vertical\"] { flex-direction: column; }\n\n /* Resize handle */\n .resize {\n @apply relative shrink-0;\n cursor: col-resize;\n background: transparent;\n width: 10px;\n }\n\n .resize::before {\n content: '';\n position: absolute;\n top: 0;\n bottom: 0;\n left: 50%;\n width: 1px;\n background: var(--panel-divider-color, #374151);\n transform: translateX(-50%);\n transition:\n width var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n height var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .resize[data-direction=\"vertical\"] {\n cursor: row-resize;\n height: 10px;\n }\n\n .resize[data-direction=\"vertical\"]::before {\n top: 50%;\n bottom: auto;\n left: 0;\n right: 0;\n width: auto;\n height: 1px;\n transform: translateY(-50%);\n }\n\n .resize:hover::before,\n .resize[data-resizing=\"true\"]::before {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n width: 2px;\n }\n\n .resize[data-direction=\"vertical\"]:hover::before,\n .resize[data-direction=\"vertical\"][data-resizing=\"true\"]::before {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n width: auto;\n height: 2px;\n }\n\n /* Spacing variants */\n .spacingNone,\n .spacing-none { gap: 0; }\n\n .spacingSm,\n .spacing-sm { gap: var(--spacing-sm, 0.5rem); }\n\n .spacingMd,\n .spacing-md { gap: var(--spacing-md, 1rem); }\n\n .spacingLg,\n .spacing-lg { gap: var(--spacing-lg, 1.5rem); }\n\n /* Compact variant */\n .compact {\n gap: calc(var(--spacing-sm, 0.5rem) / 2);\n }\n\n /* Responsive stacking (mobile) */\n @media (max-width: 767px) {\n .stacked { flex-direction: column; }\n }\n}\n",
|
|
4960
|
-
"path": "@reference \"tailwindcss\";\n\n@layer components {\n .path {\n @apply block;\n }\n\n .list {\n @apply m-0 flex flex-wrap items-center gap-2 p-0;\n list-style: none;\n }\n\n .list[data-separator=\"custom\"] .item:not(:last-child)::after {\n content: none;\n }\n\n .item {\n @apply m-0 flex items-center gap-2 p-0;\n }\n\n .item:not(:last-child)::after {\n content: \"/\";\n margin-inline-start: 0.5rem;\n color: var(--
|
|
4961
|
-
"popover": "@reference \"tailwindcss\";\n\n@layer components {\n .trigger {\n @apply inline-block;\n }\n\n .root {\n @apply absolute;\n pointer-events: none;\n z-index: 50;\n }\n\n .content {\n --frame-fill: var(--background);\n --frame-stroke-color: var(--border);\n --frame-radius: 8px;\n opacity: 0;\n transform: scale(0.95);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n pointer-events: none;\n min-width: 200px;\n max-width: 400px;\n
|
|
4962
|
-
"progress": "@reference \"tailwindcss\";\n\n@layer components {\n .bar {\n @apply relative w-full overflow-hidden;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n }\n\n .bar { height: 0.5rem; }\n\n .fill {\n @apply h-full;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--
|
|
4963
|
-
"radio": "@reference \"tailwindcss\";\n\n@layer components {\n .radio-items {\n @apply flex flex-col gap-3;\n }\n\n .radio-item {\n @apply flex items-start gap-3 cursor-pointer select-none;\n position: relative;\n overflow: visible;\n }\n\n .radio-surface {\n @apply inline-flex shrink-0;\n border-radius: 9999px;\n }\n\n .radio-input {\n @apply absolute inset-0 h-full w-full cursor-pointer opacity-0;\n }\n\n .radio {\n --disabled-opacity: 0.6;\n @apply relative flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: 9999px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n
|
|
4964
|
-
"scroll": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply relative;\n min-height: 0;\n }\n\n .vertical {\n --scrollbar-width: 12px;\n }\n\n .horizontal {\n --scrollbar-height: 12px;\n }\n\n .content {\n @apply h-full w-full;\n overflow: auto;\n }\n\n .vertical .content {\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .vertical[data-inline=\"true\"] .content {\n padding-right: 16px;\n }\n\n .horizontal .content {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .horizontal[data-inline=\"true\"] .content {\n padding-bottom: 16px;\n }\n\n .vertical .content::-webkit-scrollbar,\n .horizontal .content::-webkit-scrollbar { display: none; }\n\n .track {\n @apply absolute;\n z-index: 10;\n background-color: var(--
|
|
4965
|
-
"select": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n
|
|
4966
|
-
"slider": "@reference \"tailwindcss\";\n\n@layer components {\n .slider {\n --disabled-opacity: 0.6;\n --slider-track-size: 0.375rem;\n --slider-thumb-size: 1rem;\n\n @apply relative flex w-full items-center;\n min-inline-size: var(--slider-min-inline-size, 12rem);\n min-height: var(--slider-hit-size, 2rem);\n touch-action: none;\n user-select: none;\n }\n\n .track {\n @apply relative flex grow items-center;\n flex-grow: 1;\n height: var(--slider-track-size);\n overflow: visible;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n border: var(--slider-track-border, 0);\n background: var(--slider-track-background, var(--background));\n }\n\n .range {\n @apply absolute;\n display: var(--slider-range-display, block);\n pointer-events: none;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n background: var(--slider-range-background, var(--background));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb {\n @apply absolute block;\n top: 50%;\n width: var(--slider-thumb-size);\n height: var(--slider-thumb-size);\n transform: var(--slider-thumb-transform, translate(-50%, -50%));\n border-radius: var(--radius-full, 9999px);\n outline: none;\n background: var(--slider-thumb-background, var(--background));\n border: var(--slider-thumb-border, 1px solid var(--background-border));\n box-shadow: var(--slider-thumb-shadow, none);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .slider[data-orientation=\"horizontal\"] .range {\n top: 0;\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] {\n justify-content: center;\n min-inline-size: auto;\n width: fit-content;\n }\n\n .slider[data-orientation=\"vertical\"] .track {\n width: var(--slider-track-size);\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .range {\n left: 0;\n width: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .thumb {\n left: 50%;\n top: auto;\n --slider-thumb-transform: translate(-50%, 50%);\n }\n\n .slider[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .slider[data-disabled=\"true\"] .range {\n background: var(--slider-range-background-disabled, var(--background-disabled, var(--slider-range-background, var(--background))));\n }\n\n .thumb[data-disabled=\"true\"] {\n cursor: not-allowed;\n background: var(--slider-thumb-background-disabled, var(--background-disabled, var(--slider-thumb-background, var(--background))));\n }\n\n .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, -50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n\n .slider[data-orientation=\"vertical\"] .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, 50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n}\n",
|
|
4967
|
-
"switch": "@reference \"tailwindcss\";\n\n@layer components {\n .switch {\n --radius: 9999px;\n --inner-radius: calc(var(--radius) - var(--border-width-base));\n\n --width: 2.75rem;\n --height: 1.5rem;\n --thumb-size: 1rem;\n --thumb-offset: 0.25rem;\n\n --disabled-opacity: 0.6;\n\n @apply relative inline-flex cursor-pointer items-center;\n user-select: none;\n border-radius: var(--radius);\n width: var(--width);\n height: var(--height);\n }\n\n .switch-track {\n @apply absolute inset-0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-radius: var(--radius);\n }\n\n .switch:active:not([data-disabled]) .switch-track {\n transform: scale(0.98);\n }\n\n .switch-thumb {\n @apply absolute top-0 bottom-0 my-auto;\n left: var(--thumb-offset);\n width: var(--thumb-size);\n height: var(--thumb-size);\n transition: left 180ms var(--ease-snappy-pop), background-color 180ms var(--ease-snappy-pop);\n background-color: var(--foreground);\n border-radius: var(--inner-radius);\n z-index: 1;\n pointer-events: none;\n }\n\n .switch[data-selected] .switch-
|
|
4968
|
-
"table": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply w-full;\n }\n\n .container {\n @apply w-full overflow-x-auto rounded-
|
|
4969
|
-
"tabs": "@reference \"tailwindcss\";\n\n@layer components {\n .tabs {\n @apply flex w-full flex-col;\n\n &[data-orientation=\"vertical\"] {\n flex-direction: row;\n }\n }\n\n .list {\n @apply relative flex w-full flex-row items-center gap-3 py-1;\n border-radius: var(--radius-sm);\n\n &[data-orientation=\"vertical\"] {\n flex-direction: column;\n width: fit-content;\n min-width: 0;\n height: auto;\n align-self: flex-start;\n }\n\n &[data-variant=\"underline\"] {\n background-color: transparent;\n border-radius: 0;\n padding: 0 0 4px;\n }\n\n &[data-variant=\"underline\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-left: var(--border-width-base) solid var(--border);\n align-items: stretch;\n padding: 0 0 0 4px;\n }\n }\n\n .indicator {\n @apply absolute;\n background-color: var(--background);\n box-sizing: border-box;\n border-radius: var(--radius-sm);\n z-index: 0;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: none;\n }\n\n .indicator-fallback {\n z-index: -1;\n }\n\n .indicator-underline {\n border-radius: 0;\n }\n\n .trigger {\n @apply relative z-[1] flex shrink-0 items-center justify-center gap-2 px-2 py-1.5 cursor-pointer select-none;\n height: auto;\n background-color: var(--background);\n border: none;\n color: var(--foreground);\n outline: none;\n box-shadow: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n\n
|
|
4970
|
-
"textarea": "@reference \"tailwindcss\";\n\n@layer components {\n .textarea {\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n\n @apply block w-full px-3 py-2;\n box-sizing: border-box;\n resize: none;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n color: var(--foreground);\n font-family: inherit;\n font-size: var(--text-
|
|
4971
|
-
"toast": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply flex w-full max-w-[28rem] items-start gap-3 px-4 py-2.5 select-none;\n background: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-shadow: var(--background-shadow);\n font-family: inherit;\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n touch-action: pan-y;\n }\n\n .icon-wrap {\n @apply mr-4 mt-2 h-5 w-5 shrink-0;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--foreground);\n }\n\n .content {\n @apply min-w-0 flex-1;\n }\n\n .title {\n @apply m-0;\n --foreground: inherit;\n font-weight: var(--font-weight-semibold);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n color: var(--foreground);\n }\n\n .description {\n @apply mt-1 mb-0;\n --foreground: inherit;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n color: var(--foreground);\n }\n\n .close {\n @apply flex shrink-0 items-center justify-center p-2 cursor-pointer;\n --foreground: currentColor;\n
|
|
4873
|
+
"path": "@reference \"tailwindcss\";\n\n@layer components {\n .path {\n @apply block;\n }\n\n .list {\n @apply m-0 flex flex-wrap items-center gap-2 p-0;\n list-style: none;\n }\n\n .list[data-separator=\"custom\"] .item:not(:last-child)::after {\n content: none;\n }\n\n .item {\n @apply m-0 flex items-center gap-2 p-0;\n border-radius: var(--radius-sm, 0.375rem);\n }\n\n .item:not(:last-child)::after {\n content: \"/\";\n margin-inline-start: 0.5rem;\n color: var(--foreground);\n pointer-events: none;\n user-select: none;\n }\n\n .separator {\n @apply m-0 flex items-center p-0;\n list-style: none;\n color: var(--foreground);\n pointer-events: none;\n user-select: none;\n }\n\n .link {\n @apply relative cursor-pointer px-2 py-1;\n border: 0;\n /* Inherit the item radius so the focus ring matches rounded breadcrumbs. */\n border-radius: inherit;\n background-color: var(--background);\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--leading-normal, 1.5);\n text-decoration: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n button.link {\n font: inherit;\n }\n\n .link:focus,\n .link:focus-visible {\n outline: none;\n }\n\n .link[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-selected=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .link[data-selected=\"true\"] {\n cursor: default;\n }\n\n .link[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity);\n }\n}\n",
|
|
4874
|
+
"popover": "@reference \"tailwindcss\";\n\n@layer components {\n .trigger {\n @apply inline-block;\n }\n\n .root {\n @apply absolute;\n pointer-events: none;\n z-index: 50;\n }\n\n .content {\n --frame-fill: var(--background);\n --frame-stroke-color: var(--background-border);\n --frame-radius: 8px;\n opacity: 0;\n transform: scale(0.95);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n pointer-events: none;\n min-width: 200px;\n max-width: 400px;\n }\n\n .content[data-visible=\"true\"] {\n opacity: 1;\n transform: scale(1);\n pointer-events: auto;\n }\n\n .content[data-instant] {\n transition: none;\n }\n\n .frame {\n @apply flex items-center gap-1.5 p-2.5;\n color: var(--foreground);\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n }\n}\n",
|
|
4875
|
+
"progress": "@reference \"tailwindcss\";\n\n@layer components {\n .bar {\n @apply relative w-full overflow-hidden;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n }\n\n .bar { height: 0.5rem; }\n\n .fill {\n @apply h-full;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n transition: width 300ms var(--ease-snappy-pop);\n }\n\n .fill[data-animated=\"true\"] {\n animation: pulse 2s var(--ease-gentle-ease) infinite;\n }\n\n .fill[data-indeterminate=\"true\"] {\n width: 33.333%;\n animation: progress-indeterminate 1.5s var(--ease-gentle-ease) infinite;\n }\n\n .wrapper {\n @apply w-full;\n }\n\n .wrapper[data-has-label=\"true\"] {\n @apply space-y-1;\n }\n\n .label-row {\n @apply flex items-center justify-between;\n font-size: var(--text-sm);\n color: var(--foreground);\n }\n\n .label {\n user-select: none;\n }\n\n .value {\n font-variant-numeric: tabular-nums;\n }\n\n @keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n }\n\n @keyframes progress-indeterminate {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(400%); }\n }\n}\n",
|
|
4876
|
+
"radio": "@reference \"tailwindcss\";\n\n@layer components {\n .radio-items {\n @apply flex flex-col gap-3;\n }\n\n .radio-item {\n @apply flex items-start gap-3 cursor-pointer select-none;\n position: relative;\n overflow: visible;\n }\n\n .radio-surface {\n @apply inline-flex shrink-0;\n border-radius: 9999px;\n }\n\n .radio-input {\n @apply absolute inset-0 h-full w-full cursor-pointer opacity-0;\n }\n\n .radio {\n --disabled-opacity: 0.6;\n @apply relative flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: 9999px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n color: var(--foreground);\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n }\n }\n\n .radio-item:active .radio {\n transform: scale(0.92);\n }\n\n .dot {\n border-radius: 9999px;\n background-color: var(--background);\n transform: scale(0);\n transform-origin: center;\n transition: transform 200ms var(--ease-snappy-pop), background-color 200ms var(--ease-snappy-pop);\n }\n\n .radio[data-selected=\"true\"] .dot {\n transform: scale(1);\n }\n\n @media (hover: hover) {\n .radio-item:not([data-disabled=\"true\"]):hover .radio {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n opacity: 0.9;\n }\n }\n\n .radio-item[data-disabled=\"true\"] .radio {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .radio-label {\n @apply cursor-pointer;\n color: var(--foreground);\n font-size: inherit;\n font-weight: var(--font-weight-medium, 500);\n line-height: inherit;\n transition: color 200ms var(--ease-snappy-pop);\n user-select: none;\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n }\n\n .radio-description {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.125rem;\n transition: color 200ms var(--ease-snappy-pop);\n }\n\n .helper-text {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.5rem;\n margin-left: 2rem;\n transition: color 200ms var(--ease-snappy-pop);\n }\n\n .radio.sm {\n @apply h-4 w-4;\n }\n\n .radio.sm .dot {\n width: 0.375rem;\n height: 0.375rem;\n }\n\n .radio.md {\n @apply h-5 w-5;\n }\n\n .radio.md .dot {\n width: 0.5rem;\n height: 0.5rem;\n }\n\n .radio.lg {\n @apply h-6 w-6;\n }\n\n .radio.lg .dot {\n width: 0.625rem;\n height: 0.625rem;\n }\n}\n",
|
|
4877
|
+
"scroll": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply relative;\n min-height: 0;\n }\n\n .vertical {\n --scrollbar-width: 12px;\n }\n\n .horizontal {\n --scrollbar-height: 12px;\n }\n\n .content {\n @apply h-full w-full;\n overflow: auto;\n }\n\n .vertical .content {\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .vertical[data-inline=\"true\"] .content {\n padding-right: 16px;\n }\n\n .horizontal .content {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .horizontal[data-inline=\"true\"] .content {\n padding-bottom: 16px;\n }\n\n .vertical .content::-webkit-scrollbar,\n .horizontal .content::-webkit-scrollbar { display: none; }\n\n .track {\n @apply absolute;\n z-index: 10;\n background-color: var(--background);\n }\n\n .track[data-hide=\"true\"] {\n transition-property: opacity;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .track {\n right: 4px;\n top: var(--scroll-padding-y, 0);\n width: 12px;\n height: calc(100% - 2 * var(--scroll-padding-y, 0));\n box-sizing: border-box;\n }\n\n .horizontal .track {\n bottom: 2px;\n left: 0;\n height: 12px;\n width: 100%;\n }\n\n .thumb {\n position: absolute;\n border-radius: calc(var(--radius-xs, 0.25rem) * 0.80);\n background-color: var(--background);\n transition-property: background-color, width, height;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .vertical .thumb {\n width: 6px;\n margin-left: 6px;\n transition-property: background-color, width, margin-left;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .thumb:hover,\n .vertical[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n width: 8px;\n margin-left: 4px;\n }\n\n .horizontal .thumb {\n height: 6px;\n margin-top: 6px;\n transition-property: background-color, height, margin-top;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .horizontal .thumb:hover,\n .horizontal[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n height: 8px;\n margin-top: 4px;\n }\n}\n",
|
|
4878
|
+
"select": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n transition: box-shadow 150ms var(--ease-snappy-pop), border-color 150ms var(--ease-snappy-pop);\n\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-in-from-bottom { from { opacity: 0; translate: 0 2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-from-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n @keyframes slide-out-from-bottom { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 2px; } }\n}\n",
|
|
4879
|
+
"slider": "@reference \"tailwindcss\";\n\n@layer components {\n .slider {\n --disabled-opacity: 0.6;\n --slider-track-size: 0.375rem;\n --slider-thumb-size: 1rem;\n\n @apply relative flex w-full items-center;\n min-inline-size: var(--slider-min-inline-size, 12rem);\n min-height: var(--slider-hit-size, 2rem);\n touch-action: none;\n user-select: none;\n }\n\n .track {\n @apply relative flex grow items-center;\n flex-grow: 1;\n height: var(--slider-track-size);\n overflow: visible;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n border: var(--slider-track-border, 0);\n background: var(\n --slider-track-background,\n var(--background, var(--background-800, transparent))\n );\n }\n\n .range {\n @apply absolute;\n display: var(--slider-range-display, block);\n pointer-events: none;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n background: var(--slider-range-background, var(--background));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb {\n @apply absolute block;\n top: 50%;\n width: var(--slider-thumb-size);\n height: var(--slider-thumb-size);\n transform: var(--slider-thumb-transform, translate(-50%, -50%));\n border-radius: var(--radius-full, 9999px);\n outline: none;\n background: var(--slider-thumb-background, var(--background));\n border: var(--slider-thumb-border, 1px solid var(--background-border));\n box-shadow: var(--slider-thumb-shadow, none);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .slider[data-orientation=\"horizontal\"] .range {\n top: 0;\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] {\n justify-content: center;\n min-inline-size: auto;\n width: fit-content;\n }\n\n .slider[data-orientation=\"vertical\"] .track {\n width: var(--slider-track-size);\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .range {\n left: 0;\n width: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .thumb {\n left: 50%;\n top: auto;\n --slider-thumb-transform: translate(-50%, 50%);\n }\n\n .slider[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .slider[data-disabled=\"true\"] .range {\n background: var(--slider-range-background-disabled, var(--background-disabled, var(--slider-range-background, var(--background))));\n }\n\n .thumb[data-disabled=\"true\"] {\n cursor: not-allowed;\n background: var(--slider-thumb-background-disabled, var(--background-disabled, var(--slider-thumb-background, var(--background))));\n }\n\n .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, -50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n\n .slider[data-orientation=\"vertical\"] .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, 50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n}\n",
|
|
4880
|
+
"switch": "@reference \"tailwindcss\";\n\n@layer components {\n .switch {\n --radius: 9999px;\n --inner-radius: calc(var(--radius) - var(--border-width-base));\n\n --width: 2.75rem;\n --height: 1.5rem;\n --thumb-size: 1rem;\n --thumb-offset: 0.25rem;\n\n --disabled-opacity: 0.6;\n\n @apply relative inline-flex cursor-pointer items-center;\n user-select: none;\n border-radius: var(--radius);\n width: var(--width);\n height: var(--height);\n }\n\n .switch-track {\n @apply absolute inset-0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n border: var(--border-width-base) solid var(--background-border);\n border-radius: var(--radius);\n }\n\n .switch:active:not([data-disabled]) .switch-track {\n transform: scale(0.98);\n }\n\n .switch-thumb {\n @apply absolute top-0 bottom-0 my-auto;\n left: var(--thumb-offset);\n width: var(--thumb-size);\n height: var(--thumb-size);\n transition: left 180ms var(--ease-snappy-pop), background-color 180ms var(--ease-snappy-pop);\n background-color: var(--foreground);\n border-radius: var(--inner-radius);\n z-index: 1;\n pointer-events: none;\n }\n\n .switch[data-selected] .switch-thumb {\n left: calc(var(--width) - var(--thumb-size) - var(--thumb-offset));\n }\n\n @media (hover: hover) {\n .switch[data-hovered=\"true\"]:not([data-disabled]) .switch-track {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .switch[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n\n .switch-sm {\n --width: 1.75rem;\n --height: 1rem;\n --thumb-size: 0.625rem;\n --thumb-offset: 0.1875rem;\n }\n}\n",
|
|
4881
|
+
"table": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply w-full;\n }\n\n .container {\n @apply w-full overflow-x-auto rounded-sm;\n border: var(--border-width-base) solid var(--border, var(--background-border));\n background-color: var(--container-background, var(--background));\n }\n\n .container {\n display: block;\n max-width: none;\n }\n\n .table {\n @apply w-full;\n display: table;\n border-collapse: collapse;\n min-width: max-content;\n background-color: var(--background, transparent);\n color: var(--foreground);\n font-size: var(--text-xs);\n }\n\n .header {\n display: table-header-group;\n background-color: var(--background);\n }\n\n .body {\n display: table-row-group;\n background-color: var(--background);\n }\n\n .headerRow {\n display: table-row;\n background-color: var(--background);\n }\n\n .headerCell {\n @apply px-4 py-3 text-left;\n display: table-cell;\n background-color: var(--background);\n color: var(--foreground);\n font-weight: var(--header-font-weight, var(--font-weight-semibold));\n white-space: nowrap;\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n }\n\n .headerCell:first-child {\n border-top-left-radius: var(--radius-xs);\n }\n\n .headerCell:last-child {\n border-top-right-radius: var(--radius-xs);\n }\n\n .row {\n display: table-row;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row[data-interactive=\"true\"] {\n @apply cursor-pointer;\n }\n\n .row:hover:not([data-disabled=\"true\"]) .cell {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .row[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.5);\n }\n\n .row:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: -2px;\n }\n\n .interactive {\n @apply cursor-pointer;\n }\n\n .cell {\n @apply px-4 py-3 align-middle;\n display: table-cell;\n background-color: var(--background, transparent);\n color: var(--foreground);\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row:last-child .cell {\n border-bottom: none;\n }\n\n .row:last-child .cell:first-child {\n border-bottom-left-radius: var(--radius-xs);\n }\n\n .row:last-child .cell:last-child {\n border-bottom-right-radius: var(--radius-xs);\n }\n\n .emptyRow {\n border-bottom: none;\n }\n\n .emptyRow {\n display: table-row;\n }\n\n .emptyState {\n @apply px-4 py-8 text-center;\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .emptyState {\n display: table-cell;\n }\n\n .filterBar {\n @apply mb-4 rounded-xs border p-4;\n border: var(--border-width-base) solid var(--background-border);\n background-color: var(--background);\n }\n\n .filterBar {\n display: block;\n }\n\n .filterGrid {\n @apply grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3;\n background-color: var(--background);\n }\n\n .filterGrid {\n display: grid;\n }\n\n .filterField {\n @apply min-w-0;\n }\n\n .filterLabel {\n @apply mb-2 block;\n color: var(--foreground);\n font-size: var(--filter-label-font-size, var(--text-xs));\n font-weight: var(--filter-label-font-weight, var(--font-weight-medium));\n }\n\n .filterLabel {\n display: block;\n }\n\n .filterInput {\n @apply w-full;\n }\n}\n",
|
|
4882
|
+
"tabs": "@reference \"tailwindcss\";\n\n@layer components {\n .tabs {\n @apply flex w-full flex-col;\n\n &[data-orientation=\"vertical\"] {\n flex-direction: row;\n }\n }\n\n .list {\n @apply relative flex w-full flex-row items-center gap-3 py-1;\n border-radius: var(--radius-sm);\n\n &[data-orientation=\"vertical\"] {\n flex-direction: column;\n width: fit-content;\n min-width: 0;\n height: auto;\n align-self: flex-start;\n }\n\n &[data-variant=\"underline\"] {\n background-color: transparent;\n border-radius: 0;\n padding: 0 0 4px;\n }\n\n &[data-variant=\"underline\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-left: var(--border-width-base) solid var(--border);\n align-items: stretch;\n padding: 0 0 0 4px;\n }\n }\n\n .indicator {\n @apply absolute;\n background-color: var(--background);\n box-sizing: border-box;\n border-radius: var(--radius-sm);\n z-index: 0;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: none;\n }\n\n .indicator-fallback {\n z-index: -1;\n }\n\n .indicator-underline {\n border-radius: 0;\n }\n\n .trigger {\n @apply relative z-[1] flex shrink-0 items-center justify-center gap-2 px-2 py-1.5 cursor-pointer select-none;\n height: auto;\n background-color: var(--background);\n border: none;\n color: var(--foreground);\n outline: none;\n box-shadow: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-selected=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-selected=\"true\"] {\n cursor: pointer;\n }\n\n &[data-selected=\"true\"]:not([data-indicator-ready=\"true\"]):not([data-indicator-fallback=\"true\"]) {\n .list[data-variant=\"underline\"] & {\n border-bottom-color: var(--underline-border);\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] & {\n border-bottom-color: transparent;\n border-left-color: var(--underline-border);\n }\n }\n\n &:focus,\n &:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n }\n\n &[data-disabled=\"true\"] {\n --disabled-opacity: 0.5;\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .list[data-variant=\"underline\"] & {\n background-color: var(--background);\n background-clip: padding-box;\n border-radius: var(--radius-sm);\n border-bottom: 2px solid transparent;\n }\n\n .list[data-variant=\"underline\"] &:focus,\n .list[data-variant=\"underline\"] &:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] & {\n border-bottom: none;\n border-left: 2px solid transparent;\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] &[data-selected=\"true\"]:not([data-indicator-ready=\"true\"]):not([data-indicator-fallback=\"true\"]) {\n border-left-color: var(--underline-border);\n border-bottom: none;\n }\n }\n\n .icon {\n @apply flex h-4 w-4 shrink-0 items-center justify-center;\n }\n\n .content {\n @apply w-full p-0 outline-none;\n flex: 1;\n padding-top: 1rem;\n\n &[data-orientation=\"vertical\"] {\n flex: 1;\n width: 100%;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n }\n\n @media (max-width: 640px) {\n .list {\n padding: 0.125rem;\n\n &[data-variant=\"underline\"] {\n padding: 0 0 4px;\n }\n }\n\n .trigger {\n @apply px-1 py-1;\n .list[data-variant=\"underline\"] & {\n margin: 0.5rem 0.75rem;\n }\n }\n }\n}\n",
|
|
4883
|
+
"textarea": "@reference \"tailwindcss\";\n\n@layer components {\n .textarea {\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n\n @apply block w-full px-3 py-2;\n box-sizing: border-box;\n resize: none;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n color: var(--foreground);\n font-family: inherit;\n font-size: var(--text-xs);\n line-height: var(--leading-snug);\n outline: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &::placeholder {\n color: var(--placeholder);\n }\n\n &[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity);\n }\n\n &[data-resize-axis=\"x\"],\n &[data-resize-axis=\"both\"] {\n padding-inline-end: calc(var(--padding-inline) + 1rem);\n }\n\n &[data-resize-axis=\"y\"],\n &[data-resize-axis=\"both\"] {\n padding-block-end: calc(var(--padding-block) + 1rem);\n }\n\n &[data-scroll=\"true\"] {\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: hidden;\n\n &[data-disabled=\"true\"] {\n opacity: 1;\n }\n }\n }\n\n .size-sm {\n min-height: 5rem;\n --padding-inline: 0.5rem;\n --padding-block: 0.25rem;\n font-size: var(--text-sm);\n @apply px-2 py-1;\n }\n\n .size-md {\n min-height: 6rem;\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n font-size: var(--text-sm);\n @apply px-3 py-2;\n }\n\n .size-lg {\n min-height: 8rem;\n --padding-inline: 1rem;\n --padding-block: 0.75rem;\n font-size: var(--text-md);\n @apply px-4 py-3;\n }\n\n .container {\n min-width: 0;\n @apply w-full;\n }\n\n .scope {\n @apply relative flex w-full;\n overflow: visible;\n }\n\n .surface {\n min-width: 0;\n @apply relative w-full;\n }\n\n .scroll-wrapper {\n @apply w-full overflow-hidden;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n }\n }\n\n .resize-handle {\n position: absolute;\n z-index: 1;\n touch-action: none;\n user-select: none;\n\n &::before,\n &::after {\n content: \"\";\n position: absolute;\n border-radius: var(--radius-full);\n background-color: var(--background);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n &:hover::before,\n &:hover::after {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .resize-handle-both {\n right: 3px;\n bottom: 3px;\n width: 1.5rem;\n height: 1.5rem;\n cursor: nwse-resize;\n\n &::before {\n right: 0.15rem;\n bottom: 0.35rem;\n width: 0.5rem;\n height: 0.125rem;\n transform: rotate(-45deg);\n transform-origin: center;\n }\n\n &::after {\n right: 0.2rem;\n bottom: 0.6rem;\n width: 1rem;\n height: 0.125rem;\n transform: rotate(-45deg);\n transform-origin: center;\n }\n }\n\n .resize-handle-x {\n top: 50%;\n right: 0;\n width: 0.75rem;\n height: 2rem;\n cursor: ew-resize;\n transform: translateY(-50%);\n\n &::before {\n top: 50%;\n left: 50%;\n width: 0.125rem;\n height: 1.5rem;\n transform: translate(-50%, -50%);\n }\n\n &::after {\n display: none;\n }\n }\n\n .resize-handle-y {\n left: 50%;\n bottom: 0;\n width: 2rem;\n height: 0.75rem;\n cursor: ns-resize;\n transform: translateX(-50%);\n\n &::before {\n top: 50%;\n left: 50%;\n width: 1.5rem;\n height: 0.125rem;\n transform: translate(-50%, -50%);\n }\n\n &::after {\n display: none;\n }\n }\n\n .character-count {\n @apply mt-1;\n color: var(--foreground);\n font-size: var(--text-sm);\n transition: color 0.15s var(--ease-snappy-pop);\n }\n\n .character-count[data-over-limit=\"true\"] {\n color: var(--foreground-error);\n }\n}\n",
|
|
4884
|
+
"toast": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply flex w-full max-w-[28rem] items-start gap-3 px-4 py-2.5 select-none;\n background: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-shadow: var(--background-shadow);\n font-family: inherit;\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n touch-action: pan-y;\n }\n\n .icon-wrap {\n @apply mr-4 mt-2 h-5 w-5 shrink-0;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--foreground);\n }\n\n .content {\n @apply min-w-0 flex-1;\n }\n\n .title {\n @apply m-0;\n --foreground: inherit;\n font-weight: var(--font-weight-semibold);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n color: var(--foreground);\n }\n\n .description {\n @apply mt-1 mb-0;\n --foreground: inherit;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n color: var(--foreground);\n }\n\n .close {\n @apply flex shrink-0 items-center justify-center p-2 cursor-pointer;\n --foreground: currentColor;\n background-color: var(--background, transparent);\n border: none;\n border-radius: var(--radius-sm, 0.375rem);\n color: var(--foreground);\n opacity: 0.6;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-settle-in, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-settle-in, ease-out));\n\n &[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 var(--border-width-base, 1px) var(--focus-visible);\n outline: none;\n }\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n opacity: 1;\n }\n }\n\n .close-icon {\n @apply h-4 w-4;\n }\n}\n",
|
|
4972
4885
|
"tooltip": "@reference \"tailwindcss\";\n\n@layer components {\n .trigger {\n display: contents;\n }\n\n .root {\n @apply absolute;\n pointer-events: none;\n z-index: 50;\n }\n\n .content {\n --frame-fill: var(--background);\n --frame-stroke-color: var(--background-border);\n opacity: 0;\n transition: opacity 0.15s ease-out, transform 0.15s ease-out;\n }\n\n .content[data-open=\"true\"] {\n opacity: 1;\n pointer-events: auto;\n }\n\n .content[data-instant=\"true\"] {\n transition: none;\n }\n\n .frame {\n @apply flex items-center gap-1.5 px-2 py-1 whitespace-nowrap;\n color: var(--foreground);\n }\n\n .frame[data-hint=\"true\"] {\n @apply pr-1;\n }\n\n .hint {\n @apply flex-shrink-0;\n }\n}\n"
|
|
4973
4886
|
};
|
|
4974
4887
|
export const generatedSourceCode = {
|
|
4975
4888
|
"anchor": {
|
|
4976
4889
|
"tsx": "import * as React from \"react\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Tooltip } from \"@/components/Tooltip\";\nimport css from \"./Anchor.module.css\";\n\ntype Orientation = \"horizontal\" | \"vertical\";\ntype Size = \"sm\" | \"md\" | \"lg\";\n\ninterface AnchorStyleSlots {\n root?: StyleValue;\n underline?: StyleValue;\n preview?: StyleValue;\n}\n\ntype AnchorStylesProp = StylesProp<AnchorStyleSlots>;\n\nconst resolveAnchorBaseStyles = createStylesResolver(['root', 'underline', 'preview'] as const);\n\nfunction resolveAnchorStyles(styles: AnchorStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveAnchorBaseStyles(styles);\n return resolveAnchorBaseStyles(styles);\n}\nconst ANCHOR_PREVIEW_DISPLAY_NAME = \"Anchor.Preview\";\nconst ANCHOR_UNDERLINE_DISPLAY_NAME = \"Anchor.Underline\";\n\nconst DASHED_DIMENSIONS = {\n sm: { thickness: 1, dashLength: 8, gapLength: 4 },\n md: { thickness: 2, dashLength: 8, gapLength: 4 },\n lg: { thickness: 4, dashLength: 10, gapLength: 6 },\n} as const;\n\nconst DOTTED_DIMENSIONS = {\n sm: { thickness: 1, radius: 0.5, spacing: 6 },\n md: { thickness: 2, radius: 1, spacing: 8 },\n lg: { thickness: 4, radius: 2, spacing: 12 },\n} as const;\n\nfunction getPath(orientation: Orientation, size: Size): string {\n const { thickness, dashLength, gapLength } = DASHED_DIMENSIONS[size];\n const totalLength = dashLength + gapLength;\n\n if (orientation === \"horizontal\") {\n return `%3Csvg width='${totalLength}' height='${thickness}' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='0' width='${dashLength}' height='${thickness}' fill='%23ffffff'/%3E%3C/svg%3E`;\n }\n return `%3Csvg width='${thickness}' height='${totalLength}' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='0' width='${thickness}' height='${dashLength}' fill='%23ffffff'/%3E%3C/svg%3E`;\n}\n\nfunction getDottedMaskSvg(orientation: Orientation, size: Size): string {\n const { thickness, radius, spacing } = DOTTED_DIMENSIONS[size];\n\n if (orientation === \"horizontal\") {\n return `%3Csvg width='${spacing}' height='${thickness}' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='${radius}' cy='${radius}' r='${radius}' fill='%23ffffff'/%3E%3C/svg%3E`;\n }\n return `%3Csvg width='${thickness}' height='${spacing}' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='${radius}' cy='${radius}' r='${radius}' fill='%23ffffff'/%3E%3C/svg%3E`;\n}\n\ntype CompoundComponentType = {\n displayName?: string;\n name?: string;\n render?: {\n displayName?: string;\n name?: string;\n };\n};\n\nfunction matchesCompoundComponent(\n childType: React.JSXElementConstructor<any> | string | undefined,\n component: React.JSXElementConstructor<any>,\n displayName: string,\n): boolean {\n if (!childType) {\n return false;\n }\n\n if (childType === component) {\n return true;\n }\n\n if (typeof childType === \"string\") {\n return false;\n }\n\n const componentType = childType as CompoundComponentType;\n\n return (\n componentType.displayName === displayName ||\n componentType.name === displayName ||\n componentType.render?.displayName === displayName ||\n componentType.render?.name === displayName\n );\n}\n\n// --- Sub-components ---\n\nexport interface AnchorPreviewProps\n extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport function AnchorPreview({ children }: AnchorPreviewProps) {\n return null;\n}\nAnchorPreview.displayName = ANCHOR_PREVIEW_DISPLAY_NAME;\n\ninterface AnchorUnderlineProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Controls the line style of the underline */\n variant?: \"solid\" | \"dashed\" | \"dotted\";\n}\n\nconst AnchorUnderline = React.forwardRef<HTMLDivElement, AnchorUnderlineProps>(\n ({ className, variant = \"solid\", style, ...props }, ref) => {\n const getMaskStyles = (): React.CSSProperties => {\n if (variant === \"solid\") return {}\n\n const orientation = \"horizontal\";\n const size = \"sm\";\n\n const svgDataUri = variant === \"dashed\" ? getPath(orientation, size) : getDottedMaskSvg(orientation, size);\n const maskRepeat = \"repeat-x\";\n const encodedSvg = `url(\"data:image/svg+xml,${svgDataUri}\")`;\n\n return {\n WebkitMaskImage: encodedSvg,\n maskImage: encodedSvg,\n WebkitMaskRepeat: maskRepeat,\n maskRepeat: maskRepeat,\n } as React.CSSProperties;\n };\n\n return (\n <span\n ref={ref}\n className={cn(css.underline, className)}\n style={{ ...getMaskStyles(), ...style }}\n {...props}\n />\n );\n }\n);\nAnchorUnderline.displayName = ANCHOR_UNDERLINE_DISPLAY_NAME;\n\n// --- Main Anchor Component ---\n\nexport interface AnchorProps\n extends Omit<React.HTMLAttributes<HTMLElement>, \"onChange\"> {\n children?: React.ReactNode;\n /** Additional CSS class for the anchor element */\n className?: string;\n /** URL the anchor navigates to */\n href?: string;\n /** Browsing context for the link (e.g. \"_blank\") */\n target?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: AnchorStylesProp;\n /** Preview content to show in a tooltip on hover. Use this in server components instead of <Anchor.Preview>. */\n preview?: React.ReactNode;\n}\n\nconst AnchorRoot = React.forwardRef<HTMLAnchorElement | HTMLSpanElement, AnchorProps>(\n ({ className, children, href, target = \"_blank\", styles, preview: previewProp, ...props }, ref) => {\n const rootRef = React.useRef<HTMLAnchorElement | HTMLSpanElement>(null);\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({});\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-anchor-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n });\n const mergedRef = useMergeRefs(rootRef, ref);\n\n let previewContent: React.ReactNode = previewProp ?? null;\n let hasUnderline = false;\n\n const childrenArray = React.Children.toArray(children);\n const resolved = resolveAnchorStyles(styles);\n\n let filteredChildren: React.ReactNode[] = [];\n\n // Extract preview content and filter it out from rendered children\n React.Children.forEach(childrenArray, (child) => {\n if (React.isValidElement(child)) {\n if (matchesCompoundComponent(child.type, AnchorPreview, ANCHOR_PREVIEW_DISPLAY_NAME)) {\n if (!previewProp) previewContent = (child.props as any).children;\n // Don't add to filteredChildren\n } else if (matchesCompoundComponent(child.type, AnchorUnderline, ANCHOR_UNDERLINE_DISPLAY_NAME)) {\n hasUnderline = true;\n // Clone AnchorUnderline to inject resolved.underline\n const underlineChild = child as React.ReactElement<AnchorUnderlineProps>;\n filteredChildren.push(React.cloneElement(underlineChild, {\n className: cn(underlineChild.props.className, resolved.underline),\n }));\n } else {\n filteredChildren.push(child);\n }\n } else {\n filteredChildren.push(child);\n }\n });\n\n // Inject default underline if none provided\n if (!hasUnderline) {\n filteredChildren.push(<AnchorUnderline key=\"__default_underline\" className={resolved.underline} />);\n }\n\n const { onChange, onChangeCapture, ...otherProps } = props as any;\n const mergedFocusProps = mergeProps(focusProps, hoverProps) as any;\n const { onChange: _, onChangeCapture: __, ...safeFocusProps } = mergedFocusProps;\n\n const triggerElement = href ? (\n <a\n ref={mergedRef as React.Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={target === \"_blank\" ? \"noopener noreferrer\" : undefined}\n className={cn(\"anchor\", css.root, className, resolved.root, scopeProps.className)}\n data-anchor-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n {...(otherProps as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n {...(safeFocusProps as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n >\n <span {...indicatorProps} data-focus-indicator=\"local\" aria-hidden=\"true\" />\n {filteredChildren}\n </a>\n ) : (\n <span\n ref={mergedRef as React.Ref<HTMLSpanElement>}\n className={cn(\"anchor\", css.root, className, resolved.root, scopeProps.className)}\n data-anchor-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n {...(otherProps as React.HTMLAttributes<HTMLSpanElement>)}\n {...(safeFocusProps as React.HTMLAttributes<HTMLSpanElement>)}\n >\n <span {...indicatorProps} data-focus-indicator=\"local\" aria-hidden=\"true\" />\n {filteredChildren}\n </span>\n );\n\n // If no preview content, render trigger directly without a tooltip wrapper.\n if (!previewContent) {\n return triggerElement;\n }\n\n return (\n <Tooltip\n content={previewContent}\n showArrow\n position=\"top\"\n className={cn(\"preview\", css.preview)}\n styles={{ content: resolved.preview }}\n >\n {triggerElement}\n </Tooltip>\n );\n },\n);\nAnchorRoot.displayName = \"Anchor\";\n\n// Compound component with attached sub-components\nconst Anchor = Object.assign(AnchorRoot, {\n Preview: AnchorPreview,\n Underline: AnchorUnderline,\n});\n\nexport { Anchor };\n",
|
|
4977
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .preview, .anchor {\n display: inline\n }\n\n .root {\n @apply inline-block relative cursor-pointer;\n display: inline-block;\n color: var(--foreground, currentColor);\n text-decoration: none;\n\n
|
|
4890
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .preview, .anchor {\n display: inline\n }\n\n .root {\n @apply inline-block relative cursor-pointer;\n display: inline-block;\n color: var(--foreground, currentColor);\n text-decoration: none;\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) .underline {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible, var(--focus-ring));\n outline-offset: 2px;\n border-radius: 2px;\n }\n }\n\n .underline {\n @apply absolute left-0 right-0 bottom-0 h-px;\n background-color: var(--underline-background, var(--background-600));\n transform-origin: right;\n transform: scaleX(1);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n pointer-events: none;\n }\n\n .preview {\n }\n}\n",
|
|
4978
4891
|
"cssTypes": "export const anchor: string;\nexport const preview: string;\nexport const root: string;\nexport const underline: string;"
|
|
4979
4892
|
},
|
|
4980
4893
|
"badge": {
|
|
4981
4894
|
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Badge.module.css\";\n\nimport { X } from \"lucide-react\";\n\ntype BadgeIconSlots = {\n left?: React.ReactNode;\n right?: React.ReactNode;\n};\n\ninterface BadgeIconStyles {\n left?: StyleValue;\n right?: StyleValue;\n}\n\nexport interface BadgeStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | BadgeIconStyles;\n iconLeft?: StyleValue;\n iconRight?: StyleValue;\n dismiss?: StyleValue;\n}\n\nexport type BadgeStylesProp = StylesProp<BadgeStyleSlots>;\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual color style of the badge */\n variant?: string;\n /** Icon slots rendered before (left) or after (right) the badge label */\n icon?: React.ReactNode | BadgeIconSlots;\n /** Whether to show a dismiss button */\n dismissible?: boolean;\n /** Called when the dismiss button is clicked */\n onDismiss?: () => void;\n /** Whether to render with a fully rounded pill shape */\n pill?: boolean;\n /** Numeric count to display; replaces children when provided */\n count?: number;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: BadgeStylesProp;\n}\n\ninterface DismissButtonProps {\n onDismiss?: () => void;\n variant: string;\n className?: StyleValue;\n}\n\nfunction DismissButton({ onDismiss, variant, className }: DismissButtonProps) {\n const buttonRef = React.useRef<HTMLDivElement>(null);\n\n const { buttonProps, isPressed } = useButton(\n {\n \"aria-label\": \"Dismiss\",\n onPress: onDismiss,\n },\n buttonRef\n );\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({});\n\n return (\n <div\n {...mergeProps(buttonProps, focusProps, hoverProps)}\n ref={buttonRef}\n role=\"button\"\n tabIndex={0}\n className={cn(\"badge\", variant, \"dismiss\", css.dismiss, className)}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n <X size={14} />\n </div>\n );\n}\n\nconst resolveBadgeBaseStyles = createStylesResolver(['root', 'icon', 'iconLeft', 'iconRight', 'dismiss'] as const);\n\nfunction resolveBadgeStyles(styles: BadgeStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveBadgeBaseStyles(styles);\n const { root, icon, iconLeft, iconRight, dismiss } = styles;\n if (!icon || typeof icon === \"string\" || Array.isArray(icon)) {\n return resolveBadgeBaseStyles({ root, icon: icon as StyleValue | undefined, iconLeft, iconRight, dismiss });\n }\n\n return resolveBadgeBaseStyles({\n root,\n iconLeft: icon.left ?? iconLeft,\n iconRight: icon.right ?? iconRight,\n dismiss,\n });\n}\n\nfunction isBadgeIconSlots(icon: BadgeProps[\"icon\"]): icon is BadgeIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && (\"left\" in icon || \"right\" in icon);\n}\n\nfunction resolveBadgeIcon(icon: BadgeProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isBadgeIconSlots(icon)) {\n return icon;\n }\n\n return { left: icon };\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n variant = \"default\",\n icon,\n dismissible = false,\n onDismiss,\n pill = false,\n count,\n children,\n className,\n styles,\n ...props\n },\n ref\n ) => {\n const resolved = resolveBadgeStyles(styles);\n const resolvedIcon = resolveBadgeIcon(icon);\n return (\n <span\n ref={ref}\n className={cn(\n \"badge\",\n variant,\n css.badge,\n pill && css.pill,\n dismissible && css.dismissible,\n className,\n resolved.root\n )}\n data-variant={variant}\n data-pill={pill ? \"true\" : undefined}\n data-dismissible={dismissible || undefined}\n {...props}\n >\n {resolvedIcon?.left && (\n <span className={cn(\"badge\", variant, \"icon\", css.icon, resolved.icon, resolved.iconLeft)} aria-hidden=\"true\">\n {resolvedIcon.left}\n </span>\n )}\n {count !== undefined ? count : children}\n {resolvedIcon?.right && (\n <span className={cn(\"badge\", variant, \"icon\", css.icon, resolved.icon, resolved.iconRight)} aria-hidden=\"true\">\n {resolvedIcon.right}\n </span>\n )}\n {dismissible && <DismissButton onDismiss={onDismiss} variant={variant} className={resolved.dismiss} />}\n </span>\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n\nexport { Badge };\n",
|
|
4982
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--
|
|
4895
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
|
|
4983
4896
|
"cssTypes": "export interface Styles {\n badge: string;\n pill: string;\n dismissible: string;\n icon: string;\n dismiss: string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
4984
4897
|
},
|
|
4985
4898
|
"banner": {
|
|
@@ -4989,7 +4902,7 @@ export const generatedSourceCode = {
|
|
|
4989
4902
|
},
|
|
4990
4903
|
"button": {
|
|
4991
4904
|
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Button.module.css\";\n\ntype ButtonSize = (string & {});\ntype ButtonIconSlots = {\n left?: React.ReactNode;\n right?: React.ReactNode;\n};\n\ninterface ButtonIconStyles {\n left?: StyleValue;\n right?: StyleValue;\n}\n\nexport interface ButtonStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | ButtonIconStyles;\n}\n\nexport type ButtonStylesProp = StylesProp<ButtonStyleSlots>;\n\nconst resolveButtonBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight'] as const);\n\nfunction resolveButtonStyles(styles: ButtonStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveButtonBaseStyles(styles)\n const { root, icon } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n return resolveButtonBaseStyles({ root, iconLeft, iconRight });\n}\n\nexport interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"href\" | \"target\"> {\n /** Variant class appended to the root element. Accepts any string. */\n variant?: string;\n /** Size class appended to the root element. Accepts any string. */\n size?: ButtonSize;\n /** Disables interaction and applies disabled styling */\n isDisabled?: boolean;\n /** React Aria press handler — preferred over onClick for accessibility */\n onPress?: (e: { target: EventTarget | null }) => void;\n /** Icon slots rendered before (left) or after (right) the button label */\n icon?: React.ReactNode | ButtonIconSlots;\n /** Renders the button as an anchor element when provided */\n href?: string;\n /** Browsing context for the anchor variant (e.g. \"_blank\") */\n target?: React.HTMLAttributeAnchorTarget;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ButtonStylesProp;\n}\n\nfunction isButtonIconSlots(icon: ButtonProps[\"icon\"]): icon is ButtonIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && ('left' in icon || 'right' in icon);\n}\n\nfunction resolveButtonIcon(icon: ButtonProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isButtonIconSlots(icon)) {\n return icon;\n }\n\n return { left: icon };\n}\n\nfunction resolveButtonIconSizeClass(size: ButtonSize | undefined) {\n if (!size) {\n return undefined;\n }\n\n return (css as unknown as Record<string, string | undefined>)[`icon-${size}`];\n}\n\nconst Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n ({ className, styles, variant = \"default\", size = \"md\", children, onClick, onPress, isDisabled, disabled, icon, href, target, rel, ...props }, ref) => {\n const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement>(null);\n const mergedRef = useMergeRefs(ref, buttonRef);\n const isButtonDisabled = isDisabled ?? disabled ?? false;\n const [isPressed, setIsPressed] = React.useState(false);\n const isAnchor = !!href;\n\n const handlePress = React.useCallback((e: any) => {\n if (onPress) onPress({ target: e.target });\n if (onClick) onClick(e as unknown as React.MouseEvent<HTMLButtonElement>);\n }, [onPress, onClick]);\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n if (!isButtonDisabled) {\n setIsPressed(true);\n }\n props.onMouseDown?.(e as any);\n }, [isButtonDisabled, props]);\n\n const handleMouseUp = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseUp?.(e as any);\n }, [props]);\n\n const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseLeave?.(e as any);\n }, [props]);\n\n const { buttonProps } = useButton({\n isDisabled: isButtonDisabled,\n onPress: handlePress,\n }, buttonRef as React.RefObject<HTMLButtonElement>);\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing({ autoFocus: props.autoFocus });\n const { hoverProps, isHovered } = useHover({ isDisabled: isButtonDisabled });\n\n const resolved = resolveButtonStyles(styles);\n const resolvedIcon = resolveButtonIcon(icon);\n const iconSizeClassName = resolveButtonIconSizeClass(size);\n const iconSlotClassName = size === \"icon\" ? \"icon\" : undefined;\n const buttonClassName = cn(\"button\", variant, size, css.button, className, resolved.root);\n\n const { targetProps } = useFocus({ mode: \"target\" });\n\n if (isAnchor) {\n return (\n <a\n {...mergeProps(focusProps, hoverProps, props as any)}\n {...targetProps}\n ref={mergedRef as unknown as React.RefObject<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined)}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </a>\n );\n }\n\n return (\n <button\n {...mergeProps(buttonProps, focusProps, hoverProps, props)}\n {...targetProps}\n disabled={isButtonDisabled}\n ref={mergedRef as unknown as React.RefObject<HTMLButtonElement>}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n\nexport { Button };\n",
|
|
4992
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n
|
|
4905
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &:focus-visible {\n outline: none;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n filter: grayscale(0.5);\n }\n }\n}\n",
|
|
4993
4906
|
"cssTypes": "export interface Styles {\n button: string;\n \"default\": string;\n \"primary\": string;\n \"secondary\": string;\n \"outline\": string;\n \"ghost\": string;\n \"danger\": string;\n \"sm\": string;\n \"md\": string;\n \"lg\": string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
4994
4907
|
},
|
|
4995
4908
|
"card": {
|
|
@@ -4998,9 +4911,9 @@ export const generatedSourceCode = {
|
|
|
4998
4911
|
"cssTypes": "declare const styles: {\n card: string;\n header: string;\n body: string;\n footer: string;\n};\n\nexport default styles;\n"
|
|
4999
4912
|
},
|
|
5000
4913
|
"checkbox": {
|
|
5001
|
-
"tsx": "\"use client\";\n\nimport React, { forwardRef, useId, useState } from \"react\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Checkbox.module.css\";\n\ninterface CheckboxIconStyles {\n checkmark?: StyleValue;\n indeterminate?: StyleValue;\n}\n\nexport interface CheckboxStyleSlots {\n root?: StyleValue;\n checkbox?: StyleValue;\n \"icon-checkmark\"?: StyleValue;\n \"icon-indeterminate\"?: StyleValue;\n icon?: StyleValue | CheckboxIconStyles;\n label?: StyleValue;\n \"helper-text\"?: StyleValue;\n}\n\nexport type CheckboxStylesProp = StylesProp<CheckboxStyleSlots>;\n\nconst resolveCheckboxBaseStyles = createStylesResolver([\n \"root\",\n \"checkbox\",\n \"icon-checkmark\",\n \"icon-indeterminate\",\n \"label\",\n \"helper-text\",\n] as const);\n\nfunction resolveCheckboxStyles(styles: CheckboxStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveCheckboxBaseStyles(styles);\n const { root, checkbox, icon, label } = styles;\n\n let iconCheckmark: StyleValue | undefined = styles[\"icon-checkmark\"];\n let iconIndeterminate: StyleValue | undefined = styles[\"icon-indeterminate\"];\n\n if (icon) {\n if (typeof icon === \"string\" || Array.isArray(icon)) {\n iconCheckmark = cn(icon, iconCheckmark);\n iconIndeterminate = cn(icon, iconIndeterminate);\n } else {\n iconCheckmark = cn(icon.checkmark, iconCheckmark);\n iconIndeterminate = cn(icon.indeterminate, iconIndeterminate);\n }\n }\n\n return resolveCheckboxBaseStyles({\n root,\n checkbox,\n \"icon-checkmark\": iconCheckmark,\n \"icon-indeterminate\": iconIndeterminate,\n label,\n \"helper-text\": styles[\"helper-text\"],\n });\n}\n\nexport interface CheckboxProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n /** Label text or element displayed next to the checkbox */\n label?: React.ReactNode;\n /** Helper text shown below the checkbox. Prefer `helper`; `helperText` is kept as a compatibility alias. */\n helper?: React.ReactNode;\n /** Compatibility alias for `helper`. */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error and mark the checkbox invalid. */\n helperTextError?: boolean;\n /** Whether the checkbox is invalid. Prefer `error`; `isInvalid` is an alias for form libraries. */\n error?: boolean;\n /** Alias for `error`. */\n isInvalid?: boolean;\n /** Whether to show an indeterminate (partial selection) state. Prefer `indeterminate`; `isIndeterminate` is kept as an alias. */\n isIndeterminate?: boolean;\n /** Whether to show an indeterminate (partial selection) state. */\n indeterminate?: boolean;\n /** Ref for the underlying input. The forwarded ref remains attached to the wrapper element. */\n inputRef?: React.Ref<HTMLInputElement>;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: CheckboxStylesProp;\n}\n\nexport const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(\n (\n {\n className,\n label,\n helper,\n helperText,\n helperTextError = false,\n error = false,\n isInvalid = false,\n id,\n disabled = false,\n checked,\n defaultChecked,\n onChange,\n isIndeterminate = false,\n indeterminate = false,\n inputRef: forwardedInputRef,\n styles,\n ...props\n },\n ref\n ) => {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n const helperId = `${inputId}-helper`;\n const resolvedHelper = helper ?? helperText;\n const resolvedIndeterminate = indeterminate || isIndeterminate;\n // Track pressed state for tactile feedback animation (data-pressed attribute)\n const [isPressed, setIsPressed] = useState(false);\n const [internalChecked, setInternalChecked] = useState(() =>\n checked !== undefined ? checked : (defaultChecked ?? false)\n );\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-checkbox-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n\n // React Aria press state handlers for tactile scale animation (mouse)\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n if (!disabled) {\n setIsPressed(true);\n }\n props.onMouseDown?.(e);\n }, [disabled, props]);\n\n const handleMouseUp = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n setIsPressed(false);\n props.onMouseUp?.(e);\n }, [props]);\n\n const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n setIsPressed(false);\n props.onMouseLeave?.(e);\n }, [props]);\n\n // React Aria press state handlers for keyboard interactions (Space/Enter)\n const handleKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!disabled && (e.key === \" \" || e.key === \"Enter\")) {\n setIsPressed(true);\n }\n props.onKeyDown?.(e);\n }, [disabled, props]);\n\n const handleKeyUp = React.useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n setIsPressed(false);\n }\n props.onKeyUp?.(e);\n }, [props]);\n\n React.useEffect(() => {\n if (checked !== undefined) {\n setInternalChecked(checked);\n }\n }, [checked]);\n\n React.useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = resolvedIndeterminate;\n }\n }, [resolvedIndeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n // Update internal state (needed for uncontrolled mode)\n setInternalChecked(e.target.checked);\n // Call parent handler if provided\n onChange?.(e);\n };\n\n const inputProps = mergeProps(props, focusProps, {\n onChange: handleChange,\n onMouseDown: handleMouseDown,\n onMouseUp: handleMouseUp,\n onMouseLeave: handleMouseLeave,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }) as React.InputHTMLAttributes<HTMLInputElement>;\n\n // Determine if this is a controlled component\n const isControlled = checked !== undefined;\n const displayChecked = isControlled ? checked : internalChecked;\n const propAriaInvalid = props[\"aria-invalid\"];\n const resolvedInvalid =\n error ||\n isInvalid ||\n helperTextError ||\n propAriaInvalid === true ||\n propAriaInvalid === \"true\";\n const describedBy = [props[\"aria-describedby\"], resolvedHelper ? helperId : undefined]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n const resolved = resolveCheckboxStyles(styles);\n const mergedRootRef = useMergeRefs(rootRef, ref);\n const mergedInputRef = useMergeRefs(inputRef, forwardedInputRef);\n\n return (\n <div\n ref={mergedRootRef}\n className={cn(\"checkbox-root\", scopeProps.className, css['checkbox-root'], resolved.root)}\n data-disabled={disabled ? \"true\" : undefined}\n data-invalid={resolvedInvalid ? \"true\" : undefined}\n data-indeterminate={resolvedIndeterminate ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div className={cn(css.container)}>\n <input\n {...inputProps}\n ref={mergedInputRef}\n type=\"checkbox\"\n id={inputId}\n disabled={disabled}\n {...(isControlled ? { checked } : { defaultChecked: internalChecked })}\n className={cn(\n 'checkbox',\n css.checkbox,\n className,\n resolved.checkbox\n )}\n data-selected={displayChecked ? \"true\" : undefined}\n data-disabled={disabled ? \"true\" : undefined}\n data-invalid={resolvedInvalid ? \"true\" : undefined}\n data-error={resolvedInvalid ? \"true\" : undefined}\n data-indeterminate={resolvedIndeterminate ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : undefined}\n data-checkbox-focus-surface=\"true\"\n aria-invalid={resolvedInvalid || undefined}\n aria-checked={resolvedIndeterminate ? \"mixed\" : props[\"aria-checked\"]}\n aria-describedby={describedBy}\n />\n {displayChecked && !resolvedIndeterminate && (\n <svg\n className={cn('checkmark', css.checkmark, resolved[\"icon-checkmark\"])}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n )}\n {resolvedIndeterminate && (\n <svg\n className={cn('indeterminate', css.indeterminate, resolved[\"icon-indeterminate\"])}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n )}\n </div>\n {label && (\n <label\n htmlFor={inputId}\n className={cn(\n css.label,\n css[\"label-md\"],\n resolved.label\n )}\n data-disabled={disabled ? \"true\" : undefined}\n >\n {label}\n </label>\n )}\n {resolvedHelper && (\n <p\n id={helperId}\n className={cn(\n css[\"helper-text\"],\n resolved[\"helper-text\"]\n )}\n data-error={resolvedInvalid ? \"true\" : undefined}\n >\n {resolvedHelper}\n </p>\n )}\n </div>\n );\n }\n);\n\nCheckbox.displayName = \"Checkbox\";\n",
|
|
5002
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .checkbox
|
|
5003
|
-
"cssTypes": "declare const styles: {\n \"checkbox-root\": string;\n container: string;\n checkbox: string;\n checkmark: string;\n indeterminate: string;\n label: string;\n \"label-md\": string;\n \"helper-text\": string;\n};\n\nexport default styles;\n"
|
|
4914
|
+
"tsx": "\"use client\";\n\nimport React, { forwardRef, useId, useState } from \"react\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Checkbox.module.css\";\n\ninterface CheckboxIconStyles {\n checkmark?: StyleValue;\n indeterminate?: StyleValue;\n}\n\nexport interface CheckboxStyleSlots {\n root?: StyleValue;\n checkbox?: StyleValue;\n \"icon-checkmark\"?: StyleValue;\n \"icon-indeterminate\"?: StyleValue;\n icon?: StyleValue | CheckboxIconStyles;\n label?: StyleValue;\n \"helper-text\"?: StyleValue;\n}\n\nexport type CheckboxStylesProp = StylesProp<CheckboxStyleSlots>;\n\nconst resolveCheckboxBaseStyles = createStylesResolver([\n \"root\",\n \"checkbox\",\n \"icon-checkmark\",\n \"icon-indeterminate\",\n \"label\",\n \"helper-text\",\n] as const);\n\nfunction resolveCheckboxStyles(styles: CheckboxStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveCheckboxBaseStyles(styles);\n const { root, checkbox, icon, label } = styles;\n\n let iconCheckmark: StyleValue | undefined = styles[\"icon-checkmark\"];\n let iconIndeterminate: StyleValue | undefined = styles[\"icon-indeterminate\"];\n\n if (icon) {\n if (typeof icon === \"string\" || Array.isArray(icon)) {\n iconCheckmark = cn(icon, iconCheckmark);\n iconIndeterminate = cn(icon, iconIndeterminate);\n } else {\n iconCheckmark = cn(icon.checkmark, iconCheckmark);\n iconIndeterminate = cn(icon.indeterminate, iconIndeterminate);\n }\n }\n\n return resolveCheckboxBaseStyles({\n root,\n checkbox,\n \"icon-checkmark\": iconCheckmark,\n \"icon-indeterminate\": iconIndeterminate,\n label,\n \"helper-text\": styles[\"helper-text\"],\n });\n}\n\nexport interface CheckboxProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\"> {\n /** Label text or element displayed next to the checkbox */\n label?: React.ReactNode;\n /** Helper text shown below the checkbox. Prefer `helper`; `helperText` is kept as a compatibility alias. */\n helper?: React.ReactNode;\n /** Compatibility alias for `helper`. */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error and mark the checkbox invalid. */\n helperTextError?: boolean;\n /** Whether the checkbox is invalid. Prefer `error`; `isInvalid` is an alias for form libraries. */\n error?: boolean;\n /** Alias for `error`. */\n isInvalid?: boolean;\n /** Whether to show an indeterminate (partial selection) state. Prefer `indeterminate`; `isIndeterminate` is kept as an alias. */\n isIndeterminate?: boolean;\n /** Whether to show an indeterminate (partial selection) state. */\n indeterminate?: boolean;\n /** Ref for the underlying input. The forwarded ref remains attached to the wrapper element. */\n inputRef?: React.Ref<HTMLInputElement>;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: CheckboxStylesProp;\n}\n\nexport const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(\n (\n {\n className,\n label,\n helper,\n helperText,\n helperTextError = false,\n error = false,\n isInvalid = false,\n id,\n disabled = false,\n checked,\n defaultChecked,\n onChange,\n isIndeterminate = false,\n indeterminate = false,\n inputRef: forwardedInputRef,\n styles,\n ...props\n },\n ref\n ) => {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const generatedId = useId();\n const inputId = id ?? `checkbox-${generatedId}`;\n const helperId = `${inputId}-helper`;\n const resolvedHelper = helper ?? helperText;\n const resolvedIndeterminate = indeterminate || isIndeterminate;\n // Track pressed state for tactile feedback animation (data-pressed attribute)\n const [isPressed, setIsPressed] = useState(false);\n const [internalChecked, setInternalChecked] = useState(() =>\n checked !== undefined ? checked : (defaultChecked ?? false)\n );\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-checkbox-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n\n // React Aria press state handlers for tactile scale animation (mouse)\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n if (!disabled) {\n setIsPressed(true);\n }\n props.onMouseDown?.(e);\n }, [disabled, props]);\n\n const handleMouseUp = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n setIsPressed(false);\n props.onMouseUp?.(e);\n }, [props]);\n\n const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLInputElement>) => {\n setIsPressed(false);\n props.onMouseLeave?.(e);\n }, [props]);\n\n // React Aria press state handlers for keyboard interactions (Space/Enter)\n const handleKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (!disabled && (e.key === \" \" || e.key === \"Enter\")) {\n setIsPressed(true);\n }\n props.onKeyDown?.(e);\n }, [disabled, props]);\n\n const handleKeyUp = React.useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n setIsPressed(false);\n }\n props.onKeyUp?.(e);\n }, [props]);\n\n React.useEffect(() => {\n if (checked !== undefined) {\n setInternalChecked(checked);\n }\n }, [checked]);\n\n React.useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = resolvedIndeterminate;\n }\n }, [resolvedIndeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n // Update internal state (needed for uncontrolled mode)\n setInternalChecked(e.target.checked);\n // Call parent handler if provided\n onChange?.(e);\n };\n\n const inputProps = mergeProps(props, focusProps, {\n onChange: handleChange,\n onMouseDown: handleMouseDown,\n onMouseUp: handleMouseUp,\n onMouseLeave: handleMouseLeave,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }) as React.InputHTMLAttributes<HTMLInputElement>;\n\n // Determine if this is a controlled component\n const isControlled = checked !== undefined;\n const displayChecked = isControlled ? checked : internalChecked;\n const propAriaInvalid = props[\"aria-invalid\"];\n const resolvedInvalid =\n error ||\n isInvalid ||\n helperTextError ||\n propAriaInvalid === true ||\n propAriaInvalid === \"true\";\n const describedBy = [props[\"aria-describedby\"], resolvedHelper ? helperId : undefined]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n const resolved = resolveCheckboxStyles(styles);\n const mergedRootRef = useMergeRefs(rootRef, ref);\n const mergedInputRef = useMergeRefs(inputRef, forwardedInputRef);\n\n return (\n <div\n ref={mergedRootRef}\n className={cn(\"checkbox\", scopeProps.className, css.checkbox, resolved.root)}\n data-disabled={disabled ? \"true\" : undefined}\n data-invalid={resolvedInvalid ? \"true\" : undefined}\n data-indeterminate={resolvedIndeterminate ? \"true\" : undefined}\n data-selected={displayChecked ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div className={cn(css.container)}>\n <input\n {...inputProps}\n ref={mergedInputRef}\n type=\"checkbox\"\n id={inputId}\n disabled={disabled}\n {...(isControlled ? { checked } : { defaultChecked: internalChecked })}\n className={cn(\n css.box,\n className,\n resolved.checkbox\n )}\n data-selected={displayChecked ? \"true\" : undefined}\n data-disabled={disabled ? \"true\" : undefined}\n data-invalid={resolvedInvalid ? \"true\" : undefined}\n data-error={resolvedInvalid ? \"true\" : undefined}\n data-indeterminate={resolvedIndeterminate ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : undefined}\n data-checkbox-focus-surface=\"true\"\n aria-invalid={resolvedInvalid || undefined}\n aria-checked={resolvedIndeterminate ? \"mixed\" : props[\"aria-checked\"]}\n aria-describedby={describedBy}\n />\n {displayChecked && !resolvedIndeterminate && (\n <svg\n className={cn('checkmark', css.checkmark, resolved[\"icon-checkmark\"])}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n )}\n {resolvedIndeterminate && (\n <svg\n className={cn('indeterminate', css.indeterminate, resolved[\"icon-indeterminate\"])}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n )}\n </div>\n {label && (\n <label\n htmlFor={inputId}\n className={cn(\n css.label,\n css[\"label-md\"],\n resolved.label\n )}\n data-disabled={disabled ? \"true\" : undefined}\n >\n {label}\n </label>\n )}\n {resolvedHelper && (\n <p\n id={helperId}\n className={cn(\n css[\"helper-text\"],\n resolved[\"helper-text\"]\n )}\n data-error={resolvedInvalid ? \"true\" : undefined}\n >\n {resolvedHelper}\n </p>\n )}\n </div>\n );\n }\n);\n\nCheckbox.displayName = \"Checkbox\";\n",
|
|
4915
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .checkbox {\n @apply inline-grid gap-x-3;\n grid-template-columns: auto 1fr;\n grid-template-rows: auto auto;\n }\n\n .container {\n @apply relative inline-flex items-center justify-center;\n }\n\n .box {\n @apply relative h-5 w-5 cursor-pointer appearance-none;\n\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-xs, 0.25rem);\n outline: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:hover:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-invalid=\"true\"] {\n border-color: var(--background-error-border, var(--danger-600));\n }\n\n &[data-invalid=\"true\"][data-selected=\"true\"],\n &[data-invalid=\"true\"][data-indeterminate=\"true\"] {\n border-color: var(--background-border);\n }\n\n &[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n }\n\n .checkmark,\n .indeterminate {\n @apply absolute;\n inset: 50%;\n width: 65%;\n height: 65%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n animation: checkbox-icon-pop 200ms var(--ease-snappy-pop, ease-out);\n color: var(--foreground);\n pointer-events: none;\n }\n\n @keyframes checkbox-icon-pop {\n from {\n transform: translate(-50%, -50%) scale(0);\n }\n\n to {\n transform: translate(-50%, -50%) scale(1);\n }\n }\n\n .label {\n @apply cursor-pointer select-none;\n transition: color 200ms var(--ease-snappy-pop);\n\n &[data-disabled=\"true\"] {\n @apply opacity-60 cursor-not-allowed;\n }\n }\n\n .label-md {\n font-size: var(--text-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n }\n\n .helper-text {\n @apply text-xs;\n grid-column: 2;\n transition: color 200ms var(--ease-snappy-pop);\n color: var(--helper-foreground);\n\n &[data-error=\"true\"] {\n color: var(--helper-error-foreground, var(--foreground-error, var(--danger-600)));\n }\n }\n}\n",
|
|
4916
|
+
"cssTypes": "declare const styles: {\n \"checkbox-root\": string;\n container: string;\n checkbox: string;\n box: string;\n checkmark: string;\n indeterminate: string;\n label: string;\n \"label-md\": string;\n \"helper-text\": string;\n};\n\nexport default styles;\n"
|
|
5004
4917
|
},
|
|
5005
4918
|
"code": {
|
|
5006
4919
|
"tsx": "'use client';\n\nimport { useEffect, useRef, useState, useCallback } from \"react\";\nimport { codeToHtml } from \"shiki\";\nimport { transformerRenderIndentGuides } from \"@shikijs/transformers\";\nimport { Copy, Check, ChevronDown } from \"lucide-react\";\nimport { cn, type StyleValue } from \"../../lib/utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport styles from \"./Code.module.css\";\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"']/g, c => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' }[c] || c));\n\nfunction generateFallbackHtml(code: string): string {\n return `<pre><code style=\"display: block; padding: 1rem\">${escapeHtml(code)}</code></pre>`;\n}\n\nfunction useColorScheme(colorScheme: 'light' | 'dark' | 'system'): 'light' | 'dark' {\n const [systemMode, setSystemMode] = useState<'light' | 'dark'>(() => {\n if (typeof window === 'undefined') return 'dark';\n const domTheme = document.documentElement.getAttribute('data-theme');\n if (domTheme === 'light' || domTheme === 'dark') return domTheme;\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n });\n\n useEffect(() => {\n if (colorScheme !== 'system') return;\n\n const update = () => {\n const domTheme = document.documentElement.getAttribute('data-theme');\n if (domTheme === 'light' || domTheme === 'dark') {\n setSystemMode(domTheme);\n } else {\n setSystemMode(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');\n }\n };\n\n const observer = new MutationObserver(update);\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });\n\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n mq.addEventListener('change', update);\n\n return () => {\n observer.disconnect();\n mq.removeEventListener('change', update);\n };\n }, [colorScheme]);\n\n return colorScheme === 'system' ? systemMode : colorScheme;\n}\n\nfunction CopyButton({ code }: { code: string }) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 1800);\n };\n\n return (\n <button onClick={handleCopy} className={styles['copy-button']}>\n {copied ? <Check size={14} /> : <Copy size={14} />}\n </button>\n );\n}\n\nexport interface CodeProps {\n children: string;\n /** Programming language for syntax highlighting */\n language?: string;\n /** Additional CSS class names */\n className?: string;\n /** Filename displayed in the header bar */\n filename?: string;\n /** Custom heading text displayed in the header bar instead of filename */\n heading?: string;\n /** Shiki theme name or separate light/dark theme names */\n theme?: string | { light: string; dark: string };\n /** Color scheme used for theme selection; 'system' follows the page data-theme attribute */\n colorScheme?: 'light' | 'dark' | 'system';\n /** Pre-highlighted HTML string for light mode to skip client-side Shiki processing */\n preHighlightedLight?: string;\n /** Pre-highlighted HTML string for dark mode to skip client-side Shiki processing */\n preHighlightedDark?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: CodeStylesProp;\n}\n\nexport interface CodeStyleSlots {\n root?: StyleValue;\n header?: StyleValue;\n body?: StyleValue;\n viewport?: StyleValue;\n}\n\nexport type CodeStylesProp = StylesProp<CodeStyleSlots>;\n\nconst resolveCodeStyles = createStylesResolver(['root', 'header', 'body', 'viewport'] as const);\n\nconst MAX_HEIGHT_LINES = 20;\n\nexport function Code({\n children,\n language = \"ts\",\n className,\n filename,\n heading,\n theme,\n colorScheme = 'system',\n preHighlightedLight,\n preHighlightedDark,\n styles: stylesProp,\n}: CodeProps) {\n const mode = useColorScheme(colorScheme);\n\n const lightTheme = typeof theme === 'string' ? theme : (theme?.light ?? 'github-light');\n const darkTheme = typeof theme === 'string' ? theme : (theme?.dark ?? 'github-dark');\n const activeTheme = mode === 'light' ? lightTheme : darkTheme;\n\n const viewportRef = useRef<HTMLDivElement>(null);\n const scrollTrackRef = useRef<HTMLDivElement>(null);\n\n const [highlightedCode, setHighlightedCode] = useState<string>(() => {\n if (mode === 'light' && preHighlightedLight) return preHighlightedLight;\n if (mode === 'dark' && preHighlightedDark) return preHighlightedDark;\n if (preHighlightedLight) return preHighlightedLight;\n return generateFallbackHtml(children);\n });\n\n const [contentScrollWidth, setContentScrollWidth] = useState(0);\n const [viewportWidth, setViewportWidth] = useState(0);\n const [isExpanded, setIsExpanded] = useState(false);\n const [totalCodeLines, setTotalCodeLines] = useState(0);\n\n const handleScrollTrack = useCallback(() => {\n if (viewportRef.current && scrollTrackRef.current) {\n viewportRef.current.scrollLeft = scrollTrackRef.current.scrollLeft;\n }\n }, []);\n\n const handleScrollViewport = useCallback(() => {\n if (viewportRef.current && scrollTrackRef.current) {\n const diff = Math.abs(scrollTrackRef.current.scrollLeft - viewportRef.current.scrollLeft);\n if (diff > 1) scrollTrackRef.current.scrollLeft = viewportRef.current.scrollLeft;\n }\n }, []);\n\n const handleWheel = useCallback((e: React.WheelEvent) => {\n if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {\n if (viewportRef.current) {\n viewportRef.current.scrollLeft += e.deltaX;\n e.preventDefault();\n }\n }\n }, []);\n\n useEffect(() => {\n if (mode === 'light' && preHighlightedLight) { setHighlightedCode(preHighlightedLight); return; }\n if (mode === 'dark' && preHighlightedDark) { setHighlightedCode(preHighlightedDark); return; }\n\n const highlight = async () => {\n try {\n const html = await codeToHtml(children, {\n lang: language as any,\n theme: activeTheme,\n transformers: [transformerRenderIndentGuides()],\n });\n let styledHtml = html.replace(/<code>/, '<code style=\"display: block; padding: 1rem;\">');\n styledHtml = styledHtml.replace(/background-color:\\s*[^;]+;?/g, '');\n setHighlightedCode(styledHtml);\n } catch {\n setHighlightedCode(generateFallbackHtml(children));\n }\n };\n\n highlight();\n }, [children, language, mode, activeTheme, preHighlightedLight, preHighlightedDark]);\n\n useEffect(() => {\n const measure = () => {\n if (viewportRef.current) {\n setContentScrollWidth(viewportRef.current.scrollWidth);\n setViewportWidth(viewportRef.current.clientWidth);\n }\n };\n measure();\n const observer = new ResizeObserver(measure);\n if (viewportRef.current) observer.observe(viewportRef.current);\n return () => observer.disconnect();\n }, [highlightedCode]);\n\n useEffect(() => {\n setTotalCodeLines(children.split('\\n').length);\n }, [children]);\n\n useEffect(() => {\n if (totalCodeLines > MAX_HEIGHT_LINES) {\n setIsExpanded(totalCodeLines - MAX_HEIGHT_LINES < 30);\n } else {\n setIsExpanded(false);\n }\n }, [totalCodeLines]);\n\n const hasHorizontalOverflow = contentScrollWidth > viewportWidth;\n const hiddenCodeLines = totalCodeLines - MAX_HEIGHT_LINES;\n const shouldShowExpandButton = totalCodeLines > MAX_HEIGHT_LINES && hiddenCodeLines >= 30;\n\n const resolved = resolveCodeStyles(stylesProp);\n\n return (\n <div className={cn(styles['code'], resolved.root, className)}>\n {(filename || heading) && (\n <div className={cn(styles.header, resolved.header)}>\n <span>{heading || filename}</span>\n {!heading && <span className={styles['header-lang']}>{language}</span>}\n </div>\n )}\n\n <div className={cn(styles.body, resolved.body)}>\n <CopyButton code={children} />\n <div\n ref={viewportRef}\n onScroll={handleScrollViewport}\n onWheel={handleWheel}\n className={cn(styles.viewport, resolved.viewport)}\n style={{\n overflowY: isExpanded ? 'auto' : 'hidden',\n maskImage: !isExpanded && shouldShowExpandButton\n ? 'linear-gradient(to bottom, black 0%, black 70%, transparent 100%)'\n : 'none',\n WebkitMaskImage: !isExpanded && shouldShowExpandButton\n ? 'linear-gradient(to bottom, black 0%, black 70%, transparent 100%)'\n : 'none',\n }}\n dangerouslySetInnerHTML={{ __html: highlightedCode }}\n />\n\n {hasHorizontalOverflow && (\n <div ref={scrollTrackRef} onScroll={handleScrollTrack} className={styles['scroll-track']}>\n <div style={{ width: contentScrollWidth, height: '12px' }} />\n </div>\n )}\n\n {shouldShowExpandButton && !isExpanded && (\n <button onClick={() => setIsExpanded(true)} className={styles['expand-button']}>\n <ChevronDown size={14} className={styles['expand-icon']} />\n Show {hiddenCodeLines} more lines\n </button>\n )}\n </div>\n </div>\n );\n}\n",
|
|
@@ -5014,7 +4927,7 @@ export const generatedSourceCode = {
|
|
|
5014
4927
|
},
|
|
5015
4928
|
"command": {
|
|
5016
4929
|
"tsx": "\"use client\";\n\nimport * as React from \"react\"\n\nimport { createPortal } from \"react-dom\";\n\nimport { useDialog } from \"@react-aria/dialog\";\nimport { FocusScope } from \"@react-aria/focus\";\n\nimport { useOverlayTriggerState } from \"@react-stately/overlays\";\n\nimport { filterDOMProps } from \"@react-aria/utils\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Search } from \"lucide-react\";\nimport { useScrollLock } from \"../../hooks/useScrollLock\";\n\nimport { Card } from \"../Card\";\nimport { Scroll } from \"../Scroll\";\nimport { Badge } from \"../Badge\";\nimport { Input, type InputProps } from \"../Input\";\n\nimport type { Key } from \"react-aria\";\nimport styles from \"./Command.module.css\";\n\ninterface CommandStyleSlots {\n root?: StyleValue;\n overlay?: StyleValue;\n input?: StyleValue;\n list?: StyleValue;\n item?: StyleValue;\n itemContent?: StyleValue;\n footer?: StyleValue;\n}\n\ntype CommandStylesProp = StylesProp<CommandStyleSlots>;\n\nconst resolveCommandBaseStyles = createStylesResolver([\n \"root\",\n \"overlay\",\n \"input\",\n \"list\",\n \"item\",\n \"itemContent\",\n \"footer\",\n] as const);\n\nexport interface CommandItem {\n id: string;\n label: string;\n description?: string;\n category?: string;\n shortcut?: string;\n icon?: React.ReactNode;\n keywords?: string[];\n action: () => void | Promise<void>;\n hint?: string;\n}\n\nexport interface CommandGroupedItems {\n category: string | undefined;\n items: CommandItem[];\n}\n\ninterface CommandContextValue {\n isOpen: boolean;\n close: () => void;\n focusedKey: Key | null;\n setFocusedKey: React.Dispatch<React.SetStateAction<Key | null>>;\n registerItem: (key: Key, textValue: string) => void;\n unregisterItem: (key: Key) => void;\n actionRef: React.MutableRefObject<Map<Key, () => void | Promise<void>>>;\n searchInputRef: React.MutableRefObject<HTMLInputElement | null>;\n scrollableRef: React.MutableRefObject<HTMLDivElement | null>;\n searchValue: string;\n setSearchValue: React.Dispatch<React.SetStateAction<string>>;\n filteredItems: CommandItem[];\n groupedItems: CommandGroupedItems[];\n}\n\nconst CommandContext = React.createContext<CommandContextValue | undefined>(\n undefined,\n);\n\nfunction useCommandContext() {\n const ctx = React.useContext(CommandContext);\n if (!ctx) {\n throw new Error(\"Command sub-components must be used within Command\");\n }\n return ctx;\n}\n\nfunction scoreCommandRelevance(\n text: string,\n query: string,\n): number {\n const t = text.toLowerCase();\n const q = query.toLowerCase();\n\n if (t === q) return 1000;\n if (t.startsWith(q)) return 900;\n if (t.split(/\\s+/).some((word) => word === q)) return 800;\n if (t.includes(q)) {\n const index = t.indexOf(q);\n return 710 - Math.min(index, 10);\n }\n return 0;\n}\n\nexport interface CommandProps {\n /** Whether the command palette is open */\n open?: boolean;\n /** Called when the open state changes */\n onOpenChange?: (open: boolean) => void;\n /** Additional CSS class for the palette dialog */\n className?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, or slot object. */\n styles?: CommandStylesProp;\n /** List of command items to display */\n items?: CommandItem[];\n /** Custom filter function for commands against the query */\n filter?: (command: CommandItem, query: string) => boolean;\n /** Child elements rendered inside the palette */\n children?: React.ReactNode;\n}\n\nconst Command = React.forwardRef<HTMLDivElement, CommandProps>(\n (\n { open = false, onOpenChange, className, styles: commandStyles, items = [], filter, children },\n ref,\n ) => {\n const [mounted, setMounted] = React.useState(false);\n const overlayState = useOverlayTriggerState({\n isOpen: open,\n onOpenChange,\n });\n\n const modalRef = React.useRef<HTMLDivElement>(null);\n const paletteRef = React.useRef<HTMLDivElement>(null);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n const scrollableRef = React.useRef<HTMLDivElement>(null);\n const resolved = resolveCommandBaseStyles(commandStyles);\n\n useScrollLock(overlayState.isOpen, scrollableRef.current);\n const itemsRef = React.useRef<Map<Key, string>>(new Map());\n const actionRef = React.useRef<Map<Key, () => void | Promise<void>>>(\n new Map(),\n );\n const focusedKeyRef = React.useRef<Key | null>(null);\n\n const [focusedKey, setFocusedKey] = React.useState<Key | null>(null);\n const [itemCount, setItemCount] = React.useState(0);\n const [searchValue, setSearchValue] = React.useState(\"\");\n\n const filteredItems = items.filter((cmd) => !filter || filter(cmd, searchValue));\n\n const groupedItems = React.useMemo(() => {\n const groups = new Map<string | undefined, CommandItem[]>();\n filteredItems.forEach((cmd) => {\n const cat = cmd.category;\n if (!groups.has(cat)) {\n groups.set(cat, []);\n }\n groups.get(cat)!.push(cmd);\n });\n\n // Maintain category order from original items\n const categoryOrder = new Map<string | undefined, number>();\n let idx = 0;\n items.forEach((cmd) => {\n if (!categoryOrder.has(cmd.category)) {\n categoryOrder.set(cmd.category, idx++);\n }\n });\n\n return Array.from(groups.entries())\n .sort(\n ([a], [b]) =>\n (categoryOrder.get(a) ?? Infinity) - (categoryOrder.get(b) ?? Infinity),\n )\n .map(([category, items]) => ({ category, items }));\n }, [filteredItems, items]);\n\n React.useImperativeHandle(ref, () => paletteRef.current as HTMLDivElement);\n\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n // Sync focusedKeyRef with focusedKey\n React.useEffect(() => {\n focusedKeyRef.current = focusedKey;\n }, [focusedKey]);\n\n // Auto-focus search input when opening\n React.useEffect(() => {\n if (overlayState.isOpen && searchInputRef.current) {\n setTimeout(() => searchInputRef.current?.focus(), 0);\n }\n }, [overlayState.isOpen]);\n\n // Cleanup state when overlay closes\n React.useEffect(() => {\n if (!overlayState.isOpen) {\n scrollableRef.current = null;\n setSearchValue(\"\");\n }\n }, [overlayState.isOpen]);\n\n // Cmd+K global listener\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n const isMac =\n navigator.platform.toUpperCase().indexOf(\"MAC\") >= 0 ||\n navigator.userAgent.indexOf(\"Mac\") !== -1;\n const isCommandKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (isCommandKey && event.key === \"k\") {\n event.preventDefault();\n overlayState.open();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [overlayState]);\n\n // Auto-focus first item when items change (filtering, opening)\n React.useEffect(() => {\n if (!overlayState.isOpen) return;\n\n if (!searchValue) {\n setFocusedKey(null);\n return;\n }\n\n const keys = Array.from(itemsRef.current.keys());\n if (keys.length > 0) {\n setFocusedKey(keys[0]);\n } else {\n setFocusedKey(null);\n }\n }, [itemCount, overlayState.isOpen, searchValue]);\n\n // Keyboard navigation\n React.useEffect(() => {\n if (!overlayState.isOpen) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n const keys = Array.from(itemsRef.current.keys());\n if (keys.length === 0) return;\n if (focusedKey === null) {\n setFocusedKey(keys[0]);\n } else {\n const idx = keys.indexOf(focusedKey);\n setFocusedKey(keys[(idx + 1) % keys.length]);\n }\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n const keys = Array.from(itemsRef.current.keys());\n if (keys.length === 0) return;\n if (focusedKey === null) {\n setFocusedKey(keys[keys.length - 1]);\n } else {\n const idx = keys.indexOf(focusedKey);\n setFocusedKey(keys[idx === 0 ? keys.length - 1 : idx - 1]);\n }\n break;\n }\n case \"Enter\": {\n event.preventDefault();\n if (focusedKey !== null) {\n const action = actionRef.current.get(focusedKey);\n if (action) {\n action();\n overlayState.close();\n }\n }\n break;\n }\n case \"Escape\": {\n event.preventDefault();\n overlayState.close();\n break;\n }\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [overlayState.isOpen, focusedKey]);\n\n const registerItem = React.useCallback((key: Key, textValue: string) => {\n itemsRef.current.set(key, textValue);\n setItemCount((c) => c + 1);\n }, []);\n\n const unregisterItem = React.useCallback((key: Key) => {\n itemsRef.current.delete(key);\n setItemCount((c) => c + 1);\n }, []);\n\n // Click outside to close\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (e.target === e.currentTarget) {\n overlayState.close();\n }\n },\n [overlayState],\n );\n\n const { dialogProps } = useDialog(\n { \"aria-label\": \"Command palette\" },\n modalRef,\n );\n\n if (!mounted || !overlayState.isOpen) {\n return null;\n }\n\n return createPortal(\n <FocusScope contain restoreFocus>\n <div\n className={cn(\n \"command\",\n styles[\"overlay\"],\n resolved.overlay,\n )}\n onClick={handleOverlayClick}\n >\n <Card\n {...filterDOMProps(dialogProps)}\n ref={modalRef}\n className={cn(\"content\", styles[\"content\"], className, resolved.root)}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <CommandContext.Provider\n value={{\n isOpen: overlayState.isOpen,\n close: overlayState.close,\n focusedKey,\n setFocusedKey,\n registerItem,\n unregisterItem,\n actionRef,\n searchInputRef,\n scrollableRef,\n searchValue,\n setSearchValue,\n filteredItems,\n groupedItems,\n }}\n >\n {children}\n </CommandContext.Provider>\n </Card>\n </div>\n </FocusScope>,\n document.body,\n );\n },\n);\n\nCommand.displayName = \"Command\";\n\ninterface CommandInputProps extends InputProps { }\n\nconst CommandInput = React.forwardRef<HTMLInputElement, CommandInputProps>(\n ({ value: externalValue, onChange: externalOnChange, icon, actions, placeholder = \"Search...\", ...props }, ref) => {\n const { searchInputRef, searchValue, setSearchValue } = useCommandContext();\n\n const value = externalValue !== undefined ? externalValue : searchValue;\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchValue(e.target.value);\n externalOnChange?.(e);\n };\n\n const inputRef = (ref ?? searchInputRef) as React.RefObject<HTMLInputElement>;\n\n const resolvedActions = actions ?? (value ? [{ icon: <>✕</>, title: \"Clear search\", onClick: () => { setSearchValue(\"\"); } }] : []);\n\n return (\n <Card.Header className={styles[\"search\"]}>\n <Input\n ref={inputRef}\n value={value as string}\n onChange={handleChange}\n icon={icon ?? <Search className=\"w-4 h-4\" />}\n actions={resolvedActions}\n placeholder={placeholder}\n aria-label=\"Search commands\"\n styles={{ root: styles[\"input\"] }}\n {...props}\n />\n </Card.Header>\n );\n }\n);\n\nCommandInput.displayName = \"Command.Input\";\n\ninterface CommandListProps {\n /** Child elements rendered inside the list */\n children?: React.ReactNode;\n /** Message shown when no items match the search */\n emptyMessage?: string;\n /** Additional CSS class for the list container */\n className?: string;\n}\n\n/** Scrollable container that renders the filtered command items */\nconst CommandListComponent = React.forwardRef<\n HTMLDivElement,\n CommandListProps\n>(({ children, emptyMessage = \"No items found.\", className }, ref) => {\n const { scrollableRef } = useCommandContext();\n\n return (\n <div className={cn(styles[\"inner\"], className)}>\n <Scroll\n ref={useMergeRefs(ref, scrollableRef)}\n className={styles[\"list\"]}\n maxHeight=\"44dvh\"\n fade-y\n >\n <div role=\"listbox\" aria-label=\"Commands\">\n {!children ? (\n <div className={styles[\"empty\"]}>{emptyMessage}</div>\n ) : (\n children\n )}\n </div>\n </Scroll>\n </div>\n );\n});\n\nCommandListComponent.displayName = \"Command.List\";\n\ninterface CommandItemProps {\n /** Unique key identifying this command item */\n value: Key;\n /** Plain-text label used for keyboard navigation lookup */\n textValue: string;\n /** Called when the item is selected */\n action: () => void | Promise<void>;\n /** Child elements rendered inside the item */\n children?: React.ReactNode;\n /** Additional CSS class for the item */\n className?: string;\n /** Keyboard shortcut or hint text rendered as a Badge at the end of the command item */\n hint?: string;\n}\n\nconst CommandItem = React.forwardRef<HTMLDivElement, CommandItemProps>(\n ({ value, textValue, action, children, className, hint }, ref) => {\n const { focusedKey, registerItem, unregisterItem, actionRef, close } =\n useCommandContext();\n\n React.useEffect(() => {\n registerItem(value, textValue);\n actionRef.current.set(value, action);\n return () => {\n unregisterItem(value);\n actionRef.current.delete(value);\n };\n }, [value, textValue, action, registerItem, unregisterItem, actionRef]);\n\n const isHighlighted = focusedKey === value;\n\n return (\n <div\n ref={ref}\n data-highlighted={isHighlighted}\n role=\"option\"\n aria-selected={isHighlighted}\n onClick={() => { action(); close(); }}\n className={cn(\"item\", styles[\"item\"], className)}\n >\n <div className={styles[\"item-content\"]}>{children}</div>\n {hint && (\n <Badge variant=\"secondary\" className={styles[\"hint-wrapper\"]}>\n {hint}\n </Badge>\n )}\n </div>\n );\n },\n);\n\nCommandItem.displayName = \"Command.Item\";\n\ninterface CommandCategoryProps {\n /** Child elements rendered inside the category header */\n children?: React.ReactNode;\n /** Additional CSS class for the category */\n className?: string;\n}\n\n/** Labeled section grouping related commands */\nconst CommandCategory = React.forwardRef<\n HTMLDivElement,\n CommandCategoryProps\n>(({ children, className }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(styles[\"category-header\"], className)}\n >\n {children}\n </div>\n );\n});\n\nCommandCategory.displayName = \"Command.Category\";\n\ninterface CommandFooterProps {\n /** Child elements rendered inside the footer */\n children?: React.ReactNode;\n /** Additional CSS class applied to the footer */\n className?: string;\n}\n\n/** Fixed bottom bar in the command palette for hints or actions */\nconst CommandFooter = React.forwardRef<HTMLDivElement, CommandFooterProps>(\n ({ children, className }, ref) => {\n return (\n <Card.Footer ref={ref} className={cn(styles[\"footer\"], className)}>\n {children}\n </Card.Footer>\n );\n },\n);\n\nCommandFooter.displayName = \"Command.Footer\";\n\nexport interface CommandGroupsProps {\n /** Renders a category header for the given category name */\n renderCategory?: (category: string | undefined) => React.ReactNode;\n /** Renders a single command item row */\n renderItem: (command: CommandItem, hint?: string) => React.ReactNode;\n /** Additional CSS class for the groups container */\n className?: string;\n}\n\n/** Wrapper that renders multiple Command.Category sections */\nconst CommandGroups = React.forwardRef<HTMLDivElement, CommandGroupsProps>(\n ({ renderCategory, renderItem, className }, ref) => {\n const { groupedItems } = useCommandContext();\n\n return (\n <div ref={ref} className={className}>\n {groupedItems.map(({ category, items }) => (\n <div key={category || \"uncategorized\"}>\n {renderCategory && renderCategory(category)}\n {items.map((cmd) => (\n <React.Fragment key={cmd.id}>{renderItem(cmd, cmd.hint)}</React.Fragment>\n ))}\n </div>\n ))}\n </div>\n );\n },\n);\n\nCommandGroups.displayName = \"Command.Groups\";\n\ninterface CommandComponent\n extends React.ForwardRefExoticComponent<\n CommandProps & React.RefAttributes<HTMLDivElement>\n > {\n Input: typeof CommandInput;\n List: typeof CommandListComponent;\n Item: typeof CommandItem;\n Category: typeof CommandCategory;\n Footer: typeof CommandFooter;\n Groups: typeof CommandGroups;\n}\n\nconst CommandWithSubcomponents = Object.assign(Command, {\n Input: CommandInput,\n List: CommandListComponent,\n Item: CommandItem,\n Category: CommandCategory,\n Footer: CommandFooter,\n Groups: CommandGroups,\n}) as CommandComponent;\n\nexport { CommandWithSubcomponents as Command };\nexport { scoreCommandRelevance };\nexport { useCommandContext };\n",
|
|
5017
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n /* Overlay Container */\n .overlay {\n @apply fixed inset-0 flex items-start justify-center overflow-hidden;\n z-index: 999;\n padding-top: 20vh;\n /* Apply backdrop styles directly to avoid creating a containing block that disrupts sticky elements */\n background-color: var(--overlay);\n backdrop-filter: var(--overlay-backdrop);\n }\n\n /* Content */\n .content {\n @apply relative m-2 w-full max-w-[28rem];\n border-radius: var(--radius-sm);\n background: var(--background);\n margin-inline: 1rem;\n box-shadow: var(--shadow);\n animation: fade-in-zoom-in 0.2s ease-out;\n }\n\n .inner {\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n border-top: var(--border-width-base) solid var(--border);\n @apply overflow-hidden;\n }\n\n /* Search Section */\n .search {\n @apply border-none flex p-1.5;\n --input-active-border-color: transparent;\n --input-active-box-shadow: none;\n }\n\n .input {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n\n &[data-active],\n &[data-focus-visible] {\n border-color: transparent;\n box-shadow: none;\n }\n }\n\n /* List Section */\n .list {\n @apply py-0.5 px-2 space-y-2;\n background-color: var(--background-list);\n }\n\n .list :global([role=\"listbox\"]) {\n @apply flex w-full flex-col;\n }\n\n .item {\n @apply flex items-center justify-between rounded-sm px-2 py-0.5 cursor-pointer;\n border-radius: 0.375rem;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n color: var(--foreground);\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n
|
|
4930
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n /* Overlay Container */\n .overlay {\n @apply fixed inset-0 flex items-start justify-center overflow-hidden;\n z-index: 999;\n padding-top: 20vh;\n /* Apply backdrop styles directly to avoid creating a containing block that disrupts sticky elements */\n background-color: var(--overlay);\n backdrop-filter: var(--overlay-backdrop);\n }\n\n /* Content */\n .content {\n @apply relative m-2 w-full max-w-[28rem];\n border-radius: var(--radius-sm);\n background: var(--background);\n margin-inline: 1rem;\n box-shadow: var(--shadow);\n animation: fade-in-zoom-in 0.2s ease-out;\n }\n\n .inner {\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n border-top: var(--border-width-base) solid var(--border);\n @apply overflow-hidden;\n }\n\n /* Search Section */\n .search {\n @apply border-none flex p-1.5;\n --input-active-border-color: transparent;\n --input-active-box-shadow: none;\n }\n\n .input {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n\n &[data-active],\n &[data-focus-visible] {\n border-color: transparent;\n box-shadow: none;\n }\n }\n\n /* List Section */\n .list {\n @apply py-0.5 px-2 space-y-2;\n background-color: var(--background-list);\n }\n\n .list :global([role=\"listbox\"]) {\n @apply flex w-full flex-col;\n }\n\n .item {\n @apply flex items-center justify-between rounded-sm px-2 py-0.5 cursor-pointer;\n border-radius: 0.375rem;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item-content {\n @apply flex min-w-0 flex-1 items-center gap-2.5;\n flex: 1;\n }\n\n .item-icon {\n @apply flex h-6 w-6 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .item-labels {\n flex: 1;\n @apply min-w-0;\n }\n\n .item-label {\n font-size: var(--text-sm);\n color: var(--foreground);\n font-weight: var(--font-weight-medium);\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n color: var(--foreground-muted);\n font-size: 0.875rem;\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .hint-wrapper {\n @apply flex items-center;\n }\n\n .category-header {\n @apply px-2 py-1.5 mt-2 first:mt-0;\n font-size: var(--text-sm);\n font-weight: var(--font-weight-semibold);\n color: var(--foreground-muted);\n }\n\n /* Empty State */\n .empty {\n padding: 1.5rem 1rem;\n text-align: center;\n font-size: 0.875rem;\n color: var(--foreground-muted);\n }\n\n /* Footer */\n .footer {\n @apply flex w-full items-center gap-2 px-1.5 py-2;\n background-color: var(--background-footer);\n border-top: 1px solid var(--border);\n justify-content: flex-between;\n }\n\n /* Animations */\n @keyframes fade-in-zoom-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }\n}\n",
|
|
5018
4931
|
"cssTypes": "export interface Styles {\n overlay: string;\n content: string;\n inner: string;\n search: string;\n input: string;\n list: string;\n item: string;\n \"item-content\": string;\n \"item-icon\": string;\n \"item-labels\": string;\n \"item-label\": string;\n \"item-description\": string;\n \"category-header\": string;\n empty: string;\n footer: string;\n \"hint-wrapper\": string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
5019
4932
|
},
|
|
5020
4933
|
"confirm": {
|
|
@@ -5023,8 +4936,8 @@ export const generatedSourceCode = {
|
|
|
5023
4936
|
"cssTypes": "export interface Styles {\n confirm: string;\n container: string;\n card: string;\n body: string;\n \"body-compact\": string;\n \"dialog-overlay\": string;\n \"dialog-card\": string;\n header: string;\n \"header-content\": string;\n \"header-title\": string;\n description: string;\n \"error-message\": string;\n \"warning-box\": string;\n \"warning-box-low\": string;\n \"warning-box-medium\": string;\n \"warning-box-high\": string;\n \"warning-box-critical\": string;\n \"countdown-text\": string;\n \"input-label\": string;\n input: string;\n actions: string;\n \"actions-inline\": string;\n \"actions-dialog\": string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
5024
4937
|
},
|
|
5025
4938
|
"date": {
|
|
5026
|
-
"tsx": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\n\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\n\nimport { type StyleValue, cn } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { asElementProps } from \"@/lib/react-aria\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\n\nimport dateModuleStyles from \"./Date.module.css\"\n\n// Alias global Date to avoid shadowing by component name\nconst NativeDate = globalThis.Date;\n\ninterface DateStyleSlots {\n root?: StyleValue;\n header?: StyleValue;\n \"day-headers\"?: StyleValue;\n grid?: StyleValue;\n \"day-cell\"?: StyleValue; // individual date button\n}\n\ntype DateStylesProp = StylesProp<DateStyleSlots>;\n\nconst dateStyleSlotKeys = ['root', 'header', 'day-headers', 'grid', 'day-cell'] as const;\nconst resolveDateBaseStyles = createStylesResolver(dateStyleSlotKeys);\n\nfunction normalizeDateStyles(styles: DateStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return styles;\n }\n\n return {\n root: styles.root,\n header: styles.header,\n \"day-headers\": styles[\"day-headers\"],\n grid: styles.grid,\n \"day-cell\": styles[\"day-cell\"],\n };\n}\n\n/**\n * Context type for Calendar state management\n */\nexport interface DateContextValue {\n selectedDate: Date | null\n focusedDate: Date | null\n currentMonth: Date | null\n today: Date | null\n selectDate: (date: Date) => void\n focusDate: (date: Date) => void\n navigateMonth: (offset: number) => void\n isDateDisabled: (date: Date) => boolean\n isDateOutOfRange: (date: Date) => boolean\n}\n\nconst DateContext = React.createContext<DateContextValue | null>(null)\n\nfunction useDateContext() {\n const context = React.useContext(DateContext)\n if (!context) {\n throw new Error(\"Date component must be used within Date root\")\n }\n return context\n}\n\n/**\n * Props for Calendar component\n */\nexport interface DateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Controlled selected date */\n value?: Date | null\n /** Called when the user selects a date */\n onChange?: (date: Date) => void\n /** Function returning true for dates that should be unselectable */\n disabled?: (date: Date) => boolean\n /** Earliest selectable date */\n minDate?: Date\n /** Latest selectable date */\n maxDate?: Date\n /** Month shown initially when no date is selected */\n defaultMonth?: Date;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: DateStylesProp;\n}\n\n/**\n * Helper functions for date calculations\n */\nfunction getDaysInMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth() + 1, 0).getDate()\n}\n\nfunction getFirstDayOfMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth(), 1).getDay()\n}\n\nfunction isSameDay(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n )\n}\n\nfunction isToday(date: Date, today: Date | null): boolean {\n if (!today) return false;\n return isSameDay(date, today)\n}\n\n/**\n * Calendar grid computation\n */\nfunction getCalendarGrid(currentMonth: Date | null): Date[][] {\n if (!currentMonth) return [];\n\n const daysInMonth = getDaysInMonth(currentMonth)\n const firstDay = getFirstDayOfMonth(currentMonth)\n\n const grid: Date[] = []\n\n // Handle previous month's days\n if (firstDay > 0) {\n const prevMonth = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), 0)\n const daysInPrevMonth = getDaysInMonth(prevMonth)\n\n for (let i = firstDay - 1; i >= 0; i--) {\n const date = new NativeDate(prevMonth.getFullYear(), prevMonth.getMonth(), daysInPrevMonth - i)\n grid.push(date)\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n grid.push(new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), i))\n }\n\n // Pad with next month's days\n while (grid.length % 7 !== 0) {\n const nextDay = grid.length - firstDay - daysInMonth + 1\n const date = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth() + 1, nextDay)\n grid.push(date)\n }\n\n // Convert to rows\n const rows: Date[][] = []\n for (let i = 0; i < grid.length; i += 7) {\n rows.push(grid.slice(i, i + 7))\n }\n\n return rows\n}\n\nconst Date = React.forwardRef<HTMLDivElement, DateProps>(\n (\n {\n value: controlledValue,\n onChange,\n disabled: disabledProp = () => false,\n minDate,\n maxDate,\n defaultMonth,\n className,\n styles,\n ...props\n },\n ref\n ) => {\n const [uncontrolledValue, setUncontrolledValue] = React.useState<Date | null>(null)\n const [today, setToday] = React.useState<Date | null>(null)\n const [currentMonth, setCurrentMonth] = React.useState<Date | null>(null)\n const [focusedDate, setFocusedDate] = React.useState<Date | null>(null)\n\n const selectedDate = controlledValue !== undefined ? controlledValue : uncontrolledValue\n\n const resolved = resolveDateBaseStyles(normalizeDateStyles(styles));\n\n const isDateDisabled = React.useCallback(\n (date: Date): boolean => {\n if (disabledProp(date)) return true\n if (minDate && date < minDate) return true\n if (maxDate && date > maxDate) return true\n return false\n },\n [disabledProp, minDate, maxDate]\n )\n\n const isDateOutOfRange = React.useCallback(\n (date: Date): boolean => {\n if (!currentMonth) return false;\n return (\n date.getMonth() !== currentMonth.getMonth() ||\n date.getFullYear() !== currentMonth.getFullYear()\n )\n },\n [currentMonth]\n )\n\n const selectDate = React.useCallback(\n (date: Date) => {\n if (!isDateDisabled(date)) {\n if (controlledValue === undefined) {\n setUncontrolledValue(date)\n }\n onChange?.(date)\n setFocusedDate(null)\n }\n },\n [controlledValue, onChange, isDateDisabled]\n )\n\n const focusDate = React.useCallback((date: Date) => {\n setFocusedDate(date)\n }, [])\n\n const navigateMonth = React.useCallback((offset: number) => {\n setCurrentMonth(prev => {\n const baseDate = prev ?? new NativeDate(); // Handle null prev\n const newMonth = new NativeDate(baseDate.getFullYear(), baseDate.getMonth() + offset, 1)\n return newMonth\n })\n }, [])\n\n const calendarGrid = React.useMemo(\n () => currentMonth ? getCalendarGrid(currentMonth) : [],\n [currentMonth]\n )\n\n const contextValue: DateContextValue = React.useMemo(\n () => ({\n selectedDate,\n focusedDate,\n currentMonth,\n today,\n selectDate,\n focusDate,\n navigateMonth,\n isDateDisabled,\n isDateOutOfRange,\n }),\n [selectedDate, focusedDate, currentMonth, today, selectDate, focusDate, navigateMonth, isDateDisabled, isDateOutOfRange]\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (!focusedDate) return\n\n let newFocusedDate: Date | null = null\n\n switch (e.key) {\n case \"ArrowUp\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 7)\n break\n case \"ArrowDown\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 7)\n break\n case \"ArrowLeft\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 1)\n break\n case \"ArrowRight\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 1)\n break\n case \"Home\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), 1)\n break\n case \"End\":\n e.preventDefault()\n const daysInMonth = getDaysInMonth(focusedDate)\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), daysInMonth)\n break\n case \"PageUp\":\n e.preventDefault()\n navigateMonth(-1)\n return\n case \"PageDown\":\n e.preventDefault()\n navigateMonth(1)\n return\n case \"Enter\":\n case \" \":\n e.preventDefault()\n selectDate(focusedDate)\n return\n }\n\n if (newFocusedDate) {\n setFocusedDate(newFocusedDate)\n // Auto-navigate month if needed\n if (newFocusedDate.getMonth() !== currentMonth!.getMonth() || newFocusedDate.getFullYear() !== currentMonth!.getFullYear()) {\n setCurrentMonth(new NativeDate(newFocusedDate.getFullYear(), newFocusedDate.getMonth(), 1))\n }\n }\n },\n [focusedDate, currentMonth, selectDate, navigateMonth]\n )\n\n // Set initial focus, today, and current month on client mount\n React.useEffect(() => {\n const now = new NativeDate()\n setToday(now)\n\n if (currentMonth === null) { // Only set if not yet initialized\n setCurrentMonth(defaultMonth ?? now)\n }\n\n if (focusedDate === null) { // Only set if not yet initialized\n setFocusedDate(selectedDate ?? now)\n }\n }, [defaultMonth, currentMonth, focusedDate, selectedDate]) // Add relevant dependencies\n\n return (\n <DateContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cn(\"date\", dateModuleStyles.calendar, className, resolved.root)}\n role=\"application\"\n aria-label=\"Date picker calendar\"\n onKeyDown={handleKeyDown}\n {...props}\n >\n {currentMonth && (\n <>\n <DateHeader className={resolved.header} />\n <DateDayHeaders className={resolved[\"day-headers\"]} />\n <DateGrid grid={calendarGrid} className={resolved.grid} dayCellClassName={resolved[\"day-cell\"]} />\n </>\n )}\n </div>\n </DateContext.Provider>\n )\n }\n)\n\nDate.displayName = \"Date\"\n\n/**\n * Calendar Header component\n */\ninterface DateHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the header */\n className?: string;\n}\n\n/** Navigation header with month/year display and prev/next controls */\nconst DateHeader = React.forwardRef<HTMLDivElement, DateHeaderProps>(\n ({ className, ...props }, ref) => {\n const { currentMonth, navigateMonth } = useDateContext()\n const { focusProps: prevFocusProps, isFocused: isPrevFocused, isFocusVisible: isPrevFocusVisible } = useFocusRing()\n const { focusProps: nextFocusProps, isFocused: isNextFocused, isFocusVisible: isNextFocusVisible } = useFocusRing()\n const { targetProps: prevTargetProps } = useFocus({ mode: \"target\" })\n const { targetProps: nextTargetProps } = useFocus({ mode: \"target\" })\n\n const monthYear = currentMonth\n ? currentMonth.toLocaleDateString(\"en-US\", {\n month: \"long\",\n year: \"numeric\",\n })\n : \"\"\n\n return (\n <div\n ref={ref}\n className={cn(\"date-header\", dateModuleStyles.header, className)}\n {...props}\n >\n <div className={cn(\"date-month-year\", dateModuleStyles[\"month-year\"])}>\n {monthYear}\n </div>\n <div>\n <button\n {...asElementProps<\"button\">(mergeProps(prevFocusProps, prevTargetProps))}\n onClick={() => navigateMonth(-1)}\n className={cn(\"date-nav-button\", \"date-prev-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Previous month\"\n data-focused={isPrevFocused ? \"true\" : undefined}\n data-focus-visible={isPrevFocusVisible ? \"true\" : undefined}\n >\n <ChevronLeft size={16} />\n </button>\n <button\n {...asElementProps<\"button\">(mergeProps(nextFocusProps, nextTargetProps))}\n onClick={() => navigateMonth(1)}\n className={cn(\"date-nav-button\", \"date-next-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Next month\"\n data-focused={isNextFocused ? \"true\" : undefined}\n data-focus-visible={isNextFocusVisible ? \"true\" : undefined}\n >\n <ChevronRight size={16} />\n </button>\n </div>\n </div>\n )\n }\n)\n\nDateHeader.displayName = \"Date.Header\"\n\n/**\n * Calendar Day Headers component\n */\ninterface DateDayHeadersProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the day headers row */\n className?: string;\n}\n\n/** Row of weekday abbreviation labels above the calendar grid */\nconst DateDayHeaders = React.forwardRef<HTMLDivElement, DateDayHeadersProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"date-day-headers\", dateModuleStyles[\"day-headers\"], className)}\n {...props}\n >\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"date-day-header\", dateModuleStyles[\"day-header\"])}\n >\n {day}\n </div>\n ))}\n </div>\n )\n }\n)\n\nDateDayHeaders.displayName = \"Date.DayHeaders\"\n\n/**\n * Calendar Grid component\n */\ninterface DateGridProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Calendar grid rows, each containing 7 Date objects */\n grid: Date[][]\n /** Classes applied to each individual date cell (DateDay component) */\n dayCellClassName?: string;\n}\n\n/** The 7-column calendar grid containing date cells */\nconst DateGrid = React.forwardRef<HTMLDivElement, DateGridProps>(\n ({ grid, className, dayCellClassName, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"date-grid\", dateModuleStyles.grid, className)}\n role=\"grid\"\n {...props}\n >\n {/* Week headers */}\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"date-day-header\", dateModuleStyles[\"week-header\"])}\n role=\"columnheader\"\n >\n {day}\n </div>\n ))}\n\n {/* Calendar rows */}\n {grid.map((week: Date[], weekIndex: number) => {\n return (\n <React.Fragment key={weekIndex}>\n {week.map((date: Date, dayIndex: number) => (\n <DateDay key={`${weekIndex}-${dayIndex}`} date={date} className={dayCellClassName} />\n ))}\n </React.Fragment>\n )\n })}\n </div>\n )\n }\n)\n\nDateGrid.displayName = \"Date.Grid\"\n\n/**\n * Calendar Day component\n */\ninterface DateDayProps extends React.HTMLAttributes<HTMLButtonElement> {\n /** The date this cell represents */\n date: Date\n}\n/**\n * Individual date cell in the calendar grid\n */\nconst DateDay = React.forwardRef<HTMLButtonElement, DateDayProps>(\n ({ date, className, onClick, ...props }, ref) => {\n const {\n selectedDate,\n focusedDate,\n today,\n selectDate,\n focusDate,\n isDateDisabled,\n isDateOutOfRange,\n } = useDateContext()\n\n const isDisabled = isDateDisabled(date)\n\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(ref, buttonRef)\n const { focusProps, isFocused: isFocusRingFocused, isFocusVisible } = useFocusRing()\n const { hoverProps } = useHover({ isDisabled })\n const { targetProps } = useFocus({ mode: \"target\" })\n\n const isSelected = selectedDate ? isSameDay(date, selectedDate) : false\n const isFocused = focusedDate ? isSameDay(date, focusedDate) : false\n const isCurrentToday = isToday(date, today)\n const isOutOfRange = isDateOutOfRange(date)\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n selectDate(date)\n focusDate(date)\n onClick?.(e)\n },\n [date, selectDate, focusDate, onClick]\n )\n\n const handleFocus = React.useCallback(() => {\n focusDate(date)\n }, [date, focusDate])\n\n React.useEffect(() => {\n if (isFocused && buttonRef.current) {\n buttonRef.current.focus({ preventScroll: true })\n }\n }, [isFocused])\n\n return (\n <button\n ref={mergedRef}\n onClick={handleClick}\n onFocus={handleFocus}\n className={cn(\"date-day\", dateModuleStyles[\"day-cell\"], className)}\n data-ring={targetProps[\"data-ring\"]}\n data-focus-indicator={targetProps[\"data-focus-indicator\"]}\n data-ring-inset={targetProps[\"data-ring-inset\"]}\n data-focused={isFocusRingFocused ? \"true\" : undefined}\n data-selected={isSelected ? \"true\" : undefined}\n data-today={isCurrentToday ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n data-out-of-range={isOutOfRange ? \"true\" : undefined}\n data-focus-visible={isFocusVisible && isFocused ? \"true\" : undefined}\n disabled={isDisabled}\n aria-selected={isSelected}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n {...mergeProps(focusProps, hoverProps, props)}\n >\n {date.getDate()}\n </button>\n )\n }\n)\n\nDateDay.displayName = \"Date.Day\"\n\nexport { Date, DateHeader, DateGrid, DateDay }\n",
|
|
5027
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-
|
|
4939
|
+
"tsx": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\n\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\n\nimport { type StyleValue, cn } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { asElementProps } from \"@/lib/react-aria\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\n\nimport dateModuleStyles from \"./Date.module.css\"\n\n// Alias global Date to avoid shadowing by component name\nconst NativeDate = globalThis.Date;\n\ninterface DateStyleSlots {\n root?: StyleValue;\n header?: StyleValue;\n \"day-headers\"?: StyleValue;\n grid?: StyleValue;\n \"day-cell\"?: StyleValue; // individual date button\n}\n\ntype DateStylesProp = StylesProp<DateStyleSlots>;\n\nconst dateStyleSlotKeys = ['root', 'header', 'day-headers', 'grid', 'day-cell'] as const;\nconst resolveDateBaseStyles = createStylesResolver(dateStyleSlotKeys);\n\nfunction normalizeDateStyles(styles: DateStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return styles;\n }\n\n return {\n root: styles.root,\n header: styles.header,\n \"day-headers\": styles[\"day-headers\"],\n grid: styles.grid,\n \"day-cell\": styles[\"day-cell\"],\n };\n}\n\n/**\n * Context type for Calendar state management\n */\nexport interface DateContextValue {\n selectedDate: Date | null\n focusedDate: Date | null\n currentMonth: Date | null\n today: Date | null\n selectDate: (date: Date) => void\n focusDate: (date: Date) => void\n navigateMonth: (offset: number) => void\n isDateDisabled: (date: Date) => boolean\n isDateOutOfRange: (date: Date) => boolean\n}\n\nconst DateContext = React.createContext<DateContextValue | null>(null)\n\nfunction useDateContext() {\n const context = React.useContext(DateContext)\n if (!context) {\n throw new Error(\"Date component must be used within Date root\")\n }\n return context\n}\n\n/**\n * Props for Calendar component\n */\nexport interface DateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Controlled selected date */\n value?: Date | null\n /** Called when the user selects a date */\n onChange?: (date: Date) => void\n /** Function returning true for dates that should be unselectable */\n disabled?: (date: Date) => boolean\n /** Earliest selectable date */\n minDate?: Date\n /** Latest selectable date */\n maxDate?: Date\n /** Month shown initially when no date is selected */\n defaultMonth?: Date;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: DateStylesProp;\n}\n\n/**\n * Helper functions for date calculations\n */\nfunction getDaysInMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth() + 1, 0).getDate()\n}\n\nfunction getFirstDayOfMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth(), 1).getDay()\n}\n\nfunction isSameDay(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n )\n}\n\nfunction isToday(date: Date, today: Date | null): boolean {\n if (!today) return false;\n return isSameDay(date, today)\n}\n\n/**\n * Calendar grid computation\n */\nfunction getCalendarGrid(currentMonth: Date | null): Date[][] {\n if (!currentMonth) return [];\n\n const daysInMonth = getDaysInMonth(currentMonth)\n const firstDay = getFirstDayOfMonth(currentMonth)\n\n const grid: Date[] = []\n\n // Handle previous month's days\n if (firstDay > 0) {\n const prevMonth = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), 0)\n const daysInPrevMonth = getDaysInMonth(prevMonth)\n\n for (let i = firstDay - 1; i >= 0; i--) {\n const date = new NativeDate(prevMonth.getFullYear(), prevMonth.getMonth(), daysInPrevMonth - i)\n grid.push(date)\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n grid.push(new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), i))\n }\n\n // Pad with next month's days\n while (grid.length % 7 !== 0) {\n const nextDay = grid.length - firstDay - daysInMonth + 1\n const date = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth() + 1, nextDay)\n grid.push(date)\n }\n\n // Convert to rows\n const rows: Date[][] = []\n for (let i = 0; i < grid.length; i += 7) {\n rows.push(grid.slice(i, i + 7))\n }\n\n return rows\n}\n\nconst Date = React.forwardRef<HTMLDivElement, DateProps>(\n (\n {\n value: controlledValue,\n onChange,\n disabled: disabledProp = () => false,\n minDate,\n maxDate,\n defaultMonth,\n className,\n styles,\n ...props\n },\n ref\n ) => {\n const [uncontrolledValue, setUncontrolledValue] = React.useState<Date | null>(null)\n const [today, setToday] = React.useState<Date | null>(null)\n const [currentMonth, setCurrentMonth] = React.useState<Date | null>(null)\n const [focusedDate, setFocusedDate] = React.useState<Date | null>(null)\n\n const selectedDate = controlledValue !== undefined ? controlledValue : uncontrolledValue\n\n const resolved = resolveDateBaseStyles(normalizeDateStyles(styles));\n\n const isDateDisabled = React.useCallback(\n (date: Date): boolean => {\n if (disabledProp(date)) return true\n if (minDate && date < minDate) return true\n if (maxDate && date > maxDate) return true\n return false\n },\n [disabledProp, minDate, maxDate]\n )\n\n const isDateOutOfRange = React.useCallback(\n (date: Date): boolean => {\n if (!currentMonth) return false;\n return (\n date.getMonth() !== currentMonth.getMonth() ||\n date.getFullYear() !== currentMonth.getFullYear()\n )\n },\n [currentMonth]\n )\n\n const selectDate = React.useCallback(\n (date: Date) => {\n if (!isDateDisabled(date)) {\n if (controlledValue === undefined) {\n setUncontrolledValue(date)\n }\n onChange?.(date)\n setFocusedDate(null)\n }\n },\n [controlledValue, onChange, isDateDisabled]\n )\n\n const focusDate = React.useCallback((date: Date) => {\n setFocusedDate(date)\n }, [])\n\n const navigateMonth = React.useCallback((offset: number) => {\n setCurrentMonth(prev => {\n const baseDate = prev ?? new NativeDate(); // Handle null prev\n const newMonth = new NativeDate(baseDate.getFullYear(), baseDate.getMonth() + offset, 1)\n return newMonth\n })\n }, [])\n\n const calendarGrid = React.useMemo(\n () => currentMonth ? getCalendarGrid(currentMonth) : [],\n [currentMonth]\n )\n\n const contextValue: DateContextValue = React.useMemo(\n () => ({\n selectedDate,\n focusedDate,\n currentMonth,\n today,\n selectDate,\n focusDate,\n navigateMonth,\n isDateDisabled,\n isDateOutOfRange,\n }),\n [selectedDate, focusedDate, currentMonth, today, selectDate, focusDate, navigateMonth, isDateDisabled, isDateOutOfRange]\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (!focusedDate) return\n\n let newFocusedDate: Date | null = null\n\n switch (e.key) {\n case \"ArrowUp\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 7)\n break\n case \"ArrowDown\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 7)\n break\n case \"ArrowLeft\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 1)\n break\n case \"ArrowRight\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 1)\n break\n case \"Home\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), 1)\n break\n case \"End\":\n e.preventDefault()\n const daysInMonth = getDaysInMonth(focusedDate)\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), daysInMonth)\n break\n case \"PageUp\":\n e.preventDefault()\n navigateMonth(-1)\n return\n case \"PageDown\":\n e.preventDefault()\n navigateMonth(1)\n return\n case \"Enter\":\n case \" \":\n e.preventDefault()\n selectDate(focusedDate)\n return\n }\n\n if (newFocusedDate) {\n setFocusedDate(newFocusedDate)\n // Auto-navigate month if needed\n if (newFocusedDate.getMonth() !== currentMonth!.getMonth() || newFocusedDate.getFullYear() !== currentMonth!.getFullYear()) {\n setCurrentMonth(new NativeDate(newFocusedDate.getFullYear(), newFocusedDate.getMonth(), 1))\n }\n }\n },\n [focusedDate, currentMonth, selectDate, navigateMonth]\n )\n\n // Set initial focus, today, and current month on client mount\n React.useEffect(() => {\n const now = new NativeDate()\n setToday(now)\n\n if (currentMonth === null) { // Only set if not yet initialized\n setCurrentMonth(defaultMonth ?? now)\n }\n\n if (focusedDate === null) { // Only set if not yet initialized\n setFocusedDate(selectedDate ?? now)\n }\n }, [defaultMonth, currentMonth, focusedDate, selectedDate]) // Add relevant dependencies\n\n return (\n <DateContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cn(\"date\", dateModuleStyles.calendar, className, resolved.root)}\n role=\"application\"\n aria-label=\"Date picker calendar\"\n onKeyDown={handleKeyDown}\n {...props}\n >\n {currentMonth && (\n <>\n <DateHeader className={resolved.header} />\n <DateDayHeaders className={resolved[\"day-headers\"]} />\n <DateGrid grid={calendarGrid} className={resolved.grid} dayCellClassName={resolved[\"day-cell\"]} />\n </>\n )}\n </div>\n </DateContext.Provider>\n )\n }\n)\n\nDate.displayName = \"Date\"\n\n/**\n * Calendar Header component\n */\ninterface DateHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the header */\n className?: string;\n}\n\n/** Navigation header with month/year display and prev/next controls */\nconst DateHeader = React.forwardRef<HTMLDivElement, DateHeaderProps>(\n ({ className, ...props }, ref) => {\n const { currentMonth, navigateMonth } = useDateContext()\n const { focusProps: prevFocusProps, isFocused: isPrevFocused, isFocusVisible: isPrevFocusVisible } = useFocusRing()\n const { focusProps: nextFocusProps, isFocused: isNextFocused, isFocusVisible: isNextFocusVisible } = useFocusRing()\n const { targetProps: prevTargetProps } = useFocus({ mode: \"target\" })\n const { targetProps: nextTargetProps } = useFocus({ mode: \"target\" })\n\n const monthYear = currentMonth\n ? currentMonth.toLocaleDateString(\"en-US\", {\n month: \"long\",\n year: \"numeric\",\n })\n : \"\"\n\n return (\n <div\n ref={ref}\n className={cn(\"header\", dateModuleStyles.header, className)}\n {...props}\n >\n <div className={cn(\"month-year\", dateModuleStyles[\"month-year\"])}>\n {monthYear}\n </div>\n <div>\n <button\n {...asElementProps<\"button\">(mergeProps(prevFocusProps, prevTargetProps))}\n onClick={() => navigateMonth(-1)}\n className={cn(\"nav-button\", \"prev-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Previous month\"\n data-focused={isPrevFocused ? \"true\" : undefined}\n data-focus-visible={isPrevFocusVisible ? \"true\" : undefined}\n >\n <ChevronLeft size={16} />\n </button>\n <button\n {...asElementProps<\"button\">(mergeProps(nextFocusProps, nextTargetProps))}\n onClick={() => navigateMonth(1)}\n className={cn(\"nav-button\", \"next-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Next month\"\n data-focused={isNextFocused ? \"true\" : undefined}\n data-focus-visible={isNextFocusVisible ? \"true\" : undefined}\n >\n <ChevronRight size={16} />\n </button>\n </div>\n </div>\n )\n }\n)\n\nDateHeader.displayName = \"Date.Header\"\n\n/**\n * Calendar Day Headers component\n */\ninterface DateDayHeadersProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the day headers row */\n className?: string;\n}\n\n/** Row of weekday abbreviation labels above the calendar grid */\nconst DateDayHeaders = React.forwardRef<HTMLDivElement, DateDayHeadersProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"day-headers\", dateModuleStyles[\"day-headers\"], className)}\n {...props}\n >\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"day-header\", dateModuleStyles[\"day-header\"])}\n >\n {day}\n </div>\n ))}\n </div>\n )\n }\n)\n\nDateDayHeaders.displayName = \"Date.DayHeaders\"\n\n/**\n * Calendar Grid component\n */\ninterface DateGridProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Calendar grid rows, each containing 7 Date objects */\n grid: Date[][]\n /** Classes applied to each individual date cell (DateDay component) */\n dayCellClassName?: string;\n}\n\n/** The 7-column calendar grid containing date cells */\nconst DateGrid = React.forwardRef<HTMLDivElement, DateGridProps>(\n ({ grid, className, dayCellClassName, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"grid\", dateModuleStyles.grid, className)}\n role=\"grid\"\n {...props}\n >\n {/* Week headers */}\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"day-header\", dateModuleStyles[\"week-header\"])}\n role=\"columnheader\"\n >\n {day}\n </div>\n ))}\n\n {/* Calendar rows */}\n {grid.map((week: Date[], weekIndex: number) => {\n return (\n <React.Fragment key={weekIndex}>\n {week.map((date: Date, dayIndex: number) => (\n <DateDay key={`${weekIndex}-${dayIndex}`} date={date} className={dayCellClassName} />\n ))}\n </React.Fragment>\n )\n })}\n </div>\n )\n }\n)\n\nDateGrid.displayName = \"Date.Grid\"\n\n/**\n * Calendar Day component\n */\ninterface DateDayProps extends React.HTMLAttributes<HTMLButtonElement> {\n /** The date this cell represents */\n date: Date\n}\n/**\n * Individual date cell in the calendar grid\n */\nconst DateDay = React.forwardRef<HTMLButtonElement, DateDayProps>(\n ({ date, className, onClick, ...props }, ref) => {\n const {\n selectedDate,\n focusedDate,\n today,\n selectDate,\n focusDate,\n isDateDisabled,\n isDateOutOfRange,\n } = useDateContext()\n\n const isDisabled = isDateDisabled(date)\n\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(ref, buttonRef)\n const { focusProps, isFocused: isFocusRingFocused, isFocusVisible } = useFocusRing()\n const { hoverProps, isHovered } = useHover({ isDisabled })\n const { targetProps } = useFocus({ mode: \"target\" })\n\n const isSelected = selectedDate ? isSameDay(date, selectedDate) : false\n const isFocused = focusedDate ? isSameDay(date, focusedDate) : false\n const isCurrentToday = isToday(date, today)\n const isOutOfRange = isDateOutOfRange(date)\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n selectDate(date)\n focusDate(date)\n onClick?.(e)\n },\n [date, selectDate, focusDate, onClick]\n )\n\n const handleFocus = React.useCallback(() => {\n focusDate(date)\n }, [date, focusDate])\n\n React.useEffect(() => {\n if (isFocused && buttonRef.current) {\n buttonRef.current.focus({ preventScroll: true })\n }\n }, [isFocused])\n\n return (\n <button\n ref={mergedRef}\n onClick={handleClick}\n className={cn(\"day\", dateModuleStyles[\"day-cell\"], className)}\n data-ring={targetProps[\"data-ring\"]}\n data-focus-indicator={targetProps[\"data-focus-indicator\"]}\n data-ring-inset={targetProps[\"data-ring-inset\"]}\n data-focused={isFocusRingFocused ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-selected={isSelected ? \"true\" : undefined}\n data-today={isCurrentToday ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n data-out-of-range={isOutOfRange ? \"true\" : undefined}\n data-focus-visible={isFocusVisible && isFocused ? \"true\" : undefined}\n disabled={isDisabled}\n aria-selected={isSelected}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n {...mergeProps(focusProps, hoverProps, { onFocus: handleFocus }, props)}\n >\n {date.getDate()}\n </button>\n )\n }\n)\n\nDateDay.displayName = \"Date.Day\"\n\nexport { Date, DateHeader, DateGrid, DateDay }\n",
|
|
4940
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-xs);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-xs) var(--radius-xs) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-xs);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-xs);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-xs) var(--radius-xs);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-xs);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
|
|
5028
4941
|
"cssTypes": "declare const styles: {\n calendar: string\n \"day-headers\": string\n \"day-header\": string\n header: string\n \"month-year\": string\n \"nav-button\": string\n grid: string\n \"day-cell\": string\n \"week-header\": string\n \"week-number\": string\n}\n\nexport default styles\n"
|
|
5029
4942
|
},
|
|
5030
4943
|
"divider": {
|
|
@@ -5033,8 +4946,8 @@ export const generatedSourceCode = {
|
|
|
5033
4946
|
"cssTypes": "declare const styles: {\n readonly divider: string;\n};\n\nexport default styles;\n"
|
|
5034
4947
|
},
|
|
5035
4948
|
"expand": {
|
|
5036
|
-
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useButton } from \"@react-aria/button\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useToggleState, type ToggleState } from \"react-stately\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { Divider, type DividerProps } from \"@/components/Divider\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport styles from \"./Expand.module.css\";\n\ntype ExpandDirection = \"below\" | \"above\" | \"left\" | \"right\";\n\ninterface ExpandIconStyles {\n collapsed?: StyleValue;\n expanded?: StyleValue;\n}\n\nexport interface ExpandStyleSlots {\n root?: StyleValue;\n trigger?: StyleValue;\n icon?: StyleValue | ExpandIconStyles;\n title?: StyleValue;\n content?: StyleValue;\n contentInner?: StyleValue;\n divider?: StyleValue;\n}\n\nexport type ExpandStylesProp = StylesProp<ExpandStyleSlots>;\n\nconst resolveExpandBaseStyles = createStylesResolver([\n \"root\",\n \"trigger\",\n \"icon\",\n \"iconCollapsed\",\n \"iconExpanded\",\n \"title\",\n \"content\",\n \"contentInner\",\n \"divider\",\n] as const);\n\nfunction resolveExpandStyles(stylesProp: ExpandStylesProp | undefined) {\n if (!stylesProp || typeof stylesProp === \"string\" || Array.isArray(stylesProp)) {\n return resolveExpandBaseStyles(stylesProp);\n }\n\n const { root, trigger, icon, title, content, contentInner, divider } = stylesProp;\n\n let iconClassName: StyleValue | undefined;\n let iconCollapsed: StyleValue | undefined;\n let iconExpanded: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === \"string\" || Array.isArray(icon)) {\n iconClassName = icon;\n iconCollapsed = icon;\n iconExpanded = icon;\n } else {\n iconCollapsed = icon.collapsed;\n iconExpanded = icon.expanded;\n }\n }\n\n return resolveExpandBaseStyles({\n root,\n trigger,\n icon: iconClassName,\n iconCollapsed,\n iconExpanded,\n title,\n content,\n contentInner,\n divider,\n });\n}\n\ninterface ExpandContextValue {\n state: ToggleState;\n isDisabled: boolean;\n resolvedStyles: ReturnType<typeof resolveExpandStyles>;\n}\n\nconst ExpandContext = React.createContext<ExpandContextValue | null>(null);\n\nfunction useExpandContext() {\n const context = React.useContext(ExpandContext);\n if (!context) {\n throw new Error(\"Expand compound components must be used within Expand\");\n }\n\n return context;\n}\n\nexport interface ExpandIconProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Custom icon element rendered inside the icon wrapper */\n children?: React.ReactNode;\n}\n\nconst ExpandIcon = React.forwardRef<HTMLSpanElement, ExpandIconProps>(\n ({ children, className, ...props }, ref) => {\n const { state, resolvedStyles } = useExpandContext();\n\n return (\n <span\n ref={ref}\n className={cn(\n \"icon\",\n styles.icon,\n resolvedStyles.icon,\n state.isSelected ? resolvedStyles.iconExpanded : resolvedStyles.iconCollapsed,\n className,\n )}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n aria-hidden=\"true\"\n {...props}\n >\n {children ?? <ChevronDown size={16} />}\n </span>\n );\n },\n);\nExpandIcon.displayName = \"Expand.Icon\";\n\ninterface ExpandTriggerProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** Label or content rendered inside the trigger */\n children?: React.ReactNode;\n /** Optional title element rendered in the trigger's text slot */\n title?: React.ReactNode;\n}\n\nconst ExpandTrigger = React.forwardRef<HTMLButtonElement, ExpandTriggerProps>(\n ({ children, className, title, ...props }, ref) => {\n const { state, isDisabled, resolvedStyles } = useExpandContext();\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const mergedRef = useMergeRefs(triggerRef, ref);\n\n const { buttonProps, isPressed } = useButton(\n {\n isDisabled,\n onPress: () => state.toggle(),\n },\n triggerRef,\n );\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled });\n\n const hasElementChildren = React.Children.toArray(children).some(\n (child) => React.isValidElement(child),\n );\n const shouldRenderCompositeLabel = title !== undefined || !hasElementChildren;\n\n return (\n <button\n ref={mergedRef}\n {...mergeProps(buttonProps, focusProps, hoverProps, props)}\n className={cn(\n \"trigger\",\n styles.trigger,\n resolvedStyles.trigger,\n className,\n )}\n type=\"button\"\n aria-expanded={state.isSelected}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-expand-focus-surface=\"true\"\n >\n {shouldRenderCompositeLabel ? (\n <>\n <span\n className={cn(\"title\", styles.title, resolvedStyles.title)}\n >\n {title ?? children}\n </span>\n <ExpandIcon />\n </>\n ) : (\n children\n )}\n </button>\n );\n },\n);\nExpandTrigger.displayName = \"Expand.Trigger\";\n\nexport interface ExpandContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Content shown when the expand is open */\n children: React.ReactNode;\n /** Direction the content reveals from the trigger */\n from?: ExpandDirection;\n}\n\nconst ExpandContent = React.forwardRef<HTMLDivElement, ExpandContentProps>(\n ({ children, className, from, ...props }, ref) => {\n const { state, resolvedStyles } = useExpandContext();\n\n return (\n <div\n ref={ref}\n className={cn(\n \"content\",\n styles.content,\n resolvedStyles.content,\n className,\n )}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-from={from && from !== \"below\" ? from : undefined}\n aria-hidden={!state.isSelected}\n {...props}\n >\n <div\n className={cn(\n \"content-inner\",\n styles[\"content-inner\"],\n resolvedStyles.contentInner,\n )}\n >\n {children}\n </div>\n </div>\n );\n },\n);\nExpandContent.displayName = \"Expand.Content\";\n\nconst ExpandDivider = React.forwardRef<HTMLDivElement, DividerProps>(\n ({ className, spacing = \"none\", styles: dividerStyles, ...props }, ref) => {\n const { resolvedStyles } = useExpandContext();\n\n return (\n <Divider\n ref={ref}\n spacing={spacing}\n styles={dividerStyles}\n className={cn(\"divider\", styles.divider, resolvedStyles.divider, className)}\n {...props}\n />\n );\n },\n);\nExpandDivider.displayName = \"Expand.Divider\";\n\nexport interface ExpandProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\" | \"onChange\"> {\n /** Header content rendered in preset mode */\n title?: React.ReactNode;\n /** Controlled expanded state */\n isExpanded?: boolean;\n /** Initial expanded state for uncontrolled usage */\n defaultExpanded?: boolean;\n /** Called when the expanded state changes */\n onExpandedChange?: (isExpanded: boolean) => void;\n /** Alias for onExpandedChange */\n onChange?: (isExpanded: boolean) => void;\n /** Whether the expand is disabled */\n isDisabled?: boolean;\n /** Compound sub-components or content nodes */\n children?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ExpandStylesProp;\n}\n\nconst ExpandRoot = React.forwardRef<HTMLDivElement, ExpandProps>(\n (\n {\n className,\n title,\n isExpanded,\n defaultExpanded = false,\n onExpandedChange,\n onChange,\n isDisabled = false,\n children,\n styles: stylesProp,\n ...props\n },\n ref,\n ) => {\n const state = useToggleState({\n isSelected: isExpanded,\n defaultSelected: defaultExpanded,\n onChange: onExpandedChange ?? onChange,\n });\n\n const resolvedStyles = resolveExpandStyles(stylesProp);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const mergedRootRef = useMergeRefs(rootRef, ref);\n const childrenArray = React.Children.toArray(children);\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: rootRef,\n surfaceSelector: '[data-expand-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"ring\",\n });\n\n const contextValue = React.useMemo<ExpandContextValue>(\n () => ({\n state,\n isDisabled,\n resolvedStyles,\n }),\n [state, isDisabled, resolvedStyles],\n );\n\n return (\n <ExpandContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"expand-scope\", scopeProps.className, styles.scope)}>\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n ref={mergedRootRef}\n className={cn(\"expand\", styles.expand, className, resolvedStyles.root)}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n {...props}\n >\n {title !== undefined ? (\n <>\n <ExpandTrigger>{title}</ExpandTrigger>\n {childrenArray.find(\n (child) =>\n React.isValidElement(child) && child.type === ExpandDivider,\n ) ?? <ExpandDivider />}\n <ExpandContent>\n {childrenArray.filter(\n (child) =>\n !(React.isValidElement(child) && child.type === ExpandDivider),\n )}\n </ExpandContent>\n </>\n ) : (\n children\n )}\n </div>\n </div>\n </ExpandContext.Provider>\n );\n },\n);\nExpandRoot.displayName = \"Expand\";\n\nconst Expand = Object.assign(ExpandRoot, {\n Trigger: ExpandTrigger,\n Content: ExpandContent,\n Divider: ExpandDivider,\n Icon: ExpandIcon,\n});\n\nExpand.displayName = \"Expand\";\n\nexport { Expand };\n",
|
|
5037
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n position: relative;\n display: block;\n width: 100%;\n }\n\n .expand {\n --expand-disabled-opacity: 0.6;\n --expand-trigger-padding-x: 0.75rem;\n --expand-trigger-padding-y: 0.5rem;\n
|
|
4949
|
+
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useButton } from \"@react-aria/button\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useToggleState, type ToggleState } from \"react-stately\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { Divider, type DividerProps } from \"@/components/Divider\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport styles from \"./Expand.module.css\";\n\ntype ExpandDirection = \"below\" | \"above\" | \"left\" | \"right\";\n\ninterface ExpandIconStyles {\n collapsed?: StyleValue;\n expanded?: StyleValue;\n}\n\nexport interface ExpandStyleSlots {\n root?: StyleValue;\n trigger?: StyleValue;\n icon?: StyleValue | ExpandIconStyles;\n title?: StyleValue;\n content?: StyleValue;\n contentInner?: StyleValue;\n divider?: StyleValue;\n}\n\nexport type ExpandStylesProp = StylesProp<ExpandStyleSlots>;\n\nconst resolveExpandBaseStyles = createStylesResolver([\n \"root\",\n \"trigger\",\n \"icon\",\n \"iconCollapsed\",\n \"iconExpanded\",\n \"title\",\n \"content\",\n \"contentInner\",\n \"divider\",\n] as const);\n\nfunction resolveExpandStyles(stylesProp: ExpandStylesProp | undefined) {\n if (!stylesProp || typeof stylesProp === \"string\" || Array.isArray(stylesProp)) {\n return resolveExpandBaseStyles(stylesProp);\n }\n\n const { root, trigger, icon, title, content, contentInner, divider } = stylesProp;\n\n let iconClassName: StyleValue | undefined;\n let iconCollapsed: StyleValue | undefined;\n let iconExpanded: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === \"string\" || Array.isArray(icon)) {\n iconClassName = icon;\n iconCollapsed = icon;\n iconExpanded = icon;\n } else {\n iconCollapsed = icon.collapsed;\n iconExpanded = icon.expanded;\n }\n }\n\n return resolveExpandBaseStyles({\n root,\n trigger,\n icon: iconClassName,\n iconCollapsed,\n iconExpanded,\n title,\n content,\n contentInner,\n divider,\n });\n}\n\ninterface ExpandContextValue {\n state: ToggleState;\n isDisabled: boolean;\n resolvedStyles: ReturnType<typeof resolveExpandStyles>;\n}\n\nconst ExpandContext = React.createContext<ExpandContextValue | null>(null);\n\nfunction useExpandContext() {\n const context = React.useContext(ExpandContext);\n if (!context) {\n throw new Error(\"Expand compound components must be used within Expand\");\n }\n\n return context;\n}\n\nexport interface ExpandIconProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Custom icon element rendered inside the icon wrapper */\n children?: React.ReactNode;\n}\n\nconst ExpandIcon = React.forwardRef<HTMLSpanElement, ExpandIconProps>(\n ({ children, className, ...props }, ref) => {\n const { state, resolvedStyles } = useExpandContext();\n\n return (\n <span\n ref={ref}\n className={cn(\n \"icon\",\n styles.icon,\n resolvedStyles.icon,\n state.isSelected ? resolvedStyles.iconExpanded : resolvedStyles.iconCollapsed,\n className,\n )}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n aria-hidden=\"true\"\n {...props}\n >\n {children ?? <ChevronDown size={16} />}\n </span>\n );\n },\n);\nExpandIcon.displayName = \"Expand.Icon\";\n\ninterface ExpandTriggerProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"title\"> {\n /** Label or content rendered inside the trigger */\n children?: React.ReactNode;\n /** Optional title element rendered in the trigger's text slot */\n title?: React.ReactNode;\n}\n\nconst ExpandTrigger = React.forwardRef<HTMLButtonElement, ExpandTriggerProps>(\n ({ children, className, title, ...props }, ref) => {\n const { state, isDisabled, resolvedStyles } = useExpandContext();\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const mergedRef = useMergeRefs(triggerRef, ref);\n\n const { buttonProps, isPressed } = useButton(\n {\n isDisabled,\n onPress: () => state.toggle(),\n },\n triggerRef,\n );\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled });\n\n const hasElementChildren = React.Children.toArray(children).some(\n (child) => React.isValidElement(child),\n );\n const shouldRenderCompositeLabel = title !== undefined || !hasElementChildren;\n\n return (\n <button\n ref={mergedRef}\n {...mergeProps(buttonProps, focusProps, hoverProps, props)}\n className={cn(\n \"trigger\",\n styles.trigger,\n resolvedStyles.trigger,\n className,\n )}\n type=\"button\"\n aria-expanded={state.isSelected}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-expand-focus-surface=\"true\"\n >\n {shouldRenderCompositeLabel ? (\n <>\n <span\n className={cn(\"title\", styles.title, resolvedStyles.title)}\n >\n {title ?? children}\n </span>\n <ExpandIcon />\n </>\n ) : (\n children\n )}\n </button>\n );\n },\n);\nExpandTrigger.displayName = \"Expand.Trigger\";\n\nexport interface ExpandContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Content shown when the expand is open */\n children: React.ReactNode;\n /** Direction the content reveals from the trigger */\n from?: ExpandDirection;\n}\n\nconst ExpandContent = React.forwardRef<HTMLDivElement, ExpandContentProps>(\n ({ children, className, from, ...props }, ref) => {\n const { state, resolvedStyles } = useExpandContext();\n\n return (\n <div\n ref={ref}\n className={cn(\n \"content\",\n styles.content,\n resolvedStyles.content,\n className,\n )}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-from={from && from !== \"below\" ? from : undefined}\n aria-hidden={!state.isSelected}\n {...props}\n >\n <div\n className={cn(\n \"content-inner\",\n styles[\"content-inner\"],\n resolvedStyles.contentInner,\n )}\n >\n {children}\n </div>\n </div>\n );\n },\n);\nExpandContent.displayName = \"Expand.Content\";\n\nconst ExpandDivider = React.forwardRef<HTMLDivElement, DividerProps>(\n ({ className, spacing = \"none\", styles: dividerStyles, ...props }, ref) => {\n const { resolvedStyles } = useExpandContext();\n\n return (\n <Divider\n ref={ref}\n spacing={spacing}\n styles={dividerStyles}\n className={cn(\"divider\", styles.divider, resolvedStyles.divider, className)}\n {...props}\n />\n );\n },\n);\nExpandDivider.displayName = \"Expand.Divider\";\n\nfunction isExpandDivider(child: React.ReactNode): child is React.ReactElement<DividerProps> {\n return React.isValidElement(child) && child.type === ExpandDivider;\n}\n\nfunction isExpandContent(child: React.ReactNode): child is React.ReactElement<ExpandContentProps> {\n return React.isValidElement(child) && child.type === ExpandContent;\n}\n\nfunction prependContentChildren(\n content: React.ReactElement<ExpandContentProps>,\n prefix: React.ReactNode,\n) {\n return React.cloneElement(content, undefined, (\n <>\n {prefix}\n {content.props.children}\n </>\n ));\n}\n\nfunction moveDividersIntoContent(childrenArray: React.ReactNode[]) {\n const normalizedChildren: React.ReactNode[] = [];\n\n for (let index = 0; index < childrenArray.length; index += 1) {\n const child = childrenArray[index];\n const nextChild = childrenArray[index + 1];\n\n if (isExpandDivider(child) && isExpandContent(nextChild)) {\n normalizedChildren.push(prependContentChildren(nextChild, child));\n index += 1;\n continue;\n }\n\n normalizedChildren.push(child);\n }\n\n return normalizedChildren;\n}\n\nexport interface ExpandProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\" | \"onChange\"> {\n /** Header content rendered in preset mode */\n title?: React.ReactNode;\n /** Controlled expanded state */\n isExpanded?: boolean;\n /** Initial expanded state for uncontrolled usage */\n defaultExpanded?: boolean;\n /** Called when the expanded state changes */\n onExpandedChange?: (isExpanded: boolean) => void;\n /** Alias for onExpandedChange */\n onChange?: (isExpanded: boolean) => void;\n /** Whether the expand is disabled */\n isDisabled?: boolean;\n /** Compound sub-components or content nodes */\n children?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ExpandStylesProp;\n}\n\nconst ExpandRoot = React.forwardRef<HTMLDivElement, ExpandProps>(\n (\n {\n className,\n title,\n isExpanded,\n defaultExpanded = false,\n onExpandedChange,\n onChange,\n isDisabled = false,\n children,\n styles: stylesProp,\n ...props\n },\n ref,\n ) => {\n const state = useToggleState({\n isSelected: isExpanded,\n defaultSelected: defaultExpanded,\n onChange: onExpandedChange ?? onChange,\n });\n\n const resolvedStyles = resolveExpandStyles(stylesProp);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const mergedRootRef = useMergeRefs(rootRef, ref);\n const childrenArray = React.Children.toArray(children);\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: rootRef,\n surfaceSelector: '[data-expand-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"ring\",\n });\n\n const contextValue = React.useMemo<ExpandContextValue>(\n () => ({\n state,\n isDisabled,\n resolvedStyles,\n }),\n [state, isDisabled, resolvedStyles],\n );\n\n return (\n <ExpandContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"expand-scope\", scopeProps.className, styles.scope)}>\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n ref={mergedRootRef}\n className={cn(\"expand\", styles.expand, className, resolvedStyles.root)}\n data-selected={state.isSelected ? \"true\" : undefined}\n data-expanded={state.isSelected ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n {...props}\n >\n {title !== undefined ? (\n <>\n <ExpandTrigger>{title}</ExpandTrigger>\n <ExpandContent>\n {childrenArray.find(isExpandDivider) ?? <ExpandDivider />}\n {childrenArray.filter((child) => !isExpandDivider(child))}\n </ExpandContent>\n </>\n ) : (\n moveDividersIntoContent(childrenArray)\n )}\n </div>\n </div>\n </ExpandContext.Provider>\n );\n },\n);\nExpandRoot.displayName = \"Expand\";\n\nconst Expand = Object.assign(ExpandRoot, {\n Trigger: ExpandTrigger,\n Content: ExpandContent,\n Divider: ExpandDivider,\n Icon: ExpandIcon,\n});\n\nExpand.displayName = \"Expand\";\n\nexport { Expand };\n",
|
|
4950
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n position: relative;\n display: block;\n width: 100%;\n }\n\n .expand {\n --expand-disabled-opacity: 0.6;\n --expand-trigger-padding-x: 0.75rem;\n --expand-trigger-padding-y: 0.5rem;\n\n @apply flex w-full flex-col;\n }\n\n .expand[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .trigger {\n @apply flex w-full items-stretch justify-between border-0 p-0 text-left;\n\n appearance: none;\n color: var(--foreground);\n background-color: var(--background);\n cursor: pointer;\n border-radius: 0;\n font-size: var(--text-sm);\n line-height: var(--leading-snug);\n outline: none;\n box-shadow: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out));\n }\n\n .trigger:focus,\n .trigger:focus-visible {\n outline: none;\n box-shadow: none;\n }\n\n .trigger[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .title {\n @apply flex min-w-0 flex-1 items-center overflow-hidden;\n\n padding: var(--expand-trigger-padding-y) 0 var(--expand-trigger-padding-y)\n var(--expand-trigger-padding-x);\n font-weight: var(--font-weight-medium);\n border-radius: 0;\n color: inherit;\n background-color: transparent;\n }\n\n .icon {\n @apply flex shrink-0 items-center justify-center;\n\n padding: var(--expand-trigger-padding-y) var(--expand-trigger-padding-x);\n color: inherit;\n background-color: transparent;\n border-radius: 0;\n }\n\n @media (hover: hover) {\n .trigger:not([data-disabled=\"true\"]):hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .trigger:not([data-disabled=\"true\"]) .icon:hover {\n border-radius: 0;\n }\n }\n\n .icon > * {\n transition: transform 250ms var(--ease-smooth-settle);\n }\n\n .icon[data-selected=\"true\"] > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) {\n flex-direction: column-reverse;\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(0deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) {\n @apply flex-row-reverse items-start;\n }\n\n .expand:has(.content[data-from=\"left\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon > * {\n transform: rotate(-90deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) {\n @apply flex-row items-start;\n }\n\n .expand:has(.content[data-from=\"right\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(-90deg);\n }\n\n .content {\n display: grid;\n overflow: hidden;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms var(--ease-smooth-settle);\n }\n\n .content[data-selected=\"true\"] {\n grid-template-rows: 1fr;\n }\n\n .content[data-from=\"left\"],\n .content[data-from=\"right\"] {\n grid-template-rows: 1fr;\n grid-template-columns: 0fr;\n transition: grid-template-columns 300ms var(--ease-smooth-settle);\n }\n\n .content[data-from=\"left\"][data-selected=\"true\"],\n .content[data-from=\"right\"][data-selected=\"true\"] {\n grid-template-columns: 1fr;\n }\n\n .content-inner {\n @apply min-h-0 overflow-hidden;\n\n min-width: 0;\n color: var(--foreground);\n background-color: var(--background);\n }\n\n .divider {\n margin: 0;\n }\n}\n",
|
|
5038
4951
|
"cssTypes": "declare const styles: {\n scope: string;\n expand: string;\n trigger: string;\n icon: string;\n title: string;\n content: string;\n \"content-inner\": string;\n divider: string;\n};\n\nexport default styles;\n"
|
|
5039
4952
|
},
|
|
5040
4953
|
"flex": {
|
|
@@ -5058,14 +4971,14 @@ export const generatedSourceCode = {
|
|
|
5058
4971
|
"cssTypes": "declare const styles: {\n readonly grid: string;\n readonly container: string;\n readonly \"responsive-cols\": string;\n readonly \"responsive-gap\": string;\n readonly \"responsive-rows\": string;\n readonly \"has-row-gap\": string;\n readonly \"has-col-gap\": string;\n};\n\nexport default styles;\n"
|
|
5059
4972
|
},
|
|
5060
4973
|
"group": {
|
|
5061
|
-
"tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport { Button, type ButtonProps } from \"../Button\"\nimport { Expand, type ExpandProps } from \"../Expand\"\nimport { Input, type InputProps } from \"../Input\"\nimport { Select, type SelectProps } from \"../Select\"\nimport css from \"./Group.module.css\"\n\ntype Orientation = \"horizontal\" | \"vertical\"\ntype Spacing = \"none\" | \"xs\" | \"sm\"\n\ntype GroupItemStyles = {\n first?: StyleValue\n last?: StyleValue\n divider?: StyleValue\n grow?: StyleValue\n}\n\nexport interface GroupStyleSlots {\n root?: StyleValue;\n item?: StyleValue | GroupItemStyles;\n button?: StyleValue;\n input?: StyleValue;\n select?: StyleValue;\n expand?: StyleValue;\n}\n\nexport type GroupStylesProp = StylesProp<GroupStyleSlots>;\n\nexport interface GroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Variant class appended to the root and grouped slots. Accepts any string. */\n variant?: string\n /** Controls the axis that children are arranged along */\n orientation?: Orientation\n /** Controls the gap between group items */\n spacing?: Spacing\n /** Whether all items in the group are non-interactive */\n isDisabled?: boolean\n /** The currently active button value for toggle group behavior */\n value?: string\n /** Called when a button with a value prop is pressed */\n onChange?: (value: string) => void\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: GroupStylesProp\n}\n\ninterface GroupContextValue {\n isInGroup: boolean\n groupOrientation: Orientation\n groupSpacing: Spacing\n groupIsDisabled: boolean\n groupValue?: string\n groupOnChange?: (value: string) => void\n groupVariant?: string\n groupStyles: ReturnType<typeof resolveGroupStyles>\n registerInput?: (containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => void\n unregisterInput?: (containerRef: React.RefObject<HTMLDivElement | null>) => void\n activateInput?: () => boolean\n registerFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n unregisterFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n}\n\n// Context\nconst GroupContext = React.createContext<GroupContextValue | null>(null)\n\nfunction useGroupContext() {\n const context = React.useContext(GroupContext)\n if (!context) {\n throw new Error(\"Group sub-components must be used within Group\")\n }\n return context\n}\n\nconst resolveGroupBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"itemFirst\",\n \"itemLast\",\n \"itemDivider\",\n \"itemGrow\",\n \"button\",\n \"input\",\n \"select\",\n \"expand\",\n] as const)\n\nfunction resolveGroupStyles(styles: GroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveGroupBaseStyles(styles)\n const { root, item, button, input, select, expand } = styles\n\n let itemResolved: StyleValue | undefined\n let itemFirst: StyleValue | undefined\n let itemLast: StyleValue | undefined\n let itemDivider: StyleValue | undefined\n let itemGrow: StyleValue | undefined\n\n if (item) {\n if (typeof item === \"string\" || Array.isArray(item)) {\n itemResolved = item\n itemFirst = item\n itemLast = item\n itemDivider = item\n itemGrow = item\n } else {\n itemFirst = item.first\n itemLast = item.last\n itemDivider = item.divider\n itemGrow = item.grow\n }\n }\n\n return resolveGroupBaseStyles({\n root,\n item: itemResolved,\n itemFirst,\n itemLast,\n itemDivider,\n itemGrow,\n button,\n input,\n select,\n expand,\n })\n}\n\n// Orientation and spacing maps\nconst orientationMap: Record<Orientation, string> = {\n horizontal: css.horizontal,\n vertical: css.vertical,\n}\n\nconst spacingMap: Record<Spacing, string> = {\n none: css.none,\n xs: css.xs,\n sm: css.sm,\n}\n\n// Detect Divider elements by checking for separator role, orientation prop, or displayName\nfunction isDivider(child: React.ReactNode): boolean {\n if (!React.isValidElement(child)) return false\n const props = (child.props || {}) as Record<string, unknown>\n const type = child.type as any\n return props.role === \"separator\" || \"orientation\" in props || type?.displayName === \"Divider\"\n}\n\nfunction isHTMLElement(value: Element | null): value is HTMLElement {\n return value instanceof HTMLElement\n}\n\n// Root component\n/** Button group that groups related buttons together */\nconst GroupRoot = React.forwardRef<HTMLDivElement, GroupProps>(\n (\n {\n className,\n variant,\n orientation = \"horizontal\",\n spacing = \"none\",\n children,\n isDisabled = false,\n value,\n onChange,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const groupRef = React.useRef<HTMLDivElement>(null)\n const inputsRef = React.useRef<Map<React.RefObject<HTMLDivElement | null>, React.RefObject<HTMLInputElement | null>>>(new Map())\n const focusableSurfacesRef = React.useRef<React.RefObject<HTMLElement | null>[]>([])\n\n const childrenArray = React.Children.toArray(children).filter(\n (child) => child !== null && child !== undefined\n )\n\n const resolved = resolveGroupStyles(stylesProp)\n const mergedRef = useMergeRefs<HTMLDivElement>(ref, groupRef)\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: groupRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"item\",\n dependencies: [childrenArray.length, orientation, spacing],\n })\n\n const registerInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => {\n inputsRef.current.set(containerRef, inputRef)\n }, [])\n\n const unregisterInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>) => {\n inputsRef.current.delete(containerRef)\n }, [])\n\n const activateInput = React.useCallback(() => {\n const firstEntry = Array.from(inputsRef.current.entries())[0]\n if (firstEntry) {\n const [containerRef, inputRef] = firstEntry\n if (containerRef.current && inputRef.current) {\n // Focus the actual input for keyboard interaction\n inputRef.current.focus()\n\n // Force focus-visible state by finding the input container inside the wrapper\n // The Input component renders a container div with data-input-focus-surface\n const inputContainer = containerRef.current.querySelector('[data-input-focus-surface=\"true\"]') as HTMLElement\n if (inputContainer) {\n inputContainer.setAttribute('data-focus-visible', 'true')\n inputContainer.setAttribute('data-focused', 'true')\n }\n return true\n }\n }\n return false\n }, [])\n\n const registerFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current.push(ref)\n }, [])\n\n const unregisterFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current = focusableSurfacesRef.current.filter(r => r !== ref)\n }, [])\n\n\n const handleGroupKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"ArrowRight\" && e.key !== \"ArrowLeft\" && e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\") {\n return\n }\n\n const focusedElement = document.activeElement\n if (!focusedElement || !groupRef.current?.contains(focusedElement as Node)) {\n return\n }\n\n const focusableElements = focusableSurfacesRef.current\n .map(ref => ref.current)\n .filter((el): el is HTMLElement => el !== null && !!groupRef.current?.contains(el))\n\n if (focusableElements.length === 0) {\n return\n }\n\n const currentIndex = focusableElements.findIndex(el => el.contains(focusedElement as Node))\n if (currentIndex === -1) {\n return\n }\n\n const isHorizontal = orientation === \"horizontal\"\n const isNavigatingInline = (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") && isHorizontal\n const isNavigatingBlock = (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") && !isHorizontal\n\n if (!isNavigatingInline && !isNavigatingBlock) {\n return\n }\n\n e.preventDefault()\n\n let nextIndex = currentIndex\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n nextIndex = (currentIndex + 1) % focusableElements.length\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1\n }\n\n const nextElement = focusableElements[nextIndex]\n if (nextElement) {\n // Try to focus an interactive element within the surface\n const focusableChild = nextElement.querySelector('button, input, [role=\"button\"]') as HTMLElement | null\n if (focusableChild) {\n focusableChild.focus()\n } else {\n nextElement.focus()\n }\n }\n }, [orientation])\n\n const contextValue: GroupContextValue = {\n isInGroup: true,\n groupOrientation: orientation,\n groupSpacing: spacing,\n groupIsDisabled: isDisabled,\n groupValue: value,\n groupOnChange: onChange,\n groupVariant: variant,\n groupStyles: resolved,\n registerInput,\n unregisterInput,\n activateInput,\n registerFocusableSurface,\n unregisterFocusableSurface,\n }\n\n return (\n <GroupContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"group-scope\", scopeProps.className)}>\n <div {...indicatorProps} />\n <div\n ref={mergedRef}\n className={cn(\n 'group',\n variant,\n orientation,\n css.group,\n orientationMap[orientation],\n spacingMap[spacing],\n resolved.root,\n className\n )}\n role=\"group\"\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n onKeyDown={handleGroupKeyDown}\n {...props}\n >\n {childrenArray.map((child, index) => {\n const isFirst = index === 0\n const isLast = index === childrenArray.length - 1\n const isDividerChild = isDivider(child)\n\n // Extract layout-related classes from child to apply to the item wrapper\n const childProps = React.isValidElement(child) ? (child.props as any) : {}\n const childClassName = childProps.className || \"\"\n const shouldGrow = childClassName.includes('w-full') || childClassName.includes('flex-1')\n return (\n <div\n key={`item-${index}`}\n className={cn(\n 'item',\n variant,\n css.item,\n isFirst && resolved.itemFirst,\n isLast && resolved.itemLast,\n isDividerChild && css.divider,\n isDividerChild && resolved.itemDivider,\n shouldGrow && css.grow,\n shouldGrow && resolved.itemGrow,\n resolved.item,\n )}\n >\n {child}\n </div>\n )\n })}\n </div>\n </div>\n </GroupContext.Provider>\n )\n }\n)\nGroupRoot.displayName = \"Group\"\n\n// Group.Button component\ninterface GroupButtonProps extends ButtonProps {\n /** Whether this button is in an active/pressed state */\n active?: boolean\n /** Identifier used for toggle group behavior when Group has value/onChange */\n value?: string\n}\n\n/** Button styled to merge seamlessly with adjacent group items */\nconst GroupButton = React.forwardRef<HTMLButtonElement, GroupButtonProps>(\n ({ active, value, variant, className, onPress, onPointerDown, onMouseDown, ...restProps }, ref) => {\n const context = useGroupContext()\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(buttonRef, ref)\n\n // Merge disabled state from group context\n const isDisabled = restProps.isDisabled ?? context.groupIsDisabled\n\n // Derive active and onPress from toggle group context when value is provided\n const isActive = value !== undefined && context.groupValue !== undefined ? value === context.groupValue : active\n const baseHandlePress = value !== undefined && context.groupOnChange !== undefined ? () => context.groupOnChange!(value) : onPress\n\n const handlePress = React.useCallback((e: { target: EventTarget | null }) => {\n baseHandlePress?.(e)\n }, [baseHandlePress])\n\n // Activate input on pointer down to avoid focus ring flicker\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLButtonElement>) => {\n if (!isDisabled && e.pointerType !== \"mouse\") {\n // Pre-activate the input before button loses focus\n context.activateInput?.()\n }\n onPointerDown?.(e)\n }, [context, isDisabled, onPointerDown])\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {\n if (!isDisabled && context.activateInput?.()) {\n e.preventDefault()\n }\n onMouseDown?.(e)\n }, [context, isDisabled, onMouseDown])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(buttonRef)\n return () => {\n context.unregisterFocusableSurface?.(buttonRef)\n }\n }, [context])\n\n const buttonVariant = variant ?? context.groupVariant ?? \"ghost\"\n\n const buttonProps = {\n ...restProps,\n onPress: handlePress,\n onPointerDown: handlePointerDown,\n onMouseDown: handleMouseDown,\n variant: buttonVariant,\n isDisabled,\n \"data-focus-surface\": \"true\",\n \"data-selected\": isActive ? \"true\" : \"false\",\n className: cn(\n \"button\",\n buttonVariant,\n css.button,\n context.groupStyles.button,\n className\n ),\n }\n\n return <Button ref={mergedRef} {...buttonProps} />\n }\n)\nGroupButton.displayName = \"Group.Button\"\n\n// Group.Input component\ninterface GroupInputProps extends InputProps { }\n\n/** Input field integrated into the button group */\nconst GroupInput = React.forwardRef<HTMLInputElement, GroupInputProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"w-full\"\n />\n </div>\n )\n }\n)\nGroupInput.displayName = \"Group.Input\"\n\n// Group.InputWrapper component - preserves Input styling (for use with ghost variant)\ninterface GroupInputWrapperProps extends InputProps { }\n\n/** Input variant that preserves Input styling within the group */\nconst GroupInputWrapper = React.forwardRef<HTMLInputElement, GroupInputWrapperProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"w-full\"\n />\n </div>\n )\n }\n)\nGroupInputWrapper.displayName = \"Group.InputWrapper\"\n\n// Group.Select component\ninterface GroupSelectProps extends SelectProps<any> { }\n\n/** Select dropdown integrated into the button group */\nconst GroupSelect = React.forwardRef<HTMLDivElement, GroupSelectProps>(\n ({ className, isDisabled, ...props }, ref) => {\n const context = useGroupContext()\n const selectRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(selectRef, ref)\n\n // Merge disabled state from group context\n const disabled = isDisabled ?? context.groupIsDisabled\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(selectRef)\n return () => {\n context.unregisterFocusableSurface?.(selectRef)\n }\n }, [context])\n\n return (\n <Select\n ref={mergedRef}\n {...props}\n isDisabled={disabled}\n data-focus-surface=\"true\"\n className={cn(\"select\", context.groupVariant, css.select, context.groupStyles.select, className)}\n />\n )\n }\n)\nGroupSelect.displayName = \"Group.Select\"\n\n// Group.Expand component\ninterface GroupExpandProps extends ExpandProps { }\n\n/** Expand primitive integrated into the group */\nconst GroupExpand = React.forwardRef<HTMLDivElement, GroupExpandProps>(\n ({ className, isDisabled, styles: stylesProp, ...props }, ref) => {\n const context = useGroupContext()\n const surfaceRef = React.useRef<HTMLDivElement>(null)\n const disabled = isDisabled ?? context.groupIsDisabled\n const surfaceStyles = typeof stylesProp === \"string\" || Array.isArray(stylesProp) ? stylesProp : undefined\n const expandStyles = surfaceStyles ? undefined : stylesProp\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(surfaceRef)\n return () => {\n context.unregisterFocusableSurface?.(surfaceRef)\n }\n }, [context])\n\n return (\n <div\n ref={surfaceRef}\n data-focus-surface=\"true\"\n className={cn(\"expand\", context.groupVariant, css.expand, context.groupStyles.expand, surfaceStyles)}\n >\n <Expand\n ref={ref}\n {...props}\n className={className}\n styles={expandStyles}\n isDisabled={disabled}\n />\n </div>\n )\n }\n)\nGroupExpand.displayName = \"Group.Expand\"\n\n// Assemble compound component\nconst Group = Object.assign(GroupRoot, {\n Button: GroupButton,\n Input: GroupInput,\n InputWrapper: GroupInputWrapper,\n Select: GroupSelect,\n Expand: GroupExpand,\n})\n\nexport { Group, GroupContext }\n",
|
|
5062
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --
|
|
4974
|
+
"tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport { Button, type ButtonProps } from \"../Button\"\nimport { Expand, type ExpandProps } from \"../Expand\"\nimport { Input, type InputProps } from \"../Input\"\nimport { Select, type SelectProps } from \"../Select\"\nimport css from \"./Group.module.css\"\n\ntype Orientation = \"horizontal\" | \"vertical\"\ntype Spacing = \"none\" | \"xs\" | \"sm\"\n\ntype GroupItemStyles = {\n first?: StyleValue\n last?: StyleValue\n divider?: StyleValue\n grow?: StyleValue\n}\n\nexport interface GroupStyleSlots {\n root?: StyleValue;\n item?: StyleValue | GroupItemStyles;\n button?: StyleValue;\n input?: StyleValue;\n select?: StyleValue;\n expand?: StyleValue;\n}\n\nexport type GroupStylesProp = StylesProp<GroupStyleSlots>;\n\nexport interface GroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Variant class appended to the root and grouped slots. Accepts any string. */\n variant?: string\n /** Controls the axis that children are arranged along */\n orientation?: Orientation\n /** Controls the gap between group items */\n spacing?: Spacing\n /** Whether all items in the group are non-interactive */\n isDisabled?: boolean\n /** The currently active button value for toggle group behavior */\n value?: string\n /** Called when a button with a value prop is pressed */\n onChange?: (value: string) => void\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: GroupStylesProp\n}\n\ninterface GroupContextValue {\n isInGroup: boolean\n groupOrientation: Orientation\n groupSpacing: Spacing\n groupIsDisabled: boolean\n groupValue?: string\n groupOnChange?: (value: string) => void\n groupVariant?: string\n groupStyles: ReturnType<typeof resolveGroupStyles>\n registerInput?: (containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => void\n unregisterInput?: (containerRef: React.RefObject<HTMLDivElement | null>) => void\n activateInput?: () => boolean\n registerFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n unregisterFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n}\n\n// Context\nconst GroupContext = React.createContext<GroupContextValue | null>(null)\n\nfunction useGroupContext() {\n const context = React.useContext(GroupContext)\n if (!context) {\n throw new Error(\"Group sub-components must be used within Group\")\n }\n return context\n}\n\nconst resolveGroupBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"itemFirst\",\n \"itemLast\",\n \"itemDivider\",\n \"itemGrow\",\n \"button\",\n \"input\",\n \"select\",\n \"expand\",\n] as const)\n\nfunction resolveGroupStyles(styles: GroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveGroupBaseStyles(styles)\n const { root, item, button, input, select, expand } = styles\n\n let itemResolved: StyleValue | undefined\n let itemFirst: StyleValue | undefined\n let itemLast: StyleValue | undefined\n let itemDivider: StyleValue | undefined\n let itemGrow: StyleValue | undefined\n\n if (item) {\n if (typeof item === \"string\" || Array.isArray(item)) {\n itemResolved = item\n itemFirst = item\n itemLast = item\n itemDivider = item\n itemGrow = item\n } else {\n itemFirst = item.first\n itemLast = item.last\n itemDivider = item.divider\n itemGrow = item.grow\n }\n }\n\n return resolveGroupBaseStyles({\n root,\n item: itemResolved,\n itemFirst,\n itemLast,\n itemDivider,\n itemGrow,\n button,\n input,\n select,\n expand,\n })\n}\n\n// Orientation and spacing maps\nconst orientationMap: Record<Orientation, string> = {\n horizontal: css.horizontal,\n vertical: css.vertical,\n}\n\nconst spacingMap: Record<Spacing, string> = {\n none: css.none,\n xs: css.xs,\n sm: css.sm,\n}\n\n// Detect Divider elements by checking for separator role, orientation prop, or displayName\nfunction isDivider(child: React.ReactNode): boolean {\n if (!React.isValidElement(child)) return false\n const props = (child.props || {}) as Record<string, unknown>\n const type = child.type as any\n return props.role === \"separator\" || \"orientation\" in props || type?.displayName === \"Divider\"\n}\n\nfunction isHTMLElement(value: Element | null): value is HTMLElement {\n return value instanceof HTMLElement\n}\n\n// Root component\n/** Button group that groups related buttons together */\nconst GroupRoot = React.forwardRef<HTMLDivElement, GroupProps>(\n (\n {\n className,\n variant,\n orientation = \"horizontal\",\n spacing = \"none\",\n children,\n isDisabled = false,\n value,\n onChange,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const groupRef = React.useRef<HTMLDivElement>(null)\n const inputsRef = React.useRef<Map<React.RefObject<HTMLDivElement | null>, React.RefObject<HTMLInputElement | null>>>(new Map())\n const focusableSurfacesRef = React.useRef<React.RefObject<HTMLElement | null>[]>([])\n\n const childrenArray = React.Children.toArray(children).filter(\n (child) => child !== null && child !== undefined\n )\n\n const resolved = resolveGroupStyles(stylesProp)\n const mergedRef = useMergeRefs<HTMLDivElement>(ref, groupRef)\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: groupRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"item\",\n dependencies: [childrenArray.length, orientation, spacing],\n })\n\n const registerInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => {\n inputsRef.current.set(containerRef, inputRef)\n }, [])\n\n const unregisterInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>) => {\n inputsRef.current.delete(containerRef)\n }, [])\n\n const activateInput = React.useCallback(() => {\n const firstEntry = Array.from(inputsRef.current.entries())[0]\n if (firstEntry) {\n const [containerRef, inputRef] = firstEntry\n if (containerRef.current && inputRef.current) {\n // Focus the actual input for keyboard interaction\n inputRef.current.focus()\n\n // Force focus-visible state by finding the input container inside the wrapper\n // The Input component renders a container div with data-input-focus-surface\n const inputContainer = containerRef.current.querySelector('[data-input-focus-surface=\"true\"]') as HTMLElement\n if (inputContainer) {\n inputContainer.setAttribute('data-focus-visible', 'true')\n inputContainer.setAttribute('data-focused', 'true')\n }\n return true\n }\n }\n return false\n }, [])\n\n const registerFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current.push(ref)\n }, [])\n\n const unregisterFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current = focusableSurfacesRef.current.filter(r => r !== ref)\n }, [])\n\n\n const handleGroupKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"ArrowRight\" && e.key !== \"ArrowLeft\" && e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\") {\n return\n }\n\n const focusedElement = document.activeElement\n if (!focusedElement || !groupRef.current?.contains(focusedElement as Node)) {\n return\n }\n\n const focusableElements = focusableSurfacesRef.current\n .map(ref => ref.current)\n .filter((el): el is HTMLElement => el !== null && !!groupRef.current?.contains(el))\n\n if (focusableElements.length === 0) {\n return\n }\n\n const currentIndex = focusableElements.findIndex(el => el.contains(focusedElement as Node))\n if (currentIndex === -1) {\n return\n }\n\n const isHorizontal = orientation === \"horizontal\"\n const isNavigatingInline = (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") && isHorizontal\n const isNavigatingBlock = (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") && !isHorizontal\n\n if (!isNavigatingInline && !isNavigatingBlock) {\n return\n }\n\n e.preventDefault()\n\n let nextIndex = currentIndex\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n nextIndex = (currentIndex + 1) % focusableElements.length\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1\n }\n\n const nextElement = focusableElements[nextIndex]\n if (nextElement) {\n // Try to focus an interactive element within the surface\n const focusableChild = nextElement.querySelector('button, input, [role=\"button\"]') as HTMLElement | null\n if (focusableChild) {\n focusableChild.focus()\n } else {\n nextElement.focus()\n }\n }\n }, [orientation])\n\n const contextValue: GroupContextValue = {\n isInGroup: true,\n groupOrientation: orientation,\n groupSpacing: spacing,\n groupIsDisabled: isDisabled,\n groupValue: value,\n groupOnChange: onChange,\n groupVariant: variant,\n groupStyles: resolved,\n registerInput,\n unregisterInput,\n activateInput,\n registerFocusableSurface,\n unregisterFocusableSurface,\n }\n\n return (\n <GroupContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"group-scope\", scopeProps.className)}>\n <div {...indicatorProps} />\n <div\n ref={mergedRef}\n className={cn(\n 'group',\n variant,\n orientation,\n css.group,\n orientationMap[orientation],\n spacingMap[spacing],\n resolved.root,\n className\n )}\n role=\"group\"\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n onKeyDown={handleGroupKeyDown}\n {...props}\n >\n {childrenArray.map((child, index) => {\n const isFirst = index === 0\n const isLast = index === childrenArray.length - 1\n const isDividerChild = isDivider(child)\n\n // Extract layout-related classes from child to apply to the item wrapper\n const childProps = React.isValidElement(child) ? (child.props as any) : {}\n const childClassName = childProps.className || \"\"\n const shouldGrow = childClassName.includes('w-full') || childClassName.includes('flex-1')\n return (\n <div\n key={`item-${index}`}\n className={cn(\n 'item',\n variant,\n css.item,\n isFirst && resolved.itemFirst,\n isLast && resolved.itemLast,\n isDividerChild && css.divider,\n isDividerChild && resolved.itemDivider,\n shouldGrow && css.grow,\n shouldGrow && resolved.itemGrow,\n resolved.item,\n )}\n >\n {child}\n </div>\n )\n })}\n </div>\n </div>\n </GroupContext.Provider>\n )\n }\n)\nGroupRoot.displayName = \"Group\"\n\n// Group.Button component\ninterface GroupButtonProps extends ButtonProps {\n /** Whether this button is in an active/pressed state */\n active?: boolean\n /** Identifier used for toggle group behavior when Group has value/onChange */\n value?: string\n}\n\n/** Button styled to merge seamlessly with adjacent group items */\nconst GroupButton = React.forwardRef<HTMLButtonElement, GroupButtonProps>(\n ({ active, value, variant, className, onPress, onPointerDown, onMouseDown, ...restProps }, ref) => {\n const context = useGroupContext()\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(buttonRef, ref)\n\n // Merge disabled state from group context\n const isDisabled = restProps.isDisabled ?? context.groupIsDisabled\n\n // Derive active and onPress from toggle group context when value is provided\n const isActive = value !== undefined && context.groupValue !== undefined ? value === context.groupValue : active\n const baseHandlePress = value !== undefined && context.groupOnChange !== undefined ? () => context.groupOnChange!(value) : onPress\n\n const handlePress = React.useCallback((e: { target: EventTarget | null }) => {\n baseHandlePress?.(e)\n }, [baseHandlePress])\n\n // Activate input on pointer down to avoid focus ring flicker\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLButtonElement>) => {\n if (!isDisabled && e.pointerType !== \"mouse\") {\n // Pre-activate the input before button loses focus\n context.activateInput?.()\n }\n onPointerDown?.(e)\n }, [context, isDisabled, onPointerDown])\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {\n if (!isDisabled && context.activateInput?.()) {\n e.preventDefault()\n }\n onMouseDown?.(e)\n }, [context, isDisabled, onMouseDown])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(buttonRef)\n return () => {\n context.unregisterFocusableSurface?.(buttonRef)\n }\n }, [context])\n\n const buttonVariant = variant ?? context.groupVariant ?? \"ghost\"\n\n const buttonProps = {\n ...restProps,\n onPress: handlePress,\n onPointerDown: handlePointerDown,\n onMouseDown: handleMouseDown,\n variant: buttonVariant,\n isDisabled,\n \"data-focus-surface\": \"true\",\n \"data-selected\": isActive ? \"true\" : \"false\",\n className: cn(\n \"button\",\n buttonVariant,\n css.button,\n context.groupStyles.button,\n className\n ),\n }\n\n return <Button ref={mergedRef} {...buttonProps} />\n }\n)\nGroupButton.displayName = \"Group.Button\"\n\n// Group.Input component\ninterface GroupInputProps extends InputProps { }\n\n/** Input field integrated into the button group */\nconst GroupInput = React.forwardRef<HTMLInputElement, GroupInputProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInput.displayName = \"Group.Input\"\n\n// Group.InputWrapper component - preserves Input styling (for use with ghost variant)\ninterface GroupInputWrapperProps extends InputProps { }\n\n/** Input variant that preserves Input styling within the group */\nconst GroupInputWrapper = React.forwardRef<HTMLInputElement, GroupInputWrapperProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInputWrapper.displayName = \"Group.InputWrapper\"\n\n// Group.Select component\ninterface GroupSelectProps extends SelectProps<any> { }\n\n/** Select dropdown integrated into the button group */\nconst GroupSelect = React.forwardRef<HTMLDivElement, GroupSelectProps>(\n ({ className, isDisabled, ...props }, ref) => {\n const context = useGroupContext()\n const selectRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(selectRef, ref)\n\n // Merge disabled state from group context\n const disabled = isDisabled ?? context.groupIsDisabled\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(selectRef)\n return () => {\n context.unregisterFocusableSurface?.(selectRef)\n }\n }, [context])\n\n return (\n <Select\n ref={mergedRef}\n {...props}\n isDisabled={disabled}\n data-focus-surface=\"true\"\n className={cn(\"select\", context.groupVariant, css.select, context.groupStyles.select, className)}\n />\n )\n }\n)\nGroupSelect.displayName = \"Group.Select\"\n\n// Group.Expand component\ninterface GroupExpandProps extends ExpandProps { }\n\n/** Expand primitive integrated into the group */\nconst GroupExpand = React.forwardRef<HTMLDivElement, GroupExpandProps>(\n ({ className, isDisabled, styles: stylesProp, ...props }, ref) => {\n const context = useGroupContext()\n const surfaceRef = React.useRef<HTMLDivElement>(null)\n const disabled = isDisabled ?? context.groupIsDisabled\n const surfaceStyles = typeof stylesProp === \"string\" || Array.isArray(stylesProp) ? stylesProp : undefined\n const expandStyles = surfaceStyles ? undefined : stylesProp\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(surfaceRef)\n return () => {\n context.unregisterFocusableSurface?.(surfaceRef)\n }\n }, [context])\n\n return (\n <div\n ref={surfaceRef}\n data-focus-surface=\"true\"\n className={cn(\"expand\", context.groupVariant, css.expand, context.groupStyles.expand, surfaceStyles)}\n >\n <Expand\n ref={ref}\n {...props}\n className={className}\n styles={expandStyles}\n isDisabled={disabled}\n />\n </div>\n )\n }\n)\nGroupExpand.displayName = \"Group.Expand\"\n\n// Assemble compound component\nconst Group = Object.assign(GroupRoot, {\n Button: GroupButton,\n Input: GroupInput,\n InputWrapper: GroupInputWrapper,\n Select: GroupSelect,\n Expand: GroupExpand,\n})\n\nexport { Group, GroupContext }\n",
|
|
4975
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item .button {\n @apply w-full;\n }\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
|
|
5063
4976
|
"cssTypes": "declare const styles: {\n \"focus-scope\": string;\n \"focus-indicator\": string;\n group: string;\n horizontal: string;\n vertical: string;\n none: string;\n xs: string;\n sm: string;\n item: string;\n grow: string;\n divider: string;\n button: string;\n input: string;\n select: string;\n expand: string;\n trigger: string;\n};\n\nexport default styles;\n"
|
|
5064
4977
|
},
|
|
5065
4978
|
"input": {
|
|
5066
|
-
"tsx": "\"use client\";\n\nimport React, { forwardRef, type ComponentPropsWithoutRef } from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { mergeProps, } from \"@react-aria/utils\";\n\nimport { ChevronUp, ChevronDown } from \"lucide-react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { Tooltip } from \"@/components/Tooltip\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { GroupContext } from \"@/components/Group/Group\";\nimport css from \"./Input.module.css\";\n\ntype Variant = \"default\" | \"ghost\";\n\ntype InputIconStyles = {\n left?: StyleValue;\n right?: StyleValue;\n};\n\ntype InputStepperStyles = {\n up?: StyleValue;\n down?: StyleValue;\n};\n\nexport interface InputStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | InputIconStyles;\n stepper?: StyleValue | InputStepperStyles;\n}\n\nexport type InputStylesProp = StylesProp<InputStyleSlots>;\n\nexport type InputAction = InputActionDef | React.ReactNode;\ntype InputIconSlots = {\n prefix?: React.ReactNode;\n suffix?: React.ReactNode;\n};\n\nexport type InputActionDef = {\n icon: React.ReactNode;\n title: string;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n};\n\ntype InputActionSlots = {\n left?: InputAction[];\n right?: InputAction[];\n};\n\nconst resolveInputBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight', 'stepperUp', 'stepperDown'] as const);\n\nfunction resolveInputStyles(styles: InputStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveInputBaseStyles(styles);\n const { root, icon, stepper } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n let stepperUp: StyleValue | undefined;\n let stepperDown: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n if (stepper) {\n if (typeof stepper === 'string' || Array.isArray(stepper)) {\n stepperUp = stepper;\n stepperDown = stepper;\n } else {\n stepperUp = stepper.up;\n stepperDown = stepper.down;\n }\n }\n\n return resolveInputBaseStyles({ root, iconLeft, iconRight, stepperUp, stepperDown });\n}\n\nexport interface InputProps extends Omit<ComponentPropsWithoutRef<\"input\">, \"size\"> {\n /** Controls the visual style of the input */\n variant?: Variant;\n /** Whether the input is in an error state */\n error?: boolean;\n /** Icon displayed before the input value by default, or in named prefix/suffix slots */\n icon?: React.ReactNode | InputIconSlots;\n /** Inline actions rendered on the left or right side of the input. Passing an array keeps the existing right-side behavior. */\n actions?: InputAction[] | InputActionSlots;\n /** Hint content rendered inside a badge on the right side of the input, commonly used for keyboard shortcuts. */\n hint?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: InputStylesProp;\n /** Hides the spinner controls for number inputs */\n \"hide-controls\"?: boolean;\n}\n\nfunction isInputIconSlots(icon: InputProps[\"icon\"]): icon is InputIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && (\"prefix\" in icon || \"suffix\" in icon);\n}\n\nfunction resolveInputIcon(icon: InputProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isInputIconSlots(icon)) {\n return icon;\n }\n\n return { prefix: icon };\n}\n\nfunction isInputActionSlots(actions: InputProps[\"actions\"]): actions is InputActionSlots {\n return typeof actions === \"object\" && actions !== null && !Array.isArray(actions) && !React.isValidElement(actions) && (\"left\" in actions || \"right\" in actions);\n}\n\nfunction resolveInputActions(actions: InputProps[\"actions\"]): InputActionSlots {\n if (!actions) {\n return {};\n }\n\n if (isInputActionSlots(actions)) {\n return actions;\n }\n\n return { right: actions };\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n variant = \"default\",\n error = false,\n disabled,\n icon,\n actions,\n hint,\n type = \"text\",\n onFocus,\n onBlur,\n styles: stylesProp,\n \"hide-controls\": hideControls = false,\n ...props\n },\n ref\n ) => {\n const groupContext = React.useContext(GroupContext);\n const resolvedActions = resolveInputActions(actions);\n const resolvedIcon = resolveInputIcon(icon);\n const leftActions = resolvedActions.left ?? [];\n const rightActions = resolvedActions.right ?? [];\n const hasPrefix = !!resolvedIcon?.prefix;\n const hasSuffix = !!resolvedIcon?.suffix;\n const hasLeftActions = leftActions.length > 0;\n const hasRightActions = rightActions.length > 0;\n const hasHint = hint !== undefined && hint !== null;\n const hasStartAdornment = hasPrefix || hasLeftActions;\n const isNumberType = type === \"number\";\n const [isFocused, setIsFocused] = React.useState(false);\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n\n const { focusProps, isFocusVisible } = useFocusRing();\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef,\n surfaceSelector: '[data-input-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n\n const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n };\n\n const handleSpinClick = (direction: \"up\" | \"down\") => {\n if (!inputRef.current || disabled) return;\n\n const input = inputRef.current;\n\n if (direction === \"up\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n\n // Dispatch native input event to trigger React onChange handlers\n const event = new Event(\"input\", { bubbles: true });\n input.dispatchEvent(event);\n };\n\n const resolved = resolveInputStyles(stylesProp);\n const showControls = isNumberType && !hideControls;\n const hasEndAdornment = hasSuffix || hasRightActions || hasHint || showControls;\n const adornmentPadding = \"var(--adornment-offset)\";\n const inputPaddingStyle: React.CSSProperties = {\n ...(hasStartAdornment ? { paddingLeft: adornmentPadding } : {}),\n ...(hasEndAdornment ? { paddingRight: adornmentPadding } : {}),\n };\n\n const renderAction = (action: InputAction, index: number) => {\n const key = React.isValidElement(action) ? index : ((action as InputActionDef).title || index);\n\n return React.isValidElement(action) ? (\n <React.Fragment key={key}>{action}</React.Fragment>\n ) : (\n <Tooltip key={key} content={(action as InputActionDef).title} position=\"top\">\n <button\n type=\"button\"\n className={css.action}\n aria-label={(action as InputActionDef).title}\n onClick={(action as InputActionDef).onClick}\n >\n {(action as InputActionDef).icon}\n </button>\n </Tooltip>\n );\n };\n\n const inputRoot = (\n <div\n ref={containerRef}\n className={cn('input', css.container, resolved.root)}\n data-input-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n >\n {hasStartAdornment && (\n <div className={css['start-adornments']} data-start-adornments>\n {hasPrefix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconLeft)}>\n <span className={css.icon}>\n {resolvedIcon?.prefix}\n </span>\n </div>\n )}\n {hasLeftActions && (\n <div className={css.actions} data-actions data-actions-position=\"left\">\n {leftActions.map(renderAction)}\n </div>\n )}\n </div>\n )}\n <input\n ref={mergedRef}\n type={type}\n disabled={disabled}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n className={cn(css.field, className)}\n style={inputPaddingStyle}\n {...mergeProps(focusProps, {\n onFocus: handleFocus,\n onBlur: handleBlur,\n ...props,\n })}\n />\n {hasEndAdornment && (\n <div className={css['end-adornments']} data-end-adornments>\n {hasSuffix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconRight)}>\n <span className={css.icon}>\n {resolvedIcon?.suffix}\n </span>\n </div>\n )}\n {hasRightActions && (\n <div className={css.actions} data-actions data-actions-position=\"right\">\n {rightActions.map(renderAction)}\n </div>\n )}\n {hasHint && <span className={css.hint} data-hint>{hint}</span>}\n {showControls && (\n <div\n className={(css as any).controls}\n data-disabled={disabled || undefined}\n >\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperUp)}\n onClick={() => handleSpinClick(\"up\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Increment\"\n >\n <ChevronUp size={12} />\n </button>\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperDown)}\n onClick={() => handleSpinClick(\"down\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Decrement\"\n >\n <ChevronDown size={12} />\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n\n if (groupContext) {\n return inputRoot;\n }\n\n return (\n <div\n ref={scopeRef}\n className={cn(\"input-scope\", scopeProps.className, css.scope)}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {inputRoot}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n",
|
|
5067
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .
|
|
5068
|
-
"cssTypes": "declare const styles: {\n scope: string;\n
|
|
4979
|
+
"tsx": "\"use client\";\n\nimport React, { forwardRef, type ComponentPropsWithoutRef } from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { mergeProps, } from \"@react-aria/utils\";\n\nimport { ChevronUp, ChevronDown } from \"lucide-react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { Tooltip } from \"@/components/Tooltip\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { GroupContext } from \"@/components/Group/Group\";\nimport css from \"./Input.module.css\";\n\ntype Variant = \"default\" | \"ghost\";\n\ntype InputIconStyles = {\n left?: StyleValue;\n right?: StyleValue;\n};\n\ntype InputStepperStyles = {\n up?: StyleValue;\n down?: StyleValue;\n};\n\nexport interface InputStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | InputIconStyles;\n stepper?: StyleValue | InputStepperStyles;\n}\n\nexport type InputStylesProp = StylesProp<InputStyleSlots>;\n\nexport type InputAction = InputActionDef | React.ReactNode;\ntype InputIconSlots = {\n prefix?: React.ReactNode;\n suffix?: React.ReactNode;\n};\n\nexport type InputActionDef = {\n icon: React.ReactNode;\n title: string;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n};\n\ntype InputActionSlots = {\n left?: InputAction[];\n right?: InputAction[];\n};\n\nconst resolveInputBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight', 'stepperUp', 'stepperDown'] as const);\n\nfunction resolveInputStyles(styles: InputStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveInputBaseStyles(styles);\n const { root, icon, stepper } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n let stepperUp: StyleValue | undefined;\n let stepperDown: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n if (stepper) {\n if (typeof stepper === 'string' || Array.isArray(stepper)) {\n stepperUp = stepper;\n stepperDown = stepper;\n } else {\n stepperUp = stepper.up;\n stepperDown = stepper.down;\n }\n }\n\n return resolveInputBaseStyles({ root, iconLeft, iconRight, stepperUp, stepperDown });\n}\n\nexport interface InputProps extends Omit<ComponentPropsWithoutRef<\"input\">, \"size\"> {\n /** Controls the visual style of the input */\n variant?: Variant;\n /** Whether the input is in an error state */\n error?: boolean;\n /** Icon displayed before the input value by default, or in named prefix/suffix slots */\n icon?: React.ReactNode | InputIconSlots;\n /** Inline actions rendered on the left or right side of the input. Passing an array keeps the existing right-side behavior. */\n actions?: InputAction[] | InputActionSlots;\n /** Hint content rendered inside a badge on the right side of the input, commonly used for keyboard shortcuts. */\n hint?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: InputStylesProp;\n /** Hides the spinner controls for number inputs */\n \"hide-controls\"?: boolean;\n}\n\nfunction isInputIconSlots(icon: InputProps[\"icon\"]): icon is InputIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && (\"prefix\" in icon || \"suffix\" in icon);\n}\n\nfunction resolveInputIcon(icon: InputProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isInputIconSlots(icon)) {\n return icon;\n }\n\n return { prefix: icon };\n}\n\nfunction isInputActionSlots(actions: InputProps[\"actions\"]): actions is InputActionSlots {\n return typeof actions === \"object\" && actions !== null && !Array.isArray(actions) && !React.isValidElement(actions) && (\"left\" in actions || \"right\" in actions);\n}\n\nfunction resolveInputActions(actions: InputProps[\"actions\"]): InputActionSlots {\n if (!actions) {\n return {};\n }\n\n if (isInputActionSlots(actions)) {\n return actions;\n }\n\n return { right: actions };\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n variant = \"default\",\n error = false,\n disabled,\n icon,\n actions,\n hint,\n type = \"text\",\n onFocus,\n onBlur,\n styles: stylesProp,\n \"hide-controls\": hideControls = false,\n ...props\n },\n ref\n ) => {\n const groupContext = React.useContext(GroupContext);\n const resolvedActions = resolveInputActions(actions);\n const resolvedIcon = resolveInputIcon(icon);\n const leftActions = resolvedActions.left ?? [];\n const rightActions = resolvedActions.right ?? [];\n const hasPrefix = !!resolvedIcon?.prefix;\n const hasSuffix = !!resolvedIcon?.suffix;\n const hasLeftActions = leftActions.length > 0;\n const hasRightActions = rightActions.length > 0;\n const hasHint = hint !== undefined && hint !== null;\n const hasStartAdornment = hasPrefix || hasLeftActions;\n const isNumberType = type === \"number\";\n const [isFocused, setIsFocused] = React.useState(false);\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n\n const { focusProps, isFocusVisible } = useFocusRing();\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef,\n surfaceSelector: '[data-input-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n\n const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n };\n\n const handleSpinClick = (direction: \"up\" | \"down\") => {\n if (!inputRef.current || disabled) return;\n\n const input = inputRef.current;\n\n if (direction === \"up\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n\n // Dispatch native input event to trigger React onChange handlers\n const event = new Event(\"input\", { bubbles: true });\n input.dispatchEvent(event);\n };\n\n const resolved = resolveInputStyles(stylesProp);\n const showControls = isNumberType && !hideControls;\n const hasEndAdornment = hasSuffix || hasRightActions || hasHint || showControls;\n const adornmentPadding = \"var(--adornment-offset)\";\n const inputPaddingStyle: React.CSSProperties = {\n ...(hasStartAdornment ? { paddingLeft: adornmentPadding } : {}),\n ...(hasEndAdornment ? { paddingRight: adornmentPadding } : {}),\n };\n\n const renderAction = (action: InputAction, index: number) => {\n const key = React.isValidElement(action) ? index : ((action as InputActionDef).title || index);\n\n return React.isValidElement(action) ? (\n <React.Fragment key={key}>{action}</React.Fragment>\n ) : (\n <Tooltip key={key} content={(action as InputActionDef).title} position=\"top\">\n <button\n type=\"button\"\n className={css.action}\n aria-label={(action as InputActionDef).title}\n onClick={(action as InputActionDef).onClick}\n >\n {(action as InputActionDef).icon}\n </button>\n </Tooltip>\n );\n };\n\n const inputRoot = (\n <div\n ref={containerRef}\n className={cn('input', css.container, resolved.root)}\n data-input-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n >\n {hasStartAdornment && (\n <div className={css['start-adornments']} data-start-adornments>\n {hasPrefix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconLeft)}>\n <span className={css.icon}>\n {resolvedIcon?.prefix}\n </span>\n </div>\n )}\n {hasLeftActions && (\n <div className={css.actions} data-actions data-actions-position=\"left\">\n {leftActions.map(renderAction)}\n </div>\n )}\n </div>\n )}\n <input\n ref={mergedRef}\n type={type}\n disabled={disabled}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n className={cn(css.input, className)}\n style={inputPaddingStyle}\n {...mergeProps(focusProps, {\n onFocus: handleFocus,\n onBlur: handleBlur,\n ...props,\n })}\n />\n {hasEndAdornment && (\n <div className={css['end-adornments']} data-end-adornments>\n {hasSuffix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconRight)}>\n <span className={css.icon}>\n {resolvedIcon?.suffix}\n </span>\n </div>\n )}\n {hasRightActions && (\n <div className={css.actions} data-actions data-actions-position=\"right\">\n {rightActions.map(renderAction)}\n </div>\n )}\n {hasHint && <span className={css.hint} data-hint>{hint}</span>}\n {showControls && (\n <div\n className={css.controls}\n data-disabled={disabled || undefined}\n >\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperUp)}\n onClick={() => handleSpinClick(\"up\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Increment\"\n >\n <ChevronUp size={12} />\n </button>\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperDown)}\n onClick={() => handleSpinClick(\"down\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Decrement\"\n >\n <ChevronDown size={12} />\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n\n if (groupContext) {\n return inputRoot;\n }\n\n return (\n <div\n ref={scopeRef}\n className={cn(\"input-scope\", scopeProps.className, css.scope)}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {inputRoot}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n",
|
|
4980
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .input {\n height: fit-content;\n flex: 1;\n min-width: 0;\n @apply py-1.5 px-3;\n font-family: inherit;\n font-size: var(--text-xs);\n line-height: var(--leading-snug);\n color: var(--foreground);\n background-color: transparent;\n border: none;\n outline: none;\n box-sizing: border-box;\n\n &::placeholder {\n color: var(--placeholder);\n }\n\n &[data-disabled] {\n color: var(--disabled-foreground);\n cursor: not-allowed;\n }\n\n /* Hide default browser spinners for number inputs */\n &[type=\"number\"] {\n\n &::-webkit-outer-spin-button,\n &::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n display: none;\n }\n\n /* Firefox */\n &[type=\"number\"] {\n -moz-appearance: textfield;\n }\n }\n }\n\n .icon-wrapper {\n @apply z-10 flex items-center;\n pointer-events: none;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n color: var(--foreground, currentColor);\n }\n\n .icon-left {\n @apply relative;\n }\n\n .icon-right {\n @apply relative;\n }\n\n .container {\n --adornment-offset: calc(var(--spacing, 0.25rem) * 1.5);\n\n display: flex;\n align-items: center;\n width: 100%;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-sizing: border-box;\n overflow: hidden;\n\n &[data-disabled] {\n background-color: var(--disabled-background);\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n &[data-variant=\"ghost\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n\n background-color: transparent;\n border-color: transparent;\n }\n }\n\n .start-adornments,\n .end-adornments {\n @apply flex items-center gap-1;\n align-self: stretch;\n flex-shrink: 0;\n pointer-events: none;\n }\n\n .start-adornments {\n @apply pl-2.5;\n }\n\n .end-adornments {\n padding-right: var(--adornment-offset);\n\n &:has(.controls) {\n padding-right: 0;\n }\n\n &:has([data-hint]) {\n padding-right: 0;\n }\n }\n\n .actions {\n @apply flex items-center gap-1;\n pointer-events: auto;\n }\n\n .action {\n @apply flex items-center justify-center p-2;\n border-radius: 0.25rem;\n color: var(--action-foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--action-background-hover);\n color: var(--action-foreground-hover);\n }\n\n .hint {\n @apply inline-flex items-center justify-center whitespace-nowrap;\n flex-shrink: 0;\n margin-inline-start: calc(var(--spacing, 0.25rem) * 0.5);\n margin-inline-end: var(--adornment-offset);\n font-size: var(--text-sm);\n line-height: 1;\n color: var(--foreground);\n background-color: var(--background);\n pointer-events: auto;\n }\n\n .controls {\n @apply flex w-7.5 flex-col;\n align-self: stretch;\n min-height: 100%;\n border-left: var(--border-width-base, 1px) solid var(--background-border);\n pointer-events: auto;\n }\n\n .controls[data-disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .stepper {\n @apply flex w-full flex-1 items-center justify-center p-0 cursor-pointer;\n flex: 1;\n background-color: transparent;\n border: none;\n color: var(--foreground);\n --active-background: var(--background-700);\n --active-color: var(--foreground-100);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &+.stepper {\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n &:hover:not(:disabled) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--hover-background);\n color: var(--hover-color);\n }\n\n &:active:not(:disabled) {\n background-color: var(--active-background);\n color: var(--active-color);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n }\n}\n",
|
|
4981
|
+
"cssTypes": "declare const styles: {\n scope: string;\n input: string;\n \"icon-wrapper\": string;\n icon: string;\n container: string;\n \"start-adornments\": string;\n \"end-adornments\": string;\n actions: string;\n action: string;\n hint: string;\n controls: string;\n stepper: string;\n};\n\nexport default styles;\n"
|
|
5069
4982
|
},
|
|
5070
4983
|
"label": {
|
|
5071
4984
|
"tsx": "import { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Label.module.css\";\n\ninterface LabelStyleSlots {\n root?: StyleValue;\n requiredIndicator?: StyleValue;\n helperText?: StyleValue;\n}\n\ntype LabelStylesProp = StylesProp<LabelStyleSlots>;\n\nconst resolveLabelBaseStyles = createStylesResolver(['root', 'requiredIndicator', 'helperText'] as const);\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement> {\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: LabelStylesProp;\n /** Whether to show a required asterisk indicator */\n required?: boolean;\n /** Helper text shown below the label */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Size of the label text */\n size?: \"sm\" | \"md\" | \"lg\" | null;\n /** Whether the label appears disabled */\n disabled?: boolean | null;\n /** Whether to apply error styling */\n error?: boolean | null;\n}\n\nconst Label = ({\n className,\n styles,\n size = \"md\",\n disabled,\n error,\n required,\n helperText,\n helperTextError,\n children,\n ...props\n}: LabelProps) => {\n const resolved = resolveLabelBaseStyles(styles);\n return (\n <div className={cn('label', css.label, 'w-full', className, resolved.root)}>\n <label\n data-size={size ?? 'md'}\n data-disabled={disabled || undefined}\n data-error={error || undefined}\n {...props}\n >\n {children}\n {required && (\n <span className={cn('required-indicator', css['required-indicator'], resolved.requiredIndicator)} aria-label=\"required\">\n *\n </span>\n )}\n </label>\n {helperText && (\n <p\n className={cn('helper-text', css['helper-text'], resolved.helperText)}\n data-error={helperTextError || undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n};\n\nLabel.displayName = \"Label\";\n\nexport { Label };\n",
|
|
@@ -5074,7 +4987,7 @@ export const generatedSourceCode = {
|
|
|
5074
4987
|
},
|
|
5075
4988
|
"list": {
|
|
5076
4989
|
"tsx": "'use client';\n\nimport React from 'react';\nimport { cn } from \"./utils\";\nimport { createStylesResolver } from '@/lib/styles';\nimport { resolveGapStep, type GapSize } from '@/lib/gap';\nimport { Divider as FoldDivider } from '@/components/Divider';\nimport styles from './List.module.css';\nimport { ListContext, useListContext } from './list.context';\nimport {\n ListStyleSlot,\n ListContainerProps,\n ListHeaderProps,\n ListRef,\n ActionGroupComponentProps,\n FooterComponentProps,\n} from './list.types';\nimport { DividerProps } from '@/components/Divider';\nimport { scrollItemIntoView } from '@/utils/list-navigation';\n\nconst resolveListBaseStyles = createStylesResolver([\n 'root',\n 'header',\n 'item',\n 'checkbox',\n 'control',\n 'media',\n 'title',\n 'desc',\n 'actions',\n 'action',\n 'footer',\n] as const);\n\n// Ref container for keyboard navigation\nconst Container = React.forwardRef<ListRef, ListContainerProps>(\n (\n {\n items: _items = [],\n variant = 'default',\n orientation = 'vertical',\n gap,\n spacing = 'default',\n onNavigate,\n children,\n className,\n styles: stylesProp,\n style,\n ...props\n },\n ref\n ) => {\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const [focusedItem, setFocusedItemState] = React.useState<HTMLElement | null>(null);\n const [isFocusMode, setIsFocusMode] = React.useState(false);\n const shouldScrollFocusedItemRef = React.useRef(false);\n const resolvedStyles = resolveListBaseStyles(stylesProp) as Record<ListStyleSlot, string>;\n\n const getFocusableItems = React.useCallback(() => {\n if (!rootRef.current) return [];\n\n return Array.from(rootRef.current.querySelectorAll<HTMLElement>('[role=\"listitem\"]')).filter((item) => (\n item.isConnected &&\n item.tabIndex >= 0 &&\n item.getAttribute('aria-hidden') !== 'true' &&\n item.getAttribute('aria-disabled') !== 'true' &&\n item.getAttribute('data-disabled') !== 'true'\n ));\n }, []);\n\n const getFocusedIndex = React.useCallback(() => {\n if (!focusedItem || !isFocusMode) return null;\n const itemIndex = getFocusableItems().indexOf(focusedItem);\n return itemIndex >= 0 ? itemIndex : null;\n }, [focusedItem, getFocusableItems, isFocusMode]);\n\n const setFocusedItem = React.useCallback((\n item: HTMLElement | null,\n options: { enterFocusMode?: boolean; scroll?: boolean } = {},\n ) => {\n if (!item) {\n shouldScrollFocusedItemRef.current = false;\n setFocusedItemState(null);\n setIsFocusMode(false);\n return;\n }\n\n if (options.scroll) {\n shouldScrollFocusedItemRef.current = true;\n }\n\n setFocusedItemState(item);\n setIsFocusMode(options.enterFocusMode ?? true);\n }, []);\n\n const focusItemAtIndex = React.useCallback((index: number, scroll = true) => {\n const itemsInOrder = getFocusableItems();\n const target = itemsInOrder[index];\n if (!target) return false;\n\n shouldScrollFocusedItemRef.current = scroll;\n target.focus({ preventScroll: true });\n return true;\n }, [getFocusableItems]);\n\n const focusAdjacentItem = React.useCallback((currentItem: HTMLElement | null, direction: 1 | -1, scroll = true) => {\n const itemsInOrder = getFocusableItems();\n if (itemsInOrder.length === 0) return false;\n\n const currentIndex = currentItem ? itemsInOrder.indexOf(currentItem) : -1;\n const nextIndex = currentIndex === -1\n ? (direction === 1 ? 0 : itemsInOrder.length - 1)\n : Math.min(Math.max(currentIndex + direction, 0), itemsInOrder.length - 1);\n\n if (currentIndex !== -1 && nextIndex === currentIndex) {\n return false;\n }\n\n return focusItemAtIndex(nextIndex, scroll);\n }, [focusItemAtIndex, getFocusableItems]);\n\n const focusBoundaryItem = React.useCallback((position: 'first' | 'last', scroll = true) => {\n const itemsInOrder = getFocusableItems();\n if (itemsInOrder.length === 0) return false;\n\n return focusItemAtIndex(position === 'first' ? 0 : itemsInOrder.length - 1, scroll);\n }, [focusItemAtIndex, getFocusableItems]);\n\n // Expose ref methods for keyboard navigation\n React.useImperativeHandle(ref, () => ({\n focusNext: () => {\n focusAdjacentItem(focusedItem, 1);\n onNavigate?.down?.();\n },\n focusPrev: () => {\n focusAdjacentItem(focusedItem, -1);\n onNavigate?.up?.();\n },\n focusFirst: () => {\n focusBoundaryItem('first');\n onNavigate?.down?.();\n },\n focusLast: () => {\n focusBoundaryItem('last');\n onNavigate?.up?.();\n },\n selectHighlighted: () => {\n onNavigate?.enter?.();\n },\n clearHighlight: () => {\n setFocusedItem(null, { enterFocusMode: false });\n },\n getHighlightedIndex: () => getFocusedIndex(),\n }), [focusAdjacentItem, focusBoundaryItem, focusedItem, getFocusedIndex, onNavigate, setFocusedItem]);\n\n React.useEffect(() => {\n if (!isFocusMode || !focusedItem || !shouldScrollFocusedItemRef.current) return;\n shouldScrollFocusedItemRef.current = false;\n scrollItemIntoView(focusedItem);\n }, [focusedItem, isFocusMode]);\n\n React.useEffect(() => {\n if (!focusedItem) return;\n if (focusedItem.isConnected) return;\n setFocusedItem(null, { enterFocusMode: false });\n }, [focusedItem, setFocusedItem]);\n\n const contextValue = React.useMemo(\n () => ({\n focusedItem,\n isFocusMode,\n orientation,\n rootRef,\n styles: resolvedStyles,\n setFocusedItem,\n focusAdjacentItem,\n focusBoundaryItem,\n }),\n [focusAdjacentItem, focusBoundaryItem, focusedItem, isFocusMode, orientation, resolvedStyles, setFocusedItem]\n );\n\n return (\n <ListContext.Provider value={contextValue}>\n <div\n ref={rootRef}\n role=\"list\"\n className={cn(\n 'list',\n styles.container,\n className,\n resolvedStyles.root,\n )}\n style={{\n ...style,\n ...(gap ? { \"--list-gap-step\": resolveGapStep(gap as GapSize) } : null),\n } as React.CSSProperties}\n data-variant={variant}\n data-orientation={orientation}\n data-gap={gap}\n data-spacing={spacing}\n data-focus-mode={isFocusMode ? 'row' : undefined}\n data-keyboard-mode={isFocusMode ? 'true' : undefined}\n {...(props as React.HTMLAttributes<HTMLDivElement>)}\n >\n {children}\n </div>\n </ListContext.Provider>\n );\n }\n);\nContainer.displayName = 'List';\n\n/** Sticky heading row above a section of list items */\nconst Header = React.forwardRef<HTMLElement, ListHeaderProps>(\n ({ sticky, children, className, ...props }, ref) => {\n const { styles: listStyles } = useListContext();\n\n return (\n <header\n ref={ref}\n className={cn(styles.header, listStyles.header, sticky && styles.sticky, className)}\n {...props}\n >\n {children}\n </header>\n );\n }\n);\nHeader.displayName = 'List.Header';\n\n/** Row of action buttons aligned to the right of a list item */\nconst ActionGroup = React.forwardRef<HTMLDivElement, ActionGroupComponentProps>(\n ({ justify = 'start', children, className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(styles.actionGroup, className)}\n data-justify={justify}\n {...props}\n >\n {children}\n </div>\n )\n);\nActionGroup.displayName = 'List.ActionGroup';\n\n/** Horizontal separator between list sections */\nconst Divider = React.forwardRef<HTMLDivElement, DividerProps>(\n ({ className, ...props }, ref) => (\n <FoldDivider\n ref={ref}\n className={className}\n {...props}\n />\n )\n);\nDivider.displayName = 'List.Divider';\n\n/** Fixed bottom row beneath the list body */\nconst Footer = React.forwardRef<HTMLElement, FooterComponentProps>(\n ({ align = 'center', children, className, ...props }, ref) => {\n const { styles: listStyles } = useListContext();\n\n return (\n <footer\n ref={ref}\n className={cn(styles.footer, listStyles.footer, className)}\n data-align={align}\n {...props}\n >\n {children}\n </footer>\n );\n }\n);\nFooter.displayName = 'List.Footer';\n\n// Compound component\nconst List = Object.assign(Container, {\n Header,\n Item: null as any, // Set in index.ts\n Checkbox: null as any,\n CheckboxIndicator: null as any,\n Switch: null as any,\n Input: null as any,\n Select: null as any,\n Media: null as any,\n Desc: null as any,\n ActionGroup,\n Divider,\n Footer,\n});\n\nexport { Container, Header, ActionGroup, Divider, Footer };\n",
|
|
5077
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--
|
|
4990
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
|
|
5078
4991
|
"cssTypes": "declare const styles: {\n readonly container: string;\n readonly header: string;\n readonly sticky: string;\n readonly item: string;\n readonly actionGroup: string;\n readonly actions: string;\n readonly action: string;\n readonly checkbox: string;\n readonly control: string;\n readonly media: string;\n readonly title: string;\n readonly desc: string;\n readonly footer: string;\n};\n\nexport default styles;\n"
|
|
5079
4992
|
},
|
|
5080
4993
|
"mask": {
|
|
@@ -5084,12 +4997,12 @@ export const generatedSourceCode = {
|
|
|
5084
4997
|
},
|
|
5085
4998
|
"menu": {
|
|
5086
4999
|
"tsx": "import * as React from \"react\"\nimport type { Key } from \"react-aria\"\nimport { useListNavigation } from \"../../utils/list-navigation\"\nimport type {\n MenuContextValue,\n MenuSubmenuContextValue,\n RadioGroupContextValue,\n MenuProps,\n MenuPortalProps,\n MenuItemExtras,\n} from \"./menu.types\"\n\nconst MenuContext = React.createContext<MenuContextValue | null>(null)\n\nexport function useMenuContext() {\n const context = React.useContext(MenuContext)\n if (!context) {\n throw new Error(\"Menu component must be used within Menu root\")\n }\n return context\n}\n\nexport const MenuSubmenuContext = React.createContext<MenuSubmenuContextValue | null>(null)\n\nexport function useMenuSubmenuContext() {\n return React.useContext(MenuSubmenuContext)\n}\n\nexport const RadioGroupContext = React.createContext<RadioGroupContextValue | null>(null)\n\nexport function useRadioGroupContext() {\n return React.useContext(RadioGroupContext)\n}\n\nconst MenuPortal = ({ children }: MenuPortalProps) => {\n return <>{children}</>\n}\nMenuPortal.displayName = \"MenuPortal\"\nconst Menu = ({\n children,\n type = \"context-menu\",\n selectionMode = \"none\",\n selectedKeys: controlledSelectedKeys,\n defaultSelectedKeys,\n onSelectionChange,\n}: MenuProps) => {\n const [isOpen, setIsOpen] = React.useState(false)\n const [uncontrolledSelectedKeys, setUncontrolledSelectedKeys] = React.useState<Set<Key>>(\n defaultSelectedKeys ?? new Set()\n )\n const [radioGroups, setRadioGroups] = React.useState<Map<string, Key | null>>(new Map())\n const [activeSubmenuKey, setActiveSubmenuKey] = React.useState<Key | null>(null)\n\n const selectedKeys = controlledSelectedKeys !== undefined ? controlledSelectedKeys : uncontrolledSelectedKeys\n\n const nav = useListNavigation({ isOpen })\n const itemExtrasRef = React.useRef<Map<Key, MenuItemExtras>>(new Map())\n const mouseMoveDetectedRef = React.useRef(true)\n const clickPositionRef = React.useRef({ x: 0, y: 0 })\n const triggerRef = React.useRef<HTMLElement | null>(null)\n\n const registerItem = React.useCallback((key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => {\n nav.registerItem(key, textValue, isDisabled)\n itemExtrasRef.current.set(key, { onSelect, isSubmenuTrigger })\n }, [nav.registerItem])\n\n const unregisterItem = React.useCallback((key: Key) => {\n nav.unregisterItem(key)\n itemExtrasRef.current.delete(key)\n }, [nav.unregisterItem])\n\n const handleSelectionChange = React.useCallback((keys: Set<Key>) => {\n if (controlledSelectedKeys === undefined) {\n setUncontrolledSelectedKeys(keys)\n }\n onSelectionChange?.(keys)\n }, [controlledSelectedKeys, onSelectionChange])\n\n const toggleSelection = React.useCallback((key: Key) => {\n const newKeys = new Set(selectedKeys)\n if (selectionMode === \"single\") {\n newKeys.clear()\n newKeys.add(key)\n } else if (selectionMode === \"multiple\") {\n if (newKeys.has(key)) {\n newKeys.delete(key)\n } else {\n newKeys.add(key)\n }\n }\n handleSelectionChange(newKeys)\n }, [selectedKeys, selectionMode, handleSelectionChange])\n\n const close = React.useCallback(() => {\n setIsOpen(false)\n nav.setFocusedKey(null)\n }, [nav.setFocusedKey])\n\n const selectFocusedItem = React.useCallback(() => {\n if (nav.focusedKey === null) return\n const item = nav.items.find(i => i.key === nav.focusedKey)\n if (item?.isDisabled) return\n const extras = itemExtrasRef.current.get(nav.focusedKey)\n extras?.onSelect?.()\n }, [nav.focusedKey, nav.items])\n\n const isFocusedItemSubmenu = React.useCallback(() => {\n if (nav.focusedKey === null) return false\n const extras = itemExtrasRef.current.get(nav.focusedKey)\n return extras?.isSubmenuTrigger ?? false\n }, [nav.focusedKey])\n\n const setRadioGroupValue = React.useCallback((groupName: string, value: Key | null) => {\n setRadioGroups(prev => {\n const next = new Map(prev)\n next.set(groupName, value)\n return next\n })\n }, [])\n\n const getRadioGroupValue = React.useCallback((groupName: string) => {\n return radioGroups.get(groupName) ?? null\n }, [radioGroups])\n\n React.useEffect(() => {\n if (isOpen && nav.focusedKey === null && nav.enabledFilteredItems.length > 0) {\n nav.setFocusedKey(nav.enabledFilteredItems[0].key)\n }\n }, [isOpen, nav.enabledFilteredItems, nav.focusedKey, nav.setFocusedKey])\n\n const contextValue = React.useMemo(() => ({\n isOpen,\n setIsOpen,\n type,\n close,\n selectionMode,\n selectedKeys,\n onSelectionChange: handleSelectionChange,\n toggleSelection,\n items: nav.items,\n registerItem,\n unregisterItem,\n focusedKey: nav.focusedKey,\n setFocusedKey: nav.setFocusedKey,\n navigateToNextItem: nav.navigateToNextItem,\n navigateToPrevItem: nav.navigateToPrevItem,\n selectFocusedItem,\n isFocusedItemSubmenu,\n radioGroups,\n setRadioGroupValue,\n getRadioGroupValue,\n triggerRef,\n mouseMoveDetectedRef,\n clickPositionRef,\n activeSubmenuKey,\n setActiveSubmenuKey,\n } satisfies MenuContextValue), [\n isOpen,\n setIsOpen,\n type,\n close,\n selectionMode,\n selectedKeys,\n handleSelectionChange,\n toggleSelection,\n nav.items,\n registerItem,\n unregisterItem,\n nav.focusedKey,\n nav.setFocusedKey,\n nav.navigateToNextItem,\n nav.navigateToPrevItem,\n selectFocusedItem,\n isFocusedItemSubmenu,\n radioGroups,\n setRadioGroupValue,\n getRadioGroupValue,\n activeSubmenuKey,\n setActiveSubmenuKey,\n ])\n\n return (\n <MenuContext.Provider value={contextValue}>\n {children}\n </MenuContext.Provider>\n )\n}\nMenu.displayName = \"Menu\"\n\nexport { Menu, MenuPortal }\nexport type {\n MenuProps,\n MenuTriggerProps,\n MenuPortalProps,\n MenuContentProps,\n MenuGroupProps,\n MenuItemProps,\n MenuCheckboxItemProps,\n MenuRadioGroupProps,\n MenuRadioItemProps,\n MenuLabelProps,\n MenuSeparatorProps,\n MenuShortcutProps,\n MenuSubProps,\n MenuSubTriggerProps,\n MenuSubContentProps,\n} from \"./menu.types\"\n",
|
|
5087
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n :global(.menu) {\n display: contents;\n\n .content,\n .sub-content {\n --content-padding: calc(var(--spacing) * 1.5);\n --content-radius: var(--radius-sm, 0.375rem);\n --content-inner-radius: calc(var(--content-radius) - var(--border-width-base, 1px));\n --
|
|
5088
|
-
"cssTypes": "declare const styles: {\n trigger: string\n content: string\n list: string\n item: string\n '
|
|
5000
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n :global(.menu) {\n display: contents;\n\n .content,\n .sub-content {\n --content-padding: calc(var(--spacing) * 1.5);\n --content-radius: var(--radius-sm, 0.375rem);\n --content-inner-radius: calc(var(--content-radius) - var(--border-width-base, 1px));\n --open-animation: slide-in-from-top 0.15s var(--ease-snappy-pop);\n --closed-animation: slide-out-to-top 0.15s var(--ease-snappy-pop);\n --disabled-opacity: 0.5;\n\n @apply absolute min-w-40 max-w-80 overflow-hidden;\n z-index: 50000;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--content-radius);\n }\n\n .trigger {\n &[data-type=\"pop-over\"][data-pressed=\"true\"] {\n opacity: 1;\n background-color: var(--background-pressed);\n border-radius: var(--radius-sm, 0.375rem);\n }\n }\n\n .content[data-state=\"open\"],\n .sub-content[data-state=\"open\"] {\n animation: var(--open-animation);\n }\n\n .content[data-state=\"closed\"],\n .sub-content[data-state=\"closed\"] {\n animation: var(--closed-animation);\n }\n\n .list {\n @apply space-y-1;\n max-height: 24rem;\n overflow-y: auto;\n }\n\n .item {\n @apply flex min-w-0 items-center gap-2;\n padding: var(--item-padding, var(--content-padding));\n border-radius: var(--item-radius, var(--content-inner-radius));\n cursor: pointer;\n user-select: none;\n outline: none;\n color: var(--foreground);\n\n &[data-focused=\"true\"] {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n pointer-events: none;\n }\n }\n\n .item {\n &[data-inset=\"true\"] {\n padding-left: calc(var(--item-padding, var(--content-padding)) * 2.67);\n }\n }\n\n .item-indicator {\n @apply ml-auto flex h-4 w-4 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .sub-trigger[data-state=\"open\"]:not([data-focused=\"true\"]) {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n .sub-trigger-chevron {\n @apply ml-auto h-4 w-4 shrink-0;\n color: var(--chevron-foreground, currentColor);\n }\n\n .label {\n padding: var(--content-padding);\n color: var(--foreground-muted);\n\n &[data-inset=\"true\"] {\n padding-left: calc(var(--content-padding) * 2.67);\n }\n }\n\n .separator {\n @apply -mx-1 my-1 h-px;\n background-color: var(--background-border);\n }\n\n .shortcut {\n margin-left: auto;\n color: var(--foreground-muted);\n }\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-to-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n}\n",
|
|
5001
|
+
"cssTypes": "declare const styles: {\n trigger: string\n content: string\n list: string\n item: string\n 'item-indicator': string\n 'sub-trigger': string\n 'sub-trigger-chevron': string\n 'sub-content': string\n label: string\n separator: string\n shortcut: string\n}\n\nexport default styles\n"
|
|
5089
5002
|
},
|
|
5090
5003
|
"modal": {
|
|
5091
5004
|
"tsx": "\"use client\"\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useDialog } from \"react-aria\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useOverlayTriggerState } from \"react-stately\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { X } from \"lucide-react\";\nimport css from \"./Modal.module.css\";\n\nconst useModalKeyboard = (\n ref: React.RefObject<HTMLDivElement | null>,\n isOpen: boolean,\n isDismissable: boolean,\n isKeyboardDismissDisabled: boolean,\n onClose: () => void\n) => {\n const onCloseRef = React.useRef(onClose);\n onCloseRef.current = onClose;\n\n React.useEffect(() => {\n if (!isOpen || !ref.current) return;\n\n ref.current.focus();\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && isDismissable && !isKeyboardDismissDisabled) {\n e.preventDefault();\n onCloseRef.current();\n }\n };\n\n ref.current.addEventListener(\"keydown\", handleKeyDown);\n return () => ref.current?.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isDismissable, isKeyboardDismissDisabled]);\n};\n\nexport interface ModalStyleSlots {\n root?: StyleValue;\n overlay?: StyleValue;\n backdrop?: StyleValue;\n header?: StyleValue;\n title?: StyleValue;\n spacer?: StyleValue;\n close?: StyleValue;\n closeIcon?: StyleValue;\n content?: StyleValue;\n footer?: StyleValue;\n}\n\nexport type ModalStylesProp = StylesProp<ModalStyleSlots>;\n\nconst resolveModalBaseStyles = createStylesResolver([\n 'root', 'overlay', 'backdrop', 'header', 'title', 'spacer', 'close', 'closeIcon', 'content', 'footer'\n] as const);\n\nfunction resolveModalStyles(styles: ModalStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveModalBaseStyles(styles);\n const { root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer } = styles;\n return resolveModalBaseStyles({ root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer });\n}\n\nexport interface ModalProps {\n /** Whether the modal is open */\n isOpen?: boolean;\n /** Callback when the open state changes */\n onOpenChange?: (isOpen: boolean) => void;\n /** Optional title rendered in the modal header bar */\n title?: React.ReactNode;\n /** Modal body content */\n children: React.ReactNode;\n /** Optional footer content rendered below the body */\n footer?: React.ReactNode;\n /** Whether to show the X close button in the header */\n close?: boolean;\n /** Controls modal width: \"fit\" adapts to content, \"auto\" uses default width */\n size?: \"fit\" | \"auto\";\n /** Whether clicking the backdrop dismisses the modal */\n isDismissable?: boolean;\n /** Prevents the Escape key from dismissing the modal */\n isKeyboardDismissDisabled?: boolean;\n /** Additional class for the modal panel */\n className?: string;\n /** Additional class for the inner content area */\n contentClassName?: string;\n /** Additional class for the backdrop overlay */\n overlayClassName?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ModalStylesProp;\n}\n\nfunction getModalChildDisplayName(child: React.ReactNode) {\n if (!React.isValidElement(child)) return null;\n const type = child.type as { displayName?: string };\n return type.displayName ?? null;\n}\n\n\n/**\n * Modal component that displays content in a centered dialog with a backdrop overlay.\n * Built with React Aria for full accessibility support including focus management,\n * keyboard handling, and screen reader announcements.\n */\nconst ModalBase = React.forwardRef<HTMLDivElement, ModalProps>(\n (\n {\n isOpen: controlledIsOpen,\n onOpenChange,\n title,\n children,\n footer,\n close = true,\n size = \"auto\",\n isDismissable = true,\n isKeyboardDismissDisabled = false,\n className,\n contentClassName,\n overlayClassName,\n styles,\n },\n ref\n ) => {\n const modalRef = React.useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = React.useState(false);\n const [isClosePressed, setIsClosePressed] = React.useState(false);\n const [isCloseHovered, setIsCloseHovered] = React.useState(false);\n const [isCloseFocused, setIsCloseFocused] = React.useState(false);\n const [isCloseFocusVisible, setIsCloseFocusVisible] = React.useState(false);\n\n const resolved = resolveModalStyles(styles);\n\n // Use uncontrolled state management via useOverlayTriggerState\n const state = useOverlayTriggerState({\n isOpen: controlledIsOpen,\n onOpenChange: onOpenChange,\n });\n\n // Handle mount to prevent hydration issues\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n // Use forwardRef callback to expose modalRef\n React.useImperativeHandle(ref, () => modalRef.current as HTMLDivElement);\n\n // Handle keyboard events and auto-focus\n useModalKeyboard(\n modalRef,\n state.isOpen,\n isDismissable,\n isKeyboardDismissDisabled,\n () => state.close()\n );\n\n // useDialog hook provides accessibility attributes and title handling\n const { dialogProps, titleProps } = useDialog({}, modalRef);\n const { focusProps: modalFocusProps, isFocused: isModalFocused, isFocusVisible: isModalFocusVisible } = useFocusRing();\n\n const handleClose = () => state.close();\n\n if (!mounted || !state.isOpen) return null;\n\n const handleCloseMouseDown = () => setIsClosePressed(true);\n const handleCloseMouseUp = () => setIsClosePressed(false);\n const handleCloseMouseLeave = () => {\n setIsClosePressed(false);\n setIsCloseHovered(false);\n };\n const handleCloseMouseEnter = () => setIsCloseHovered(true);\n const handleCloseFocus = (event: React.FocusEvent<HTMLButtonElement>) => {\n setIsCloseFocused(true);\n setIsCloseFocusVisible(event.currentTarget.matches(\":focus-visible\"));\n };\n const handleCloseBlur = () => {\n setIsCloseFocused(false);\n setIsCloseFocusVisible(false);\n };\n\n const childArray = React.Children.toArray(children);\n const slottedHeader: React.ReactNode[] = [];\n const slottedBody: React.ReactNode[] = [];\n const slottedFooter: React.ReactNode[] = [];\n const unslottedChildren: React.ReactNode[] = [];\n\n childArray.forEach((child) => {\n switch (getModalChildDisplayName(child)) {\n case \"Modal.Header\":\n slottedHeader.push(child);\n break;\n case \"Modal.Body\":\n slottedBody.push(child);\n break;\n case \"Modal.Footer\":\n slottedFooter.push(child);\n break;\n default:\n unslottedChildren.push(child);\n }\n });\n\n const headerContent =\n slottedHeader.length > 0 ? (\n slottedHeader\n ) : (\n (title || close) && (\n <div className={cn(\"header\", css.header, resolved.header)}>\n {title && (\n <h4 {...asElementProps<\"h4\">(titleProps)} className={cn(\"title\", css.title, resolved.title)}>\n {title}\n </h4>\n )}\n {!title && close && <div className={cn(\"spacer\", css.spacer, resolved.spacer)} />}\n {close && (\n <button\n onClick={handleClose}\n onMouseDown={handleCloseMouseDown}\n onMouseEnter={handleCloseMouseEnter}\n onMouseUp={handleCloseMouseUp}\n onMouseLeave={handleCloseMouseLeave}\n onFocus={handleCloseFocus}\n onBlur={handleCloseBlur}\n className={cn(\"close\", css.close, resolved.close)}\n aria-label=\"Close modal\"\n type=\"button\"\n data-pressed={isClosePressed ? \"true\" : \"false\"}\n data-hovered={isCloseHovered ? \"true\" : \"false\"}\n data-focused={isCloseFocused ? \"true\" : \"false\"}\n data-focus-visible={isCloseFocusVisible ? \"true\" : \"false\"}\n >\n <X className={cn(\"close-icon\", css[\"close-icon\"], resolved.closeIcon)} />\n </button>\n )}\n </div>\n )\n );\n\n const bodyContent =\n slottedBody.length > 0 ? (\n slottedBody\n ) : (\n <div className={cn(\"content\", css.content, contentClassName, resolved.content)}>\n {unslottedChildren}\n </div>\n );\n\n return createPortal(\n <div\n className={cn(\n \"modal\",\n \"fixed inset-0 z-9999 flex items-center justify-center\",\n overlayClassName,\n resolved.overlay\n )}\n >\n {/* Backdrop overlay - click outside to dismiss */}\n <div\n className={cn(\"backdrop\", css.backdrop, resolved.backdrop)}\n onMouseDown={() => { if (isDismissable) state.close(); }}\n />\n\n {/* Modal content */}\n <div\n {...asElementProps<\"div\">(mergeProps(dialogProps, modalFocusProps))}\n aria-modal=\"true\"\n ref={modalRef}\n className={cn(\n \"panel\",\n css.panel,\n className,\n resolved.root\n )}\n onClick={(e) => e.stopPropagation()}\n tabIndex={-1}\n data-open={state.isOpen || undefined}\n data-size={size}\n data-focused={isModalFocused ? \"true\" : \"false\"}\n data-focus-visible={isModalFocusVisible ? \"true\" : \"false\"}\n >\n {/* Header */}\n {headerContent}\n\n {/* Body */}\n {bodyContent}\n\n {/* Footer */}\n {slottedFooter.length > 0 && slottedFooter}\n {!slottedFooter.length && footer && (\n <div className={cn(\"footer\", css.footer, resolved.footer)}>\n {footer}\n </div>\n )}\n </div>\n </div>,\n document.body\n );\n }\n);\n\nModalBase.displayName = \"Modal\";\n\n/**\n * ModalHeader component for use with compound Modal pattern\n */\nconst ModalHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"header\", css.header, className)} {...props}>\n {children}\n </div>\n));\n\nModalHeader.displayName = \"Modal.Header\";\n\n/**\n * ModalBody component for use with compound Modal pattern\n */\nconst ModalBody = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"content\", css.content, className)} {...props}>\n {children}\n </div>\n));\n\nModalBody.displayName = \"Modal.Body\";\n\n/**\n * ModalFooter component for use with compound Modal pattern\n */\nconst ModalFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"footer\", css.footer, className)} {...props}>\n {children}\n </div>\n));\n\nModalFooter.displayName = \"Modal.Footer\";\n\nconst Modal = Object.assign(ModalBase, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n\nexport { Modal, ModalHeader, ModalBody, ModalFooter };\n",
|
|
5092
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--
|
|
5005
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--foreground);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-pressed=\"true\"] {\n transform: scale(0.92);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n border-radius: var(--radius-xs, 0.25rem);\n }\n }\n\n .close-icon {\n @apply h-5 w-5;\n }\n\n .content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n color: var(--foreground);\n }\n\n .content::-webkit-scrollbar {\n width: 6px;\n }\n\n .content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .content::-webkit-scrollbar-thumb {\n background-color: var(--background);\n border-radius: 3px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .content::-webkit-scrollbar-thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex shrink-0 items-center justify-between gap-4 px-6 py-4;\n background-color: var(--footer-background, var(--background));\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n /* Size variants */\n .panel[data-size=\"fit\"] {\n width: fit-content;\n }\n\n .panel[data-size=\"auto\"] {\n max-width: min(90vw, 28rem);\n }\n\n /* Media queries for smaller screens */\n @media (max-width: 640px) {\n .panel {\n margin: 1rem;\n }\n\n .content {\n max-height: calc(100vh - 10rem);\n }\n }\n}\n",
|
|
5093
5006
|
"cssTypes": "declare const styles: {\n backdrop: string;\n panel: string;\n header: string;\n title: string;\n spacer: string;\n close: string;\n \"close-icon\": string;\n content: string;\n footer: string;\n};\n\nexport default styles;\n"
|
|
5094
5007
|
},
|
|
5095
5008
|
"page": {
|
|
@@ -5104,62 +5017,62 @@ export const generatedSourceCode = {
|
|
|
5104
5017
|
},
|
|
5105
5018
|
"path": {
|
|
5106
5019
|
"tsx": "\"use client\";\n\nimport * as React from \"react\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Path.module.css\";\n\nexport interface PathItemStyleSlots {\n root?: StyleValue;\n link?: StyleValue;\n}\n\nexport type PathItemStylesProp = StylesProp<PathItemStyleSlots>;\n\nexport interface PathStyleSlots {\n root?: StyleValue;\n list?: StyleValue;\n separator?: StyleValue;\n}\n\nexport type PathStylesProp = StylesProp<PathStyleSlots>;\n\nfunction focusPathSibling(\n currentTarget: HTMLElement,\n direction: \"next\" | \"previous\" | \"first\" | \"last\"\n) {\n const listElement = currentTarget.closest('[data-path-list=\"true\"]');\n if (!listElement) {\n return;\n }\n\n const focusableItems = Array.from(\n listElement.querySelectorAll('[data-path-item-focus-surface=\"true\"]:not([data-disabled=\"true\"])')\n ) as HTMLElement[];\n\n if (!focusableItems.length) {\n return;\n }\n\n const currentIndex = focusableItems.indexOf(currentTarget);\n if (currentIndex === -1) {\n return;\n }\n\n let nextIndex = currentIndex;\n\n if (direction === \"next\") {\n nextIndex = (currentIndex + 1) % focusableItems.length;\n } else if (direction === \"previous\") {\n nextIndex = currentIndex === 0 ? focusableItems.length - 1 : currentIndex - 1;\n } else if (direction === \"first\") {\n nextIndex = 0;\n } else if (direction === \"last\") {\n nextIndex = focusableItems.length - 1;\n }\n\n focusableItems[nextIndex]?.focus();\n}\n\nconst resolvePathBaseStyles = createStylesResolver([\"root\", \"list\", \"separator\"] as const);\nconst resolvePathItemBaseStyles = createStylesResolver([\"root\", \"link\"] as const);\n\nfunction resolvePathStyles(styles: PathStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolvePathBaseStyles(styles);\n const { root, list, separator } = styles;\n return resolvePathBaseStyles({ root, list, separator });\n}\n\nfunction resolvePathItemStyles(styles: PathItemStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolvePathItemBaseStyles(styles);\n const { root, link } = styles;\n return resolvePathItemBaseStyles({ root, link });\n}\n\nexport interface PathItemProps {\n /** Content rendered inside the path item. */\n children: React.ReactNode;\n /** URL this path item navigates to. */\n href?: string;\n /** Called when the item is activated. */\n onPress?: () => void;\n /** Whether this item represents the current page. */\n isCurrent?: boolean;\n /** Whether the item is non-interactive. */\n isDisabled?: boolean;\n /** Additional CSS class names applied to the item root. */\n className?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: PathItemStylesProp;\n}\n\nexport interface PathProps {\n /** Path items rendered inside the ordered list. */\n children: React.ReactNode;\n /** Additional CSS class names applied to the path root. */\n className?: string;\n /** Custom separator rendered between path items. */\n separator?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: PathStylesProp;\n}\n\nconst PathItem = React.forwardRef<HTMLLIElement, PathItemProps>(\n (\n {\n href,\n onPress,\n children,\n isCurrent = false,\n isDisabled = false,\n className,\n styles,\n },\n ref\n ) => {\n const itemRef = React.useRef<HTMLLIElement>(null);\n const mergedRef = useMergeRefs(ref, itemRef);\n const isInteractive = !isCurrent && !isDisabled && Boolean(href || onPress);\n const [isPressed, setIsPressed] = React.useState(false);\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: !isInteractive });\n const resolved = resolvePathItemStyles(styles);\n\n const handleMouseDown = React.useCallback(() => {\n if (isInteractive) {\n setIsPressed(true);\n }\n }, [isInteractive]);\n\n const handleMouseUp = React.useCallback(() => {\n setIsPressed(false);\n }, []);\n\n const handleMouseLeave = React.useCallback(() => {\n setIsPressed(false);\n }, []);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === \"ArrowRight\") {\n event.preventDefault();\n focusPathSibling(event.currentTarget, \"next\");\n return;\n }\n\n if (event.key === \"ArrowLeft\") {\n event.preventDefault();\n focusPathSibling(event.currentTarget, \"previous\");\n return;\n }\n\n if (event.key === \"Home\") {\n event.preventDefault();\n focusPathSibling(event.currentTarget, \"first\");\n return;\n }\n\n if (event.key === \"End\") {\n event.preventDefault();\n focusPathSibling(event.currentTarget, \"last\");\n return;\n }\n\n if (!isInteractive) {\n return;\n }\n\n if (event.key === \" \" || event.key === \"Enter\") {\n setIsPressed(true);\n }\n },\n [isInteractive]\n );\n\n const handleKeyUp = React.useCallback((event: React.KeyboardEvent<HTMLElement>) => {\n if (event.key === \" \" || event.key === \"Enter\") {\n setIsPressed(false);\n }\n }, []);\n\n const mergedInteractionProps = mergeProps(focusProps, hoverProps, {\n onMouseDown: handleMouseDown,\n onMouseUp: handleMouseUp,\n onMouseLeave: handleMouseLeave,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }) as unknown as Record<string, unknown>;\n\n const {\n onChange: _onChange,\n onChangeCapture: _onChangeCapture,\n ...interactionProps\n } = mergedInteractionProps;\n\n const stateProps = {\n \"data-selected\": isCurrent ? \"true\" : undefined,\n \"data-disabled\": isDisabled ? \"true\" : undefined,\n \"data-focused\": isFocused ? \"true\" : undefined,\n \"data-focus-visible\": isFocusVisible ? \"true\" : undefined,\n \"data-hovered\": isHovered ? \"true\" : undefined,\n \"data-pressed\": isPressed ? \"true\" : undefined,\n \"data-path-item-focus-surface\": \"true\" as const,\n \"aria-current\": isCurrent ? (\"page\" as const) : undefined,\n };\n\n const surfaceClassName = cn(\"path-link\", css.link, resolved.link);\n const focusableTabIndex = isDisabled ? -1 : isCurrent ? 0 : undefined;\n\n return (\n <li\n ref={mergedRef}\n className={cn(\"path-item\", css.item, className, resolved.root)}\n data-selected={isCurrent ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n >\n {isInteractive && href ? (\n <a\n {...(interactionProps as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n href={href}\n className={surfaceClassName}\n tabIndex={focusableTabIndex}\n {...stateProps}\n onClick={(event) => {\n if (onPress) {\n event.preventDefault();\n onPress();\n }\n }}\n >\n {children}\n </a>\n ) : isInteractive ? (\n <button\n {...(interactionProps as React.ButtonHTMLAttributes<HTMLButtonElement>)}\n type=\"button\"\n className={surfaceClassName}\n tabIndex={focusableTabIndex}\n onClick={onPress}\n {...stateProps}\n >\n {children}\n </button>\n ) : (\n <span\n {...(interactionProps as React.HTMLAttributes<HTMLSpanElement>)}\n className={surfaceClassName}\n tabIndex={focusableTabIndex}\n {...stateProps}\n >\n {children}\n </span>\n )}\n </li>\n );\n }\n);\n\nPathItem.displayName = \"Path.Item\";\n\nexport interface PathComponent\n extends React.ForwardRefExoticComponent<PathProps & React.RefAttributes<HTMLElement>> {\n Item: typeof PathItem;\n}\n\nconst Path = Object.assign(\n React.forwardRef<HTMLElement, PathProps>(\n ({ children, className, separator, styles }, ref) => {\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const navRef = React.useRef<HTMLElement>(null);\n const mergedRef = useMergeRefs(ref, navRef);\n const childArray = React.Children.toArray(children);\n const childCount = childArray.length;\n const resolved = resolvePathStyles(styles);\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: navRef,\n surfaceSelector: '[data-path-item-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n dependencies: [childCount, Boolean(separator)],\n });\n\n return (\n <div ref={scopeRef} className={cn(\"path-scope\", scopeProps.className)}>\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <nav\n ref={mergedRef}\n className={cn(\"path\", css.path, className, resolved.root)}\n aria-label=\"Path\"\n >\n <ol\n className={cn(\"path-list\", css.list, resolved.list)}\n data-path-list=\"true\"\n data-separator={separator ? \"custom\" : undefined}\n >\n {React.Children.map(childArray, (child, index) => {\n const isLastChild = index === childCount - 1;\n\n if (React.isValidElement(child)) {\n const element = React.cloneElement(\n child as React.ReactElement<PathItemProps>,\n { isCurrent: isLastChild }\n );\n\n if (separator && !isLastChild) {\n return (\n <React.Fragment key={child.key ?? index}>\n {element}\n <li\n className={cn(\"path-separator\", css.separator, resolved.separator)}\n aria-hidden=\"true\"\n >\n {separator}\n </li>\n </React.Fragment>\n );\n }\n\n return element;\n }\n\n return child;\n })}\n </ol>\n </nav>\n </div>\n );\n }\n ),\n {\n Item: PathItem,\n }\n) as PathComponent;\n\nPath.displayName = \"Path\";\n\nexport { Path, PathItem };\n",
|
|
5107
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .path {\n @apply block;\n }\n\n .list {\n @apply m-0 flex flex-wrap items-center gap-2 p-0;\n list-style: none;\n }\n\n .list[data-separator=\"custom\"] .item:not(:last-child)::after {\n content: none;\n }\n\n .item {\n @apply m-0 flex items-center gap-2 p-0;\n }\n\n .item:not(:last-child)::after {\n content: \"/\";\n margin-inline-start: 0.5rem;\n color: var(--
|
|
5020
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .path {\n @apply block;\n }\n\n .list {\n @apply m-0 flex flex-wrap items-center gap-2 p-0;\n list-style: none;\n }\n\n .list[data-separator=\"custom\"] .item:not(:last-child)::after {\n content: none;\n }\n\n .item {\n @apply m-0 flex items-center gap-2 p-0;\n border-radius: var(--radius-sm, 0.375rem);\n }\n\n .item:not(:last-child)::after {\n content: \"/\";\n margin-inline-start: 0.5rem;\n color: var(--foreground);\n pointer-events: none;\n user-select: none;\n }\n\n .separator {\n @apply m-0 flex items-center p-0;\n list-style: none;\n color: var(--foreground);\n pointer-events: none;\n user-select: none;\n }\n\n .link {\n @apply relative cursor-pointer px-2 py-1;\n border: 0;\n /* Inherit the item radius so the focus ring matches rounded breadcrumbs. */\n border-radius: inherit;\n background-color: var(--background);\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--leading-normal, 1.5);\n text-decoration: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n button.link {\n font: inherit;\n }\n\n .link:focus,\n .link:focus-visible {\n outline: none;\n }\n\n .link[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-selected=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .link[data-selected=\"true\"] {\n cursor: default;\n }\n\n .link[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity);\n }\n}\n",
|
|
5108
5021
|
"cssTypes": "export interface Styles {\n \"path\": string;\n \"list\": string;\n \"item\": string;\n \"separator\": string;\n \"link\": string;\n}\n\nexport default styles;\n"
|
|
5109
5022
|
},
|
|
5110
5023
|
"popover": {
|
|
5111
|
-
"tsx": "\"use client\"\n\nimport React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useOverlayTrigger, useDialog, mergeProps } from \"react-aria\";\nimport { useOverlayTriggerState } from \"react-stately\";\nimport { useFloating } from \"../../hooks/useFloat/react/useFloating\";\nimport { flip } from \"../../hooks/useFloat/core/middleware/flip\";\nimport { offset } from \"../../hooks/useFloat/core/middleware/offset\";\nimport { shift } from \"../../hooks/useFloat/core/middleware/shift\";\nimport { autoUpdate } from \"../../hooks/useFloat/dom/autoUpdate\";\nimport { cn } from \"./utils\";\nimport { type StyleValue } from \"./utils\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Frame } from \"../Frame\";\nimport css from \"./Popover.module.css\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\n\nconst ARROW_PATH = \"M 0 0 L 6 -12 L 12 0\";\nconst ARROW_WIDTH = 12;\nconst POPOVER_GAP = 2;\nconst ARROW_POSITIONING_SIZE = 6;\n\ntype PopoverPosition = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nconst getFrameSide = (position: PopoverPosition): \"top\" | \"right\" | \"bottom\" | \"left\" => {\n switch (position) {\n case \"top\":\n return \"bottom\";\n case \"bottom\":\n return \"top\";\n case \"left\":\n return \"right\";\n case \"right\":\n return \"left\";\n }\n};\n\n/**\n * Maps placement to initial transform for directional entrance animation.\n * When animating in, the component slides from its placement direction toward the center.\n * For example, \"top\" placement slides up (-Y) and fades in.\n */\nconst getInitialTransform = (placement: string): string => {\n switch (placement) {\n case \"top\":\n return \"translateY(3px) scale(0.95)\";\n case \"bottom\":\n return \"translateY(-3px) scale(0.95)\";\n case \"left\":\n return \"translateX(3px) scale(0.95)\";\n case \"right\":\n return \"translateX(-3px) scale(0.95)\";\n default:\n return \"scale(0.95)\";\n }\n};\n\ninterface PopoverStyleSlots {\n root?: StyleValue;\n content?: StyleValue;\n trigger?: StyleValue;\n frame?: StyleValue;\n}\n\ntype PopoverStylesProp = StylesProp<PopoverStyleSlots>;\n\nexport interface PopoverProps {\n children: React.ReactNode;\n /** Content to display inside the popover panel */\n content: React.ReactNode;\n /** Preferred side of the trigger where the popover appears */\n position?: PopoverPosition;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: PopoverStylesProp;\n /** Additional CSS class for the trigger element. */\n className?: string;\n /** Controlled open state */\n isOpen?: boolean;\n /** Called when the popover opens or closes */\n onOpenChange?: (isOpen: boolean) => void;\n /** Whether to render a directional arrow pointing at the trigger */\n showArrow?: boolean;\n}\n\nconst Popover = React.forwardRef<HTMLDivElement, PopoverProps>(\n ({ children, content, position = \"bottom\", styles, className: externalClassName, isOpen: controlledIsOpen, onOpenChange, showArrow = false }, ref) => {\n\n const resolvePopoverBaseStyles = createStylesResolver([\n 'root',\n 'content',\n 'trigger',\n 'frame',\n ] as const);\n\n const resolved = resolvePopoverBaseStyles(styles);\n\n const triggerRef = React.useRef<HTMLDivElement>(null);\n const popoverContentRef = React.useRef<HTMLDivElement>(null);\n const [isAnimating, setIsAnimating] = React.useState(false);\n const [isExiting, setIsExiting] = React.useState(false);\n\n const state = useOverlayTriggerState({\n isOpen: controlledIsOpen,\n onOpenChange,\n });\n\n const { triggerProps, overlayProps } = useOverlayTrigger({ type: \"dialog\" }, state, triggerRef);\n const { dialogProps } = useDialog({}, popoverContentRef);\n\n const placementMap: Record<PopoverPosition, \"top\" | \"bottom\" | \"left\" | \"right\"> = {\n top: \"top\",\n bottom: \"bottom\",\n left: \"left\",\n right: \"right\",\n };\n\n const { refs, floatingStyles, placement } = useFloating({\n placement: placementMap[position],\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(POPOVER_GAP + ARROW_POSITIONING_SIZE),\n flip(),\n shift({ padding: 8 }),\n ],\n });\n\n const isPositioned = floatingStyles.transform !== undefined;\n\n // Trigger animation when popover is opened and positioned\n React.useEffect(() => {\n if (state.isOpen && isPositioned) {\n setIsExiting(false);\n setIsAnimating(true);\n }\n }, [state.isOpen, isPositioned]);\n\n // Handle exit animation when closing\n React.useEffect(() => {\n if (!state.isOpen && isAnimating) {\n // First, enable exit mode so element stays in DOM\n setIsExiting(true);\n\n requestAnimationFrame(() => setIsAnimating(false));\n const timer = setTimeout(() => setIsExiting(false), 50)\n return () => clearTimeout(timer);\n }\n }, [state.isOpen, isAnimating]);\n\n React.useLayoutEffect(() => {\n refs.setReference(triggerRef.current);\n }, [refs]);\n\n React.useEffect(() => {\n if (!state.isOpen) return;\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n triggerRef.current &&\n !triggerRef.current.contains(target) &&\n popoverContentRef.current &&\n !popoverContentRef.current.contains(target)\n ) {\n state.close();\n }\n };\n document.addEventListener(\"click\", handleClickOutside);\n return () => document.removeEventListener(\"click\", handleClickOutside);\n }, [state.isOpen, state]);\n\n React.useEffect(() => {\n if (!state.isOpen) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") state.close();\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [state.isOpen, state]);\n\n const mergedRef = useMergeRefs(triggerRef, refs.setReference, ref);\n\n const mergedContentRef = useMergeRefs(popoverContentRef, refs.setFloating);\n\n // Convert React Aria's onPress to onClick for native HTML elements\n const nativeProps = React.useMemo(() => {\n const props: any = { ...triggerProps };\n if (props.onPress && typeof props.onPress === 'function') {\n const onPress = props.onPress;\n props.onClick = (e: React.MouseEvent) => {\n onPress({ target: e.currentTarget, type: 'press', pointerType: 'mouse', ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey, altKey: e.altKey });\n };\n delete props.onPress;\n }\n return props;\n }, [triggerProps]);\n\n const triggerElement = React.isValidElement(children)\n ? React.cloneElement(children as React.ReactElement<{ className?: string; ref?: React.Ref<HTMLButtonElement | HTMLDivElement> }>, {\n ...nativeProps,\n className: cn((children as React.ReactElement<{ className?: string }>).props.className, externalClassName, css.trigger, resolved.trigger),\n ref: mergedRef,\n })\n : (\n <span ref={mergedRef} {...nativeProps} className={cn(css.trigger, externalClassName, resolved.trigger)}>\n {children}\n </span>\n );\n\n return (\n <>\n {triggerElement}\n {(state.isOpen || isExiting) &&\n createPortal(\n <div\n ref={mergedContentRef}\n {...asElementProps<\"div\">(mergeProps(overlayProps, dialogProps))}\n className={cn(css.root, resolved.root)}\n style={{\n ...floatingStyles,\n }}\n >\n <div\n className={cn('content', css.content, resolved.content)}\n style={{\n opacity: isAnimating ? 1 : 0,\n transform: isAnimating ? \"scale(1)\" : getInitialTransform(placement),\n pointerEvents: isAnimating ? 'auto' : 'none',\n }}\n >\n <Frame\n role=\"dialog\"\n side={showArrow ? getFrameSide(position) : position}\n shapeMode={showArrow ? \"extend\" : undefined}\n path={showArrow ? ARROW_PATH : undefined}\n pathWidth={showArrow ? ARROW_WIDTH : undefined}\n >\n <div className={cn('frame', css.frame, resolved.frame)}>\n {content}\n </div>\n </Frame>\n </div>\n </div>,\n document.body\n )}\n </>\n );\n }\n);\n\nPopover.displayName = \"Popover\";\n\nexport { Popover };\n",
|
|
5112
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .trigger {\n @apply inline-block;\n }\n\n .root {\n @apply absolute;\n pointer-events: none;\n z-index: 50;\n }\n\n .content {\n --frame-fill: var(--background);\n --frame-stroke-color: var(--border);\n --frame-radius: 8px;\n opacity: 0;\n transform: scale(0.95);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n pointer-events: none;\n min-width: 200px;\n max-width: 400px;\n
|
|
5024
|
+
"tsx": "\"use client\"\n\nimport React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useOverlayTrigger, useDialog, mergeProps } from \"react-aria\";\nimport { useOverlayTriggerState } from \"react-stately\";\nimport { useFloating } from \"../../hooks/useFloat/react/useFloating\";\nimport { flip } from \"../../hooks/useFloat/core/middleware/flip\";\nimport { offset } from \"../../hooks/useFloat/core/middleware/offset\";\nimport { shift } from \"../../hooks/useFloat/core/middleware/shift\";\nimport { autoUpdate } from \"../../hooks/useFloat/dom/autoUpdate\";\nimport { cn } from \"./utils\";\nimport { type StyleValue } from \"./utils\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Frame } from \"../Frame\";\nimport css from \"./Popover.module.css\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\n\nconst ARROW_PATH = \"M 0 0 L 6 -12 L 12 0\";\nconst ARROW_WIDTH = 12;\nconst POPOVER_GAP = 2;\nconst ARROW_POSITIONING_SIZE = 6;\n\ntype PopoverPosition = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nconst getFrameSide = (position: PopoverPosition): \"top\" | \"right\" | \"bottom\" | \"left\" => {\n switch (position) {\n case \"top\":\n return \"bottom\";\n case \"bottom\":\n return \"top\";\n case \"left\":\n return \"right\";\n case \"right\":\n return \"left\";\n }\n};\n\n/**\n * Maps placement to initial transform for directional entrance animation.\n * When animating in, the component slides from its placement direction toward the center.\n * For example, \"top\" placement slides up (-Y) and fades in.\n */\nconst getInitialTransform = (placement: string): string => {\n switch (placement) {\n case \"top\":\n return \"translateY(3px) scale(0.95)\";\n case \"bottom\":\n return \"translateY(-3px) scale(0.95)\";\n case \"left\":\n return \"translateX(3px) scale(0.95)\";\n case \"right\":\n return \"translateX(-3px) scale(0.95)\";\n default:\n return \"scale(0.95)\";\n }\n};\n\ninterface PopoverStyleSlots {\n root?: StyleValue;\n content?: StyleValue;\n trigger?: StyleValue;\n frame?: StyleValue;\n}\n\ntype PopoverStylesProp = StylesProp<PopoverStyleSlots>;\n\nexport interface PopoverProps {\n children: React.ReactNode;\n /** Content to display inside the popover panel */\n content: React.ReactNode;\n /** Preferred side of the trigger where the popover appears */\n position?: PopoverPosition;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: PopoverStylesProp;\n /** Additional CSS class for the trigger element. */\n className?: string;\n /** Controlled open state */\n isOpen?: boolean;\n /** Called when the popover opens or closes */\n onOpenChange?: (isOpen: boolean) => void;\n /** Whether to render a directional arrow pointing at the trigger */\n showArrow?: boolean;\n}\n\nconst Popover = React.forwardRef<HTMLDivElement, PopoverProps>(\n ({ children, content, position = \"bottom\", styles, className: externalClassName, isOpen: controlledIsOpen, onOpenChange, showArrow = false }, ref) => {\n\n const resolvePopoverBaseStyles = createStylesResolver([\n 'root',\n 'content',\n 'trigger',\n 'frame',\n ] as const);\n\n const resolved = resolvePopoverBaseStyles(styles);\n\n const triggerRef = React.useRef<HTMLDivElement>(null);\n const popoverContentRef = React.useRef<HTMLDivElement>(null);\n const [isAnimating, setIsAnimating] = React.useState(false);\n const [isExiting, setIsExiting] = React.useState(false);\n\n const state = useOverlayTriggerState({\n isOpen: controlledIsOpen,\n onOpenChange,\n });\n\n const { triggerProps, overlayProps } = useOverlayTrigger({ type: \"dialog\" }, state, triggerRef);\n const { dialogProps } = useDialog({}, popoverContentRef);\n\n const placementMap: Record<PopoverPosition, \"top\" | \"bottom\" | \"left\" | \"right\"> = {\n top: \"top\",\n bottom: \"bottom\",\n left: \"left\",\n right: \"right\",\n };\n\n const { refs, floatingStyles, placement } = useFloating({\n placement: placementMap[position],\n whileElementsMounted: autoUpdate,\n middleware: [\n offset(POPOVER_GAP + ARROW_POSITIONING_SIZE),\n flip(),\n shift({ padding: 8 }),\n ],\n });\n\n const isPositioned = floatingStyles.transform !== undefined;\n\n // Trigger animation when popover is opened and positioned\n React.useEffect(() => {\n if (state.isOpen && isPositioned) {\n setIsExiting(false);\n setIsAnimating(true);\n }\n }, [state.isOpen, isPositioned]);\n\n // Handle exit animation when closing\n React.useEffect(() => {\n if (!state.isOpen && isAnimating) {\n // First, enable exit mode so element stays in DOM\n setIsExiting(true);\n\n requestAnimationFrame(() => setIsAnimating(false));\n const timer = setTimeout(() => setIsExiting(false), 50)\n return () => clearTimeout(timer);\n }\n }, [state.isOpen, isAnimating]);\n\n React.useLayoutEffect(() => {\n refs.setReference(triggerRef.current);\n }, [refs]);\n\n React.useEffect(() => {\n if (!state.isOpen) return;\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n triggerRef.current &&\n !triggerRef.current.contains(target) &&\n popoverContentRef.current &&\n !popoverContentRef.current.contains(target)\n ) {\n state.close();\n }\n };\n document.addEventListener(\"click\", handleClickOutside);\n return () => document.removeEventListener(\"click\", handleClickOutside);\n }, [state.isOpen, state]);\n\n React.useEffect(() => {\n if (!state.isOpen) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") state.close();\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [state.isOpen, state]);\n\n const mergedRef = useMergeRefs(triggerRef, refs.setReference, ref);\n\n const mergedContentRef = useMergeRefs(popoverContentRef, refs.setFloating);\n\n // Convert React Aria's onPress to onClick for native HTML elements\n const nativeProps = React.useMemo(() => {\n const props: any = { ...triggerProps };\n if (props.onPress && typeof props.onPress === 'function') {\n const onPress = props.onPress;\n props.onClick = (e: React.MouseEvent) => {\n onPress({ target: e.currentTarget, type: 'press', pointerType: 'mouse', ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey, altKey: e.altKey });\n };\n delete props.onPress;\n }\n return props;\n }, [triggerProps]);\n\n const triggerElement = React.isValidElement(children)\n ? React.cloneElement(children as React.ReactElement<{ className?: string; ref?: React.Ref<HTMLButtonElement | HTMLDivElement> }>, {\n ...nativeProps,\n className: cn((children as React.ReactElement<{ className?: string }>).props.className, externalClassName, css.trigger, resolved.trigger),\n ref: mergedRef,\n })\n : (\n <span ref={mergedRef} {...nativeProps} className={cn(css.trigger, externalClassName, resolved.trigger)}>\n {children}\n </span>\n );\n\n return (\n <>\n {triggerElement}\n {(state.isOpen || isExiting) &&\n createPortal(\n <div\n ref={mergedContentRef}\n {...asElementProps<\"div\">(mergeProps(overlayProps, dialogProps))}\n className={cn(\"popover\", css.root, resolved.root)}\n style={{\n ...floatingStyles,\n }}\n >\n <div\n className={cn('content', css.content, resolved.content)}\n style={{\n opacity: isAnimating ? 1 : 0,\n transform: isAnimating ? \"scale(1)\" : getInitialTransform(placement),\n pointerEvents: isAnimating ? 'auto' : 'none',\n }}\n >\n <Frame\n role=\"dialog\"\n side={showArrow ? getFrameSide(position) : position}\n shapeMode={showArrow ? \"extend\" : undefined}\n path={showArrow ? ARROW_PATH : undefined}\n pathWidth={showArrow ? ARROW_WIDTH : undefined}\n >\n <div className={cn('frame', css.frame, resolved.frame)}>\n {content}\n </div>\n </Frame>\n </div>\n </div>,\n document.body\n )}\n </>\n );\n }\n);\n\nPopover.displayName = \"Popover\";\n\nexport { Popover };\n",
|
|
5025
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .trigger {\n @apply inline-block;\n }\n\n .root {\n @apply absolute;\n pointer-events: none;\n z-index: 50;\n }\n\n .content {\n --frame-fill: var(--background);\n --frame-stroke-color: var(--background-border);\n --frame-radius: 8px;\n opacity: 0;\n transform: scale(0.95);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n pointer-events: none;\n min-width: 200px;\n max-width: 400px;\n }\n\n .content[data-visible=\"true\"] {\n opacity: 1;\n transform: scale(1);\n pointer-events: auto;\n }\n\n .content[data-instant] {\n transition: none;\n }\n\n .frame {\n @apply flex items-center gap-1.5 p-2.5;\n color: var(--foreground);\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n }\n}\n",
|
|
5113
5026
|
"cssTypes": "export interface Styles {\n trigger: string;\n root: string;\n content: string;\n frame: string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
5114
5027
|
},
|
|
5115
5028
|
"progress": {
|
|
5116
|
-
"tsx": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Progress.module.css\";\n\nexport interface ProgressStyleSlots {\n root?: StyleValue;\n labelRow?: StyleValue;\n label?: StyleValue;\n value?: StyleValue;\n progress?: StyleValue;\n fill?: StyleValue;\n}\n\nexport type ProgressStylesProp = StylesProp<ProgressStyleSlots>;\n\nexport interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Current progress value */\n value?: number;\n /** Maximum value that represents 100% */\n max?: number;\n /** Visual color variant indicating progress state */\n variant?: string;\n /** Whether to show an infinite loading animation instead of a fixed value */\n indeterminate?: boolean;\n /** Accessible label describing what is progressing */\n label?: string;\n /** Whether to display the percentage value next to the label */\n showValue?: boolean;\n /** Whether to show a shimmer animation on the progress fill */\n animated?: boolean;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ProgressStylesProp;\n}\n\nconst resolveProgressBaseStyles = createStylesResolver([\n 'root',\n 'labelRow',\n 'label',\n 'value',\n 'progress',\n 'fill',\n] as const);\n\nfunction resolveProgressStyles(styles: ProgressStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveProgressBaseStyles(styles);\n }\n\n const { root, labelRow, label, value, progress, fill } = styles;\n return resolveProgressBaseStyles({ root, labelRow, label, value, progress, fill });\n}\n\nconst Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n className,\n value = 0,\n max = 100,\n variant = \"default\",\n indeterminate = false,\n label,\n showValue = false,\n animated = false,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const clampedValue = Math.min(Math.max(value, 0), max);\n const percentage = (clampedValue / max) * 100;\n const hasLabelContent = label || showValue;\n\n const resolved = resolveProgressStyles(stylesProp);\n\n return (\n <div\n className={cn(\"progress\", css.wrapper, resolved.root)}\n data-has-label={hasLabelContent ? \"true\" : \"false\"}\n >\n {hasLabelContent && (\n <div className={cn(css['label-row'], resolved.labelRow)}>\n {label && (\n <span className={cn(css.label, resolved.label)}>\n {label}\n </span>\n )}\n {showValue && !indeterminate && (\n <span className={cn(css.value, resolved.value)}>{Math.round(percentage)}%</span>\n )}\n </div>\n )}\n <div\n ref={ref}\n role=\"progressbar\"\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label}\n className={cn(\"bar\", variant, css.bar, className, resolved.progress)}\n data-variant={variant}\n data-indeterminate={indeterminate ? \"true\" : \"false\"}\n {...props}\n >\n <div\n className={cn(css.fill, resolved.fill)}\n data-animated={animated || indeterminate ? \"true\" : \"false\"}\n data-indeterminate={indeterminate ? \"true\" : \"false\"}\n style={indeterminate ? undefined : { width: `${percentage}%` }}\n />\n </div>\n </div>\n );\n }\n);\n\nProgress.displayName = \"Progress\";\n\nexport { Progress };\n",
|
|
5117
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .bar {\n @apply relative w-full overflow-hidden;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n }\n\n .bar { height: 0.5rem; }\n\n .fill {\n @apply h-full;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--
|
|
5029
|
+
"tsx": "\"use client\";\n\nimport * as React from \"react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Progress.module.css\";\n\nexport interface ProgressStyleSlots {\n root?: StyleValue;\n labelRow?: StyleValue;\n label?: StyleValue;\n value?: StyleValue;\n progress?: StyleValue;\n fill?: StyleValue;\n}\n\nexport type ProgressStylesProp = StylesProp<ProgressStyleSlots>;\n\nexport interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Current progress value */\n value?: number;\n /** Maximum value that represents 100% */\n max?: number;\n /** Visual color variant indicating progress state */\n variant?: string;\n /** Whether to show an infinite loading animation instead of a fixed value */\n indeterminate?: boolean;\n /** Accessible label describing what is progressing */\n label?: string;\n /** Whether to display the percentage value next to the label */\n showValue?: boolean;\n /** Whether to show a shimmer animation on the progress fill */\n animated?: boolean;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ProgressStylesProp;\n}\n\nconst resolveProgressBaseStyles = createStylesResolver([\n 'root',\n 'labelRow',\n 'label',\n 'value',\n 'progress',\n 'fill',\n] as const);\n\nfunction resolveProgressStyles(styles: ProgressStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveProgressBaseStyles(styles);\n }\n\n const { root, labelRow, label, value, progress, fill } = styles;\n return resolveProgressBaseStyles({ root, labelRow, label, value, progress, fill });\n}\n\nconst Progress = React.forwardRef<HTMLDivElement, ProgressProps>(\n (\n {\n className,\n value = 0,\n max = 100,\n variant = \"default\",\n indeterminate = false,\n label,\n showValue = false,\n animated = false,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const clampedValue = Math.min(Math.max(value, 0), max);\n const percentage = (clampedValue / max) * 100;\n const hasLabelContent = label || showValue;\n\n const resolved = resolveProgressStyles(stylesProp);\n\n return (\n <div\n className={cn(\"progress\", css.wrapper, resolved.root)}\n data-has-label={hasLabelContent ? \"true\" : \"false\"}\n >\n {hasLabelContent && (\n <div className={cn(css['label-row'], resolved.labelRow)}>\n {label && (\n <span className={cn(css.label, resolved.label)}>\n {label}\n </span>\n )}\n {showValue && !indeterminate && (\n <span className={cn(css.value, resolved.value)}>{Math.round(percentage)}%</span>\n )}\n </div>\n )}\n <div\n ref={ref}\n role=\"progressbar\"\n aria-valuenow={indeterminate ? undefined : clampedValue}\n aria-valuemin={0}\n aria-valuemax={max}\n aria-label={label}\n className={cn(\"bar\", variant, css.bar, className, resolved.progress)}\n data-variant={variant}\n data-indeterminate={indeterminate ? \"true\" : \"false\"}\n {...props}\n >\n <div\n className={cn(\"fill\", css.fill, resolved.fill)}\n data-animated={animated || indeterminate ? \"true\" : \"false\"}\n data-indeterminate={indeterminate ? \"true\" : \"false\"}\n style={indeterminate ? undefined : { width: `${percentage}%` }}\n />\n </div>\n </div>\n );\n }\n);\n\nProgress.displayName = \"Progress\";\n\nexport { Progress };\n",
|
|
5030
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .bar {\n @apply relative w-full overflow-hidden;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n }\n\n .bar { height: 0.5rem; }\n\n .fill {\n @apply h-full;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n transition: width 300ms var(--ease-snappy-pop);\n }\n\n .fill[data-animated=\"true\"] {\n animation: pulse 2s var(--ease-gentle-ease) infinite;\n }\n\n .fill[data-indeterminate=\"true\"] {\n width: 33.333%;\n animation: progress-indeterminate 1.5s var(--ease-gentle-ease) infinite;\n }\n\n .wrapper {\n @apply w-full;\n }\n\n .wrapper[data-has-label=\"true\"] {\n @apply space-y-1;\n }\n\n .label-row {\n @apply flex items-center justify-between;\n font-size: var(--text-sm);\n color: var(--foreground);\n }\n\n .label {\n user-select: none;\n }\n\n .value {\n font-variant-numeric: tabular-nums;\n }\n\n @keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n }\n\n @keyframes progress-indeterminate {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(400%); }\n }\n}\n",
|
|
5118
5031
|
"cssTypes": "export interface Styles {\n bar: string;\n sm: string;\n md: string;\n lg: string;\n fill: string;\n wrapper: string;\n \"label-row\": string;\n label: string;\n value: string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
5119
5032
|
},
|
|
5120
5033
|
"radio": {
|
|
5121
|
-
"tsx": "\"use client\";\n\nimport React, { useId, createContext, useContext } from \"react\";\nimport { useRadioGroupState } from \"react-stately\";\n\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useRadioGroup, useRadio } from \"@react-aria/radio\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Radio.module.css\";\n\ntype Size = \"sm\" | \"md\" | \"lg\";\n\nexport interface RadioStyleSlots {\n root?: StyleValue;\n item?: StyleValue;\n input?: StyleValue;\n dot?: StyleValue;\n label?: StyleValue;\n description?: StyleValue;\n helperText?: StyleValue;\n}\n\nexport type RadioStylesProp = StylesProp<RadioStyleSlots>;\n\nconst resolveRadioBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"input\",\n \"dot\",\n \"label\",\n \"description\",\n \"helperText\",\n] as const);\n\nfunction resolveRadioStyles(styles: RadioStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveRadioBaseStyles(styles);\n }\n\n const { root, item, input, dot, label, description, helperText } = styles;\n return resolveRadioBaseStyles({ root, item, input, dot, label, description, helperText });\n}\n\ninterface RadioGroupContextType {\n state?: ReturnType<typeof useRadioGroupState>;\n disabled?: boolean;\n size?: Size;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextType | undefined>(undefined);\n\nconst useRadioGroupContext = () => {\n const context = useContext(RadioGroupContext);\n return context;\n};\n\nexport interface RadioGroupStyleSlots {\n root?: StyleValue;\n label?: StyleValue;\n description?: StyleValue;\n group?: StyleValue;\n}\n\nexport type RadioGroupStylesProp = StylesProp<RadioGroupStyleSlots>;\n\nconst resolveRadioGroupBaseStyles = createStylesResolver([\n \"root\",\n \"label\",\n \"description\",\n \"group\",\n] as const);\n\nfunction resolveRadioGroupStyles(styles: RadioGroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveRadioGroupBaseStyles(styles);\n }\n\n const { root, label, description, group } = styles;\n return resolveRadioGroupBaseStyles({ root, label, description, group });\n}\n\nexport interface RadioGroupProps {\n /** Controlled selected radio value */\n value?: string;\n /** Initial selected value for uncontrolled usage */\n defaultValue?: string;\n /** Called when the selected value changes */\n onValueChange?: (value: string) => void;\n /** Whether all radios in the group are disabled */\n disabled?: boolean;\n /** Size of all radio buttons in the group */\n size?: Size;\n children: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Accessible label for the radio group */\n label?: string;\n /** Descriptive text shown below the group label */\n description?: string;\n /** Classes applied to the root or named slots */\n styles?: RadioGroupStylesProp;\n}\n\nconst RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value: controlledValue,\n defaultValue,\n onValueChange,\n disabled = false,\n size = \"md\",\n children,\n className,\n label,\n description,\n styles: stylesProp,\n },\n ref\n ) => {\n const state = useRadioGroupState({\n value: controlledValue,\n defaultValue,\n onChange: onValueChange,\n isDisabled: disabled,\n });\n\n useRadioGroup(\n {\n isDisabled: disabled,\n label,\n description,\n },\n state\n );\n\n const resolved = resolveRadioGroupStyles(stylesProp);\n\n return (\n <RadioGroupContext.Provider value={{ state, disabled, size }}>\n <div ref={ref} className={cn(\"radio-group\", className, resolved.root)} role=\"group\">\n {label && (\n <label\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n {label}\n </label>\n )}\n {description && (\n <p className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}>\n {description}\n </p>\n )}\n <div className={cn(css[\"radio-items\"], resolved.group)}>{children}</div>\n </div>\n </RadioGroupContext.Provider>\n );\n }\n);\n\nRadioGroup.displayName = \"RadioGroup\";\n\nexport interface RadioItemProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\"> {\n /** Size of the radio button */\n size?: Size;\n /** Label text or element displayed next to the radio */\n label?: React.ReactNode;\n /** Secondary description shown below the label */\n description?: React.ReactNode;\n /** Helper text shown below the radio item */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Whether to apply error styling */\n error?: boolean;\n /** Value submitted when this radio is selected */\n value: string;\n /** Classes applied to named slots */\n styles?: RadioStylesProp;\n}\n\nconst RadioItem = React.forwardRef<HTMLInputElement, RadioItemProps>(\n (\n {\n className,\n size: sizeProp,\n disabled: disabledProp = false,\n error = false,\n label,\n description,\n helperText,\n helperTextError = false,\n value,\n id,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const radioGroupContext = useRadioGroupContext();\n const generatedId = useId();\n const radioId = id || `radio-${generatedId}`;\n\n if (!radioGroupContext?.state) {\n throw new Error(\"RadioItem must be used within a Radio.Group\");\n }\n\n const { state } = radioGroupContext;\n const size = sizeProp || radioGroupContext?.size || \"md\";\n const disabled = disabledProp ?? radioGroupContext?.disabled ?? false;\n const isSelected = state.selectedValue === value;\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n\n const ariaLabelFromProps = props[\"aria-label\"];\n const ariaLabelValue = ariaLabelFromProps || (typeof label === \"string\" ? label : undefined);\n\n const { inputProps } = useRadio(\n {\n value,\n isDisabled: disabled,\n ...(ariaLabelValue && { \"aria-label\": ariaLabelValue }),\n },\n state,\n inputRef\n );\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-radio-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n const resolved = resolveRadioStyles(stylesProp);\n\n return (\n <div\n ref={rootRef}\n className={cn(\"w-full\", css[\"radio-item\"], scopeProps.className, resolved.item)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n className={cn(\"relative\", css[\"radio-surface\"])}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n data-radio-focus-surface=\"true\"\n >\n <div\n className={cn(\"radio\", css.radio, css[size], className, resolved.root)}\n data-selected={isSelected ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : \"false\"}\n role=\"presentation\"\n >\n <div className={cn(css[\"radio-dot\"], css[size], resolved.dot)} />\n </div>\n <input\n {...asElementProps<\"input\">(mergeProps(inputProps, focusProps, hoverProps))}\n ref={mergedRef}\n type=\"radio\"\n id={radioId}\n className={cn(css[\"radio-input\"], resolved.input)}\n suppressHydrationWarning\n {...props}\n />\n </div>\n {(label || description) && (\n <div className=\"flex flex-col gap-1\">\n {label && (\n <label\n htmlFor={radioId}\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n suppressHydrationWarning\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}\n data-error={error ? \"true\" : undefined}\n >\n {description}\n </p>\n )}\n </div>\n )}\n {helperText && (\n <p\n className={cn(\"helper-text\", css[\"helper-text\"], resolved.helperText)}\n data-error={helperTextError ? \"true\" : undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n }\n);\n\nRadioItem.displayName = \"RadioItem\";\n\nexport interface RadioProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\"> {\n /** Size of the radio button */\n size?: Size;\n /** Label text or element displayed next to the radio */\n label?: React.ReactNode;\n /** Secondary description shown below the label */\n description?: React.ReactNode;\n /** Helper text shown below the radio item */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Whether to apply error styling */\n error?: boolean;\n /** Classes applied to named slots */\n styles?: RadioStylesProp;\n}\n\nconst RadioBase = React.forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n className,\n size = \"md\",\n disabled = false,\n error = false,\n label,\n description,\n helperText,\n helperTextError = false,\n checked: checkedProp,\n defaultChecked,\n onChange,\n id,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const [internalChecked, setInternalChecked] = React.useState(checkedProp ?? defaultChecked ?? false);\n const generatedId = useId();\n\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(e.target.checked);\n }\n onChange?.(e);\n };\n\n const radioId = id || `radio-${generatedId}`;\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-radio-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n const resolved = resolveRadioStyles(stylesProp);\n\n return (\n <div\n ref={rootRef}\n className={cn(\"w-full\", css[\"radio-item\"], scopeProps.className, resolved.item)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n className={cn(\"relative\", css[\"radio-surface\"])}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n data-radio-focus-surface=\"true\"\n >\n <div\n className={cn(\"radio\", css.radio, css[size], className, resolved.root)}\n data-selected={checked ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : \"false\"}\n role=\"presentation\"\n >\n <div className={cn(css[\"radio-dot\"], css[size], resolved.dot)} />\n </div>\n <input\n {...asElementProps<\"input\">(mergeProps(focusProps, hoverProps))}\n ref={mergedRef}\n type=\"radio\"\n id={radioId}\n checked={checked}\n onChange={handleChange}\n disabled={disabled ?? false}\n className={cn(css[\"radio-input\"], resolved.input)}\n aria-label={typeof label === \"string\" ? label : undefined}\n suppressHydrationWarning\n {...props}\n />\n </div>\n {(label || description) && (\n <div className=\"flex flex-col gap-1\">\n {label && (\n <label\n htmlFor={radioId}\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n suppressHydrationWarning\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}\n data-error={error ? \"true\" : undefined}\n >\n {description}\n </p>\n )}\n </div>\n )}\n {helperText && (\n <p\n className={cn(\"helper-text\", css[\"helper-text\"], resolved.helperText)}\n data-error={helperTextError ? \"true\" : undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n }\n);\n\nRadioBase.displayName = \"Radio\";\n\nconst Radio = Object.assign(RadioBase, {\n Group: RadioGroup,\n Item: RadioItem,\n});\n\nexport { Radio };\n",
|
|
5122
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .radio-items {\n @apply flex flex-col gap-3;\n }\n\n .radio-item {\n @apply flex items-start gap-3 cursor-pointer select-none;\n position: relative;\n overflow: visible;\n }\n\n .radio-surface {\n @apply inline-flex shrink-0;\n border-radius: 9999px;\n }\n\n .radio-input {\n @apply absolute inset-0 h-full w-full cursor-pointer opacity-0;\n }\n\n .radio {\n --disabled-opacity: 0.6;\n @apply relative flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: 9999px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n
|
|
5123
|
-
"cssTypes": "declare const styles: {\n \"radio-items\": string;\n \"radio-item\": string;\n \"radio-surface\": string;\n \"radio-input\": string;\n radio: string;\n
|
|
5034
|
+
"tsx": "\"use client\";\n\nimport React, { useId, createContext, useContext } from \"react\";\nimport { useRadioGroupState } from \"react-stately\";\n\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useRadioGroup, useRadio } from \"@react-aria/radio\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Radio.module.css\";\n\ntype Size = \"sm\" | \"md\" | \"lg\";\n\nexport interface RadioStyleSlots {\n root?: StyleValue;\n item?: StyleValue;\n input?: StyleValue;\n dot?: StyleValue;\n label?: StyleValue;\n description?: StyleValue;\n helperText?: StyleValue;\n}\n\nexport type RadioStylesProp = StylesProp<RadioStyleSlots>;\n\nconst resolveRadioBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"input\",\n \"dot\",\n \"label\",\n \"description\",\n \"helperText\",\n] as const);\n\nfunction resolveRadioStyles(styles: RadioStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveRadioBaseStyles(styles);\n }\n\n const { root, item, input, dot, label, description, helperText } = styles;\n return resolveRadioBaseStyles({ root, item, input, dot, label, description, helperText });\n}\n\ninterface RadioGroupContextType {\n state?: ReturnType<typeof useRadioGroupState>;\n disabled?: boolean;\n size?: Size;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextType | undefined>(undefined);\n\nconst useRadioGroupContext = () => {\n const context = useContext(RadioGroupContext);\n return context;\n};\n\nexport interface RadioGroupStyleSlots {\n root?: StyleValue;\n label?: StyleValue;\n description?: StyleValue;\n group?: StyleValue;\n}\n\nexport type RadioGroupStylesProp = StylesProp<RadioGroupStyleSlots>;\n\nconst resolveRadioGroupBaseStyles = createStylesResolver([\n \"root\",\n \"label\",\n \"description\",\n \"group\",\n] as const);\n\nfunction resolveRadioGroupStyles(styles: RadioGroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveRadioGroupBaseStyles(styles);\n }\n\n const { root, label, description, group } = styles;\n return resolveRadioGroupBaseStyles({ root, label, description, group });\n}\n\nexport interface RadioGroupProps {\n /** Controlled selected radio value */\n value?: string;\n /** Initial selected value for uncontrolled usage */\n defaultValue?: string;\n /** Called when the selected value changes */\n onValueChange?: (value: string) => void;\n /** Whether all radios in the group are disabled */\n disabled?: boolean;\n /** Size of all radio buttons in the group */\n size?: Size;\n children: React.ReactNode;\n /** Additional CSS class names */\n className?: string;\n /** Accessible label for the radio group */\n label?: string;\n /** Descriptive text shown below the group label */\n description?: string;\n /** Classes applied to the root or named slots */\n styles?: RadioGroupStylesProp;\n}\n\nconst RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value: controlledValue,\n defaultValue,\n onValueChange,\n disabled = false,\n size = \"md\",\n children,\n className,\n label,\n description,\n styles: stylesProp,\n },\n ref\n ) => {\n const state = useRadioGroupState({\n value: controlledValue,\n defaultValue,\n onChange: onValueChange,\n isDisabled: disabled,\n });\n\n useRadioGroup(\n {\n isDisabled: disabled,\n label,\n description,\n },\n state\n );\n\n const resolved = resolveRadioGroupStyles(stylesProp);\n\n return (\n <RadioGroupContext.Provider value={{ state, disabled, size }}>\n <div ref={ref} className={cn(\"radio-group\", className, resolved.root)} role=\"group\">\n {label && (\n <label\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n {label}\n </label>\n )}\n {description && (\n <p className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}>\n {description}\n </p>\n )}\n <div className={cn(css[\"radio-items\"], resolved.group)}>{children}</div>\n </div>\n </RadioGroupContext.Provider>\n );\n }\n);\n\nRadioGroup.displayName = \"RadioGroup\";\n\nexport interface RadioItemProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\"> {\n /** Size of the radio button */\n size?: Size;\n /** Label text or element displayed next to the radio */\n label?: React.ReactNode;\n /** Secondary description shown below the label */\n description?: React.ReactNode;\n /** Helper text shown below the radio item */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Whether to apply error styling */\n error?: boolean;\n /** Value submitted when this radio is selected */\n value: string;\n /** Classes applied to named slots */\n styles?: RadioStylesProp;\n}\n\nconst RadioItem = React.forwardRef<HTMLInputElement, RadioItemProps>(\n (\n {\n className,\n size: sizeProp,\n disabled: disabledProp = false,\n error = false,\n label,\n description,\n helperText,\n helperTextError = false,\n value,\n id,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const radioGroupContext = useRadioGroupContext();\n const generatedId = useId();\n const radioId = id || `radio-${generatedId}`;\n\n if (!radioGroupContext?.state) {\n throw new Error(\"RadioItem must be used within a Radio.Group\");\n }\n\n const { state } = radioGroupContext;\n const size = sizeProp || radioGroupContext?.size || \"md\";\n const disabled = disabledProp ?? radioGroupContext?.disabled ?? false;\n const isSelected = state.selectedValue === value;\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n\n const ariaLabelFromProps = props[\"aria-label\"];\n const ariaLabelValue = ariaLabelFromProps || (typeof label === \"string\" ? label : undefined);\n\n const { inputProps } = useRadio(\n {\n value,\n isDisabled: disabled,\n ...(ariaLabelValue && { \"aria-label\": ariaLabelValue }),\n },\n state,\n inputRef\n );\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-radio-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n const resolved = resolveRadioStyles(stylesProp);\n\n return (\n <div\n ref={rootRef}\n className={cn(\"w-full\", css[\"radio-item\"], scopeProps.className, resolved.item)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n className={cn(\"relative\", css[\"radio-surface\"])}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n data-radio-focus-surface=\"true\"\n >\n <div\n className={cn(\"radio\", css.radio, css[size], className, resolved.root)}\n data-selected={isSelected ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : \"false\"}\n role=\"presentation\"\n >\n <div className={cn(\"dot\", css.dot, resolved.dot)} />\n </div>\n <input\n {...asElementProps<\"input\">(mergeProps(inputProps, focusProps, hoverProps))}\n ref={mergedRef}\n type=\"radio\"\n id={radioId}\n className={cn(css[\"radio-input\"], resolved.input)}\n suppressHydrationWarning\n {...props}\n />\n </div>\n {(label || description) && (\n <div className=\"flex flex-col gap-1\">\n {label && (\n <label\n htmlFor={radioId}\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n suppressHydrationWarning\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}\n data-error={error ? \"true\" : undefined}\n >\n {description}\n </p>\n )}\n </div>\n )}\n {helperText && (\n <p\n className={cn(\"helper-text\", css[\"helper-text\"], resolved.helperText)}\n data-error={helperTextError ? \"true\" : undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n }\n);\n\nRadioItem.displayName = \"RadioItem\";\n\nexport interface RadioProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\"> {\n /** Size of the radio button */\n size?: Size;\n /** Label text or element displayed next to the radio */\n label?: React.ReactNode;\n /** Secondary description shown below the label */\n description?: React.ReactNode;\n /** Helper text shown below the radio item */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Whether to apply error styling */\n error?: boolean;\n /** Classes applied to named slots */\n styles?: RadioStylesProp;\n}\n\nconst RadioBase = React.forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n className,\n size = \"md\",\n disabled = false,\n error = false,\n label,\n description,\n helperText,\n helperTextError = false,\n checked: checkedProp,\n defaultChecked,\n onChange,\n id,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const [internalChecked, setInternalChecked] = React.useState(checkedProp ?? defaultChecked ?? false);\n const generatedId = useId();\n\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalChecked(e.target.checked);\n }\n onChange?.(e);\n };\n\n const radioId = id || `radio-${generatedId}`;\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-radio-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n const resolved = resolveRadioStyles(stylesProp);\n\n return (\n <div\n ref={rootRef}\n className={cn(\"w-full\", css[\"radio-item\"], scopeProps.className, resolved.item)}\n data-disabled={disabled ? \"true\" : undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n className={cn(\"relative\", css[\"radio-surface\"])}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n data-radio-focus-surface=\"true\"\n >\n <div\n className={cn(\"radio\", css.radio, css[size], className, resolved.root)}\n data-selected={checked ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : \"false\"}\n role=\"presentation\"\n >\n <div className={cn(\"dot\", css.dot, resolved.dot)} />\n </div>\n <input\n {...asElementProps<\"input\">(mergeProps(focusProps, hoverProps))}\n ref={mergedRef}\n type=\"radio\"\n id={radioId}\n checked={checked}\n onChange={handleChange}\n disabled={disabled ?? false}\n className={cn(css[\"radio-input\"], resolved.input)}\n aria-label={typeof label === \"string\" ? label : undefined}\n suppressHydrationWarning\n {...props}\n />\n </div>\n {(label || description) && (\n <div className=\"flex flex-col gap-1\">\n {label && (\n <label\n htmlFor={radioId}\n className={cn(\"radio-label\", css[\"radio-label\"], resolved.label)}\n data-disabled={disabled ? \"true\" : undefined}\n suppressHydrationWarning\n >\n {label}\n </label>\n )}\n {description && (\n <p\n className={cn(\"radio-description\", css[\"radio-description\"], resolved.description)}\n data-error={error ? \"true\" : undefined}\n >\n {description}\n </p>\n )}\n </div>\n )}\n {helperText && (\n <p\n className={cn(\"helper-text\", css[\"helper-text\"], resolved.helperText)}\n data-error={helperTextError ? \"true\" : undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n }\n);\n\nRadioBase.displayName = \"Radio\";\n\nconst Radio = Object.assign(RadioBase, {\n Group: RadioGroup,\n Item: RadioItem,\n});\n\nexport { Radio };\n",
|
|
5035
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .radio-items {\n @apply flex flex-col gap-3;\n }\n\n .radio-item {\n @apply flex items-start gap-3 cursor-pointer select-none;\n position: relative;\n overflow: visible;\n }\n\n .radio-surface {\n @apply inline-flex shrink-0;\n border-radius: 9999px;\n }\n\n .radio-input {\n @apply absolute inset-0 h-full w-full cursor-pointer opacity-0;\n }\n\n .radio {\n --disabled-opacity: 0.6;\n @apply relative flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: 9999px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n color: var(--foreground);\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n }\n }\n\n .radio-item:active .radio {\n transform: scale(0.92);\n }\n\n .dot {\n border-radius: 9999px;\n background-color: var(--background);\n transform: scale(0);\n transform-origin: center;\n transition: transform 200ms var(--ease-snappy-pop), background-color 200ms var(--ease-snappy-pop);\n }\n\n .radio[data-selected=\"true\"] .dot {\n transform: scale(1);\n }\n\n @media (hover: hover) {\n .radio-item:not([data-disabled=\"true\"]):hover .radio {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n opacity: 0.9;\n }\n }\n\n .radio-item[data-disabled=\"true\"] .radio {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .radio-label {\n @apply cursor-pointer;\n color: var(--foreground);\n font-size: inherit;\n font-weight: var(--font-weight-medium, 500);\n line-height: inherit;\n transition: color 200ms var(--ease-snappy-pop);\n user-select: none;\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n }\n\n .radio-description {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.125rem;\n transition: color 200ms var(--ease-snappy-pop);\n }\n\n .helper-text {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.5rem;\n margin-left: 2rem;\n transition: color 200ms var(--ease-snappy-pop);\n }\n\n .radio.sm {\n @apply h-4 w-4;\n }\n\n .radio.sm .dot {\n width: 0.375rem;\n height: 0.375rem;\n }\n\n .radio.md {\n @apply h-5 w-5;\n }\n\n .radio.md .dot {\n width: 0.5rem;\n height: 0.5rem;\n }\n\n .radio.lg {\n @apply h-6 w-6;\n }\n\n .radio.lg .dot {\n width: 0.625rem;\n height: 0.625rem;\n }\n}\n",
|
|
5036
|
+
"cssTypes": "declare const styles: {\n \"radio-items\": string;\n \"radio-item\": string;\n \"radio-surface\": string;\n \"radio-input\": string;\n radio: string;\n dot: string;\n \"radio-label\": string;\n \"radio-description\": string;\n \"helper-text\": string;\n sm: string;\n md: string;\n lg: string;\n};\n\nexport default styles;\n"
|
|
5124
5037
|
},
|
|
5125
5038
|
"scroll": {
|
|
5126
5039
|
"tsx": "\"use client\";\n\nimport React, {\n useRef,\n useLayoutEffect,\n useState,\n useCallback,\n} from \"react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Mask } from \"../Mask\";\nimport css from \"./Scroll.module.css\";\nimport {\n SCROLL_RESTORE_AXIS_ATTR,\n SCROLL_RESTORE_DEBUG_ID_KEY,\n SCROLL_RESTORE_FLAG,\n SCROLL_RESTORE_STORAGE_KEY_ATTR,\n getBootstrapRestoredNode,\n getScrollRestoreDebugId,\n getScrollRestoreMetrics,\n getScrollPositionProperty,\n recordScrollRestoreTrace,\n} from \"./scripts/restore-scroll.constants\";\n\nexport interface ScrollStyleSlots {\n root?: StyleValue;\n content?: StyleValue;\n track?: StyleValue;\n thumb?: StyleValue;\n}\n\nexport type ScrollStylesProp = StylesProp<ScrollStyleSlots>;\n\nexport interface ScrollProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n maxHeight?: string;\n maxWidth?: string;\n direction?: \"vertical\" | \"horizontal\";\n paddingY?: string | number;\n \"fade-y\"?: boolean;\n fadeDistance?: number;\n fadeSize?: number;\n enabled?: boolean;\n hide?: boolean;\n inline?: boolean;\n styles?: ScrollStylesProp;\n storageKey?: string;\n}\n\nconst resolveScrollBaseStyles = createStylesResolver([\n \"root\",\n \"content\",\n \"track\",\n \"thumb\",\n] as const);\n\nfunction resolveScrollStyles(styles: ScrollStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveScrollBaseStyles(styles);\n const { root, content, track, thumb } = styles;\n return resolveScrollBaseStyles({ root, content, track, thumb });\n}\n\nconst SCROLLBAR_VISIBILITY_EPSILON = 1;\n\nfunction getInitialScrollFadeVars(\n direction: ScrollProps[\"direction\"],\n fadeY: boolean,\n fadeSize: number,\n): React.CSSProperties {\n if (direction !== \"vertical\" || !fadeY) {\n return {\n \"--mask-top-fade\": \"0%\",\n \"--mask-bottom-fade\": \"0%\",\n } as React.CSSProperties;\n }\n\n // SSR cannot know overflow or scroll position, so default to a bottom-only hint.\n return {\n \"--mask-top-fade\": \"0%\",\n \"--mask-bottom-fade\": `${fadeSize}%`,\n } as React.CSSProperties;\n}\n\nfunction readStoredScrollOffset(storageKey: string): number | null {\n if (typeof window === \"undefined\") return null;\n\n try {\n const storedValue = window.sessionStorage.getItem(storageKey);\n if (storedValue === null) return null;\n\n const parsedValue = parseInt(storedValue, 10);\n return Number.isNaN(parsedValue) ? null : parsedValue;\n } catch {\n return null;\n }\n}\n\nfunction persistStoredScrollOffset(storageKey: string, scrollOffset: number): void {\n if (typeof window === \"undefined\") return;\n\n try {\n window.sessionStorage.setItem(storageKey, String(scrollOffset));\n } catch {\n // Ignore storage failures. The live scroll position is already updated.\n }\n}\n\nfunction hasPreHydrationScrollRestore(node: HTMLDivElement): boolean {\n return Boolean((node as HTMLDivElement & Record<string, unknown>)[SCROLL_RESTORE_FLAG]);\n}\n\nconst Scroll = React.forwardRef<HTMLDivElement, ScrollProps>(\n (\n {\n children,\n className,\n maxHeight,\n maxWidth,\n direction = \"vertical\",\n paddingY = 4,\n \"fade-y\": fadeY = false,\n fadeDistance = 5,\n fadeSize = 4,\n enabled = true,\n hide = true,\n inline = false,\n styles,\n storageKey,\n style: propsStyle,\n ...restProps\n },\n ref,\n ) => {\n const isHoriz = direction === \"horizontal\";\n\n // Axis-Agnostic property keys\n const clientSizeKey = isHoriz ? \"clientWidth\" : \"clientHeight\";\n const scrollSizeKey = isHoriz ? \"scrollWidth\" : \"scrollHeight\";\n const scrollPosKey = getScrollPositionProperty(direction);\n const clientPosKey = isHoriz ? \"clientX\" : \"clientY\";\n const trackSizeKey = isHoriz ? \"width\" : \"height\";\n const trackPosKey = isHoriz ? \"left\" : \"top\";\n\n const numPaddingY = typeof paddingY === \"number\" ? paddingY : parseInt(String(paddingY), 10) || 0;\n const strPaddingY = typeof paddingY === \"number\" ? `${paddingY}px` : String(paddingY);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const maskRef = useRef<HTMLDivElement>(null);\n const thumbRef = useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, containerRef);\n\n const resolved = resolveScrollStyles(styles);\n\n const [needsScrollbar, setNeedsScrollbar] = useState(false);\n const [isHoveredRight, setIsHoveredRight] = useState(false);\n const [thumbSize, setThumbSize] = useState(0);\n const [thumbPosition, setThumbPosition] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isScrolling, setIsScrolling] = useState(false);\n\n const scrollTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const dragStartRef = useRef({ origin: 0, scrollOrigin: 0 });\n const thumbSizeRef = useRef(0);\n const resizeObserverRef = useRef<ResizeObserver | null>(null);\n const mutationObserverRef = useRef<MutationObserver | null>(null);\n\n const updateScrollbar = useCallback(() => {\n if (!containerRef.current || !contentRef.current) return;\n\n const container = containerRef.current;\n const content = contentRef.current;\n\n const viewportSize = content[clientSizeKey] || container[clientSizeKey];\n const contentSize = content[scrollSizeKey] || viewportSize;\n const currentScroll = content[scrollPosKey];\n const trackSize = isHoriz ? container[clientSizeKey] : container[clientSizeKey] - numPaddingY * 2;\n\n const maxScroll = Math.max(0, contentSize - viewportSize);\n const needs = maxScroll > SCROLLBAR_VISIBILITY_EPSILON;\n setNeedsScrollbar(needs);\n\n const scrollRatio = trackSize / Math.max(1, contentSize);\n const newThumbSize = Math.max(20, Math.min(trackSize, trackSize * scrollRatio));\n const scrollProgress = needs && maxScroll > 0 ? currentScroll / maxScroll : 0;\n const maxThumbPos = trackSize - newThumbSize;\n const newThumbPos = scrollProgress * maxThumbPos;\n\n setThumbSize(newThumbSize);\n thumbSizeRef.current = newThumbSize;\n setThumbPosition(newThumbPos);\n\n if (!isHoriz && maskRef.current) {\n const maskNode = maskRef.current;\n if (fadeY && needs) {\n const topP = Math.min(1, Math.max(0, currentScroll / fadeDistance));\n const botP = Math.min(1, Math.max(0, (maxScroll - currentScroll) / fadeDistance));\n maskNode.style.setProperty(\"--mask-top-fade\", `${topP * fadeSize}%`);\n maskNode.style.setProperty(\"--mask-bottom-fade\", `${botP * fadeSize}%`);\n } else {\n maskNode.style.setProperty(\"--mask-top-fade\", \"0%\");\n maskNode.style.setProperty(\"--mask-bottom-fade\", \"0%\");\n }\n }\n }, [isHoriz, clientSizeKey, scrollSizeKey, scrollPosKey, numPaddingY, fadeY, fadeDistance, fadeSize]);\n\n const cleanupScrollTimeout = useCallback(() => {\n if (scrollTimeoutRef.current) {\n clearTimeout(scrollTimeoutRef.current);\n scrollTimeoutRef.current = null;\n }\n }, []);\n\n const cleanupObservers = useCallback(() => {\n resizeObserverRef.current?.disconnect();\n mutationObserverRef.current?.disconnect();\n resizeObserverRef.current = null;\n mutationObserverRef.current = null;\n }, []);\n\n const cleanupDragListeners = useCallback(() => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n document.body.style.userSelect = \"\";\n }, []);\n\n const restoreStoredScrollPosition = useCallback(() => {\n if (!storageKey || !contentRef.current) return;\n\n const contentNode = contentRef.current;\n const bootstrapNode = getBootstrapRestoredNode(storageKey);\n const sameNodeAsBootstrap = Boolean(bootstrapNode) && bootstrapNode === contentNode;\n const currentNodeId = getScrollRestoreDebugId(contentNode);\n const bootstrapNodeId = getScrollRestoreDebugId(bootstrapNode);\n const beforeMetrics = getScrollRestoreMetrics(contentNode, direction);\n const hasPreHydrationRestore = hasPreHydrationScrollRestore(contentNode);\n\n recordScrollRestoreTrace(\"client:layout-effect\", {\n storageKey,\n hasPreHydrationRestore,\n sameNodeAsBootstrap,\n nodeReplaced: Boolean(bootstrapNode) && bootstrapNode !== contentNode,\n currentNodeId,\n bootstrapNodeId,\n clientSize: beforeMetrics.clientSize,\n scrollSize: beforeMetrics.scrollSize,\n maxScroll: beforeMetrics.maxScroll,\n scrollOffset: beforeMetrics.scrollOffset,\n });\n\n if (hasPreHydrationRestore) {\n recordScrollRestoreTrace(\"client:skip-prehydrated\", {\n storageKey,\n sameNodeAsBootstrap,\n nodeReplaced: Boolean(bootstrapNode) && bootstrapNode !== contentNode,\n currentNodeId,\n bootstrapNodeId,\n });\n return;\n }\n\n const savedOffset = readStoredScrollOffset(storageKey);\n if (savedOffset === null) {\n recordScrollRestoreTrace(\"client:no-stored-offset\", {\n storageKey,\n sameNodeAsBootstrap,\n nodeReplaced: Boolean(bootstrapNode) && bootstrapNode !== contentNode,\n currentNodeId,\n bootstrapNodeId,\n });\n return;\n }\n\n contentNode[scrollPosKey] = savedOffset;\n\n const afterMetrics = getScrollRestoreMetrics(contentNode, direction);\n recordScrollRestoreTrace(\"client:fallback-restore\", {\n storageKey,\n storedOffset: savedOffset,\n sameNodeAsBootstrap,\n nodeReplaced: Boolean(bootstrapNode) && bootstrapNode !== contentNode,\n currentNodeId,\n bootstrapNodeId,\n beforeScrollOffset: beforeMetrics.scrollOffset,\n afterScrollOffset: afterMetrics.scrollOffset,\n clientSize: afterMetrics.clientSize,\n scrollSize: afterMetrics.scrollSize,\n maxScroll: afterMetrics.maxScroll,\n clamped: savedOffset !== afterMetrics.scrollOffset,\n clampedToZero: savedOffset > 0 && afterMetrics.scrollOffset === 0,\n });\n }, [direction, scrollPosKey, storageKey]);\n\n const connectObservers = useCallback(() => {\n cleanupObservers();\n updateScrollbar();\n\n const resizeObserver = new ResizeObserver(() => requestAnimationFrame(updateScrollbar));\n const mutationObserver = new MutationObserver(() => requestAnimationFrame(updateScrollbar));\n\n if (containerRef.current) resizeObserver.observe(containerRef.current);\n if (contentRef.current) {\n resizeObserver.observe(contentRef.current);\n mutationObserver.observe(contentRef.current, { childList: true, subtree: true });\n }\n\n resizeObserverRef.current = resizeObserver;\n mutationObserverRef.current = mutationObserver;\n }, [cleanupObservers, updateScrollbar]);\n\n const handleContentRef = useCallback(\n (node: HTMLDivElement | null) => {\n contentRef.current = node;\n if (!node) {\n cleanupObservers();\n cleanupDragListeners();\n cleanupScrollTimeout();\n return;\n }\n\n recordScrollRestoreTrace(\"client:content-ref\", {\n storageKey: storageKey ?? null,\n currentNodeId: getScrollRestoreDebugId(node),\n preHydrationFlag: hasPreHydrationScrollRestore(node),\n bootstrapDebugId: storageKey ? getScrollRestoreDebugId(getBootstrapRestoredNode(storageKey)) : null,\n debugIdPropertyKey: SCROLL_RESTORE_DEBUG_ID_KEY,\n });\n connectObservers();\n },\n [cleanupDragListeners, cleanupObservers, cleanupScrollTimeout, connectObservers, storageKey]\n );\n\n const handleScroll = useCallback(() => {\n updateScrollbar();\n if (storageKey && contentRef.current) {\n persistStoredScrollOffset(storageKey, contentRef.current[scrollPosKey]);\n }\n setIsScrolling(true);\n if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);\n scrollTimeoutRef.current = setTimeout(() => setIsScrolling(false), 1500);\n }, [updateScrollbar, storageKey, scrollPosKey]);\n\n const handleContainerMouseMove = useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (!containerRef.current) return;\n const rect = containerRef.current.getBoundingClientRect();\n const mousePos = isHoriz ? e.clientY - rect.top : e.clientX - rect.left;\n const rectSize = isHoriz ? rect.height : rect.width;\n\n const newIsHovered = mousePos > rectSize - 20;\n if (newIsHovered !== isHoveredRight) setIsHoveredRight(newIsHovered);\n },\n [isHoriz, isHoveredRight]\n );\n\n const handleContainerMouseLeave = useCallback(() => setIsHoveredRight(false), []);\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n if (!contentRef.current || !containerRef.current) return;\n\n const delta = e[clientPosKey] - dragStartRef.current.origin;\n const viewportSize = contentRef.current[clientSizeKey] || containerRef.current[clientSizeKey];\n const maxScroll = Math.max(0, contentRef.current[scrollSizeKey] - viewportSize);\n const scrollRatio = maxScroll / Math.max(1, viewportSize - thumbSizeRef.current);\n\n contentRef.current[scrollPosKey] = Math.max(\n 0,\n Math.min(maxScroll, dragStartRef.current.scrollOrigin + delta * scrollRatio)\n );\n },\n [clientPosKey, clientSizeKey, scrollPosKey, scrollSizeKey]\n );\n\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n cleanupDragListeners();\n }, [cleanupDragListeners]);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n if (!contentRef.current) return;\n e.preventDefault();\n\n dragStartRef.current = {\n origin: e[clientPosKey],\n scrollOrigin: contentRef.current[scrollPosKey],\n };\n setIsDragging(true);\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n document.body.style.userSelect = \"none\";\n },\n [clientPosKey, scrollPosKey, handleMouseMove, handleMouseUp]\n );\n\n const handleTrackClick = useCallback(\n (e: React.MouseEvent) => {\n if (!containerRef.current || !contentRef.current || !thumbRef.current) return;\n\n const rect = containerRef.current.getBoundingClientRect();\n const thumbRect = thumbRef.current.getBoundingClientRect();\n const rectStartKey = isHoriz ? \"left\" : \"top\";\n const rectEndKey = isHoriz ? \"right\" : \"bottom\";\n const padOffset = isHoriz ? 0 : numPaddingY;\n\n const clickPos = e[clientPosKey] - rect[rectStartKey] - padOffset;\n const relThumbStart = thumbRect[rectStartKey] - rect[rectStartKey] - padOffset;\n const relThumbEnd = thumbRect[rectEndKey] - rect[rectStartKey] - padOffset;\n\n // Ignore clicks directly on the thumb (handled by handleMouseDown)\n if (clickPos >= relThumbStart && clickPos <= relThumbEnd) return;\n\n const viewportSize = contentRef.current[clientSizeKey] || containerRef.current[clientSizeKey];\n const contentSize = contentRef.current[scrollSizeKey];\n const maxScroll = Math.max(0, contentSize - viewportSize);\n const trackSize = isHoriz\n ? containerRef.current[clientSizeKey]\n : containerRef.current[clientSizeKey] - numPaddingY * 2;\n\n const newThumbSize = Math.max(20, trackSize * (trackSize / contentSize));\n const targetThumbStart = clickPos - newThumbSize / 2;\n const maxThumbPos = trackSize - newThumbSize;\n const clampedThumbStart = Math.max(0, Math.min(maxThumbPos, targetThumbStart));\n\n const scrollProgress = maxThumbPos > 0 ? clampedThumbStart / maxThumbPos : 0;\n contentRef.current[scrollPosKey] = Math.max(0, Math.min(maxScroll, scrollProgress * maxScroll));\n\n dragStartRef.current = {\n origin: e[clientPosKey],\n scrollOrigin: contentRef.current[scrollPosKey],\n };\n setIsDragging(true);\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n document.body.style.userSelect = \"none\";\n },\n [isHoriz, numPaddingY, clientPosKey, clientSizeKey, scrollPosKey, scrollSizeKey, handleMouseMove, handleMouseUp]\n );\n\n const handleWheel = useCallback(\n (e: React.WheelEvent) => {\n if (!contentRef.current || !isHoriz) return;\n e.preventDefault();\n\n const content = contentRef.current;\n const scrollAmount = e.deltaY || e.deltaX;\n const maxScroll = content.scrollWidth - content.clientWidth;\n\n content.scrollLeft = Math.max(0, Math.min(maxScroll, content.scrollLeft + scrollAmount));\n },\n [isHoriz]\n );\n\n useLayoutEffect(() => {\n restoreStoredScrollPosition();\n connectObservers();\n }, [restoreStoredScrollPosition, connectObservers, enabled]);\n\n const axisConstraintStyle = {\n ...(isHoriz\n ? (maxWidth ? { maxWidth } : {})\n : (maxHeight ? { maxHeight } : {})),\n };\n\n if (!enabled) {\n return (\n <div\n ref={ref}\n className={cn(\"scroll\", css.root, resolved.root, className)}\n style={{\n [isHoriz ? \"width\" : \"height\"]: \"100%\",\n ...axisConstraintStyle,\n ...propsStyle,\n }}\n {...restProps}\n >\n {children}\n </div>\n );\n }\n\n const showOpacity = needsScrollbar && (!hide || isHoveredRight || isDragging || isScrolling) ? 1 : 0;\n\n return (\n <div\n ref={mergedRef}\n className={cn(\n \"scroll\",\n css.root,\n isHoriz ? css.horizontal : css.vertical,\n className,\n resolved.root\n )}\n style={{\n [isHoriz ? \"width\" : \"height\"]: \"100%\",\n ...axisConstraintStyle,\n ...(!isHoriz && strPaddingY ? { \"--scroll-padding-y\": strPaddingY } : {}),\n ...propsStyle,\n } as React.CSSProperties}\n onMouseMove={handleContainerMouseMove}\n onMouseLeave={handleContainerMouseLeave}\n data-pressed={isDragging || undefined}\n data-inline={String(inline && needsScrollbar)}\n {...restProps}\n >\n <Mask\n ref={maskRef}\n style={{\n [isHoriz ? \"maxWidth\" : \"maxHeight\"]: \"inherit\",\n overflow: \"hidden\",\n ...getInitialScrollFadeVars(direction, fadeY, fadeSize),\n } as React.CSSProperties}\n >\n {!isHoriz && fadeY ? <Mask.Fade /> : null}\n <div\n ref={handleContentRef}\n className={cn(css.content, resolved.content)}\n onScroll={handleScroll}\n onWheel={isHoriz ? handleWheel : undefined}\n style={{\n [isHoriz ? \"maxWidth\" : \"maxHeight\"]: \"inherit\",\n minHeight: 0,\n minWidth: 0,\n }}\n {...(storageKey\n ? {\n [SCROLL_RESTORE_STORAGE_KEY_ATTR]: storageKey,\n [SCROLL_RESTORE_AXIS_ATTR]: direction,\n }\n : {})}\n >\n {children}\n </div>\n </Mask>\n\n <div\n className={cn(\"track\", css.track, resolved.track)}\n data-hide={String(hide)}\n style={{\n opacity: showOpacity,\n pointerEvents: needsScrollbar ? \"auto\" : \"none\",\n }}\n onMouseDown={handleTrackClick}\n >\n {needsScrollbar && (\n <div\n ref={thumbRef}\n className={cn(\"thumb\", css.thumb, resolved.thumb)}\n style={{\n [trackSizeKey]: `${thumbSize}px`,\n [trackPosKey]: `${thumbPosition}px`,\n }}\n onMouseDown={handleMouseDown}\n />\n )}\n </div>\n </div>\n );\n }\n);\n\nScroll.displayName = \"Scroll\";\n\nexport { Scroll };\n",
|
|
5127
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply relative;\n min-height: 0;\n }\n\n .vertical {\n --scrollbar-width: 12px;\n }\n\n .horizontal {\n --scrollbar-height: 12px;\n }\n\n .content {\n @apply h-full w-full;\n overflow: auto;\n }\n\n .vertical .content {\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .vertical[data-inline=\"true\"] .content {\n padding-right: 16px;\n }\n\n .horizontal .content {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .horizontal[data-inline=\"true\"] .content {\n padding-bottom: 16px;\n }\n\n .vertical .content::-webkit-scrollbar,\n .horizontal .content::-webkit-scrollbar { display: none; }\n\n .track {\n @apply absolute;\n z-index: 10;\n background-color: var(--
|
|
5040
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply relative;\n min-height: 0;\n }\n\n .vertical {\n --scrollbar-width: 12px;\n }\n\n .horizontal {\n --scrollbar-height: 12px;\n }\n\n .content {\n @apply h-full w-full;\n overflow: auto;\n }\n\n .vertical .content {\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .vertical[data-inline=\"true\"] .content {\n padding-right: 16px;\n }\n\n .horizontal .content {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .horizontal[data-inline=\"true\"] .content {\n padding-bottom: 16px;\n }\n\n .vertical .content::-webkit-scrollbar,\n .horizontal .content::-webkit-scrollbar { display: none; }\n\n .track {\n @apply absolute;\n z-index: 10;\n background-color: var(--background);\n }\n\n .track[data-hide=\"true\"] {\n transition-property: opacity;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .track {\n right: 4px;\n top: var(--scroll-padding-y, 0);\n width: 12px;\n height: calc(100% - 2 * var(--scroll-padding-y, 0));\n box-sizing: border-box;\n }\n\n .horizontal .track {\n bottom: 2px;\n left: 0;\n height: 12px;\n width: 100%;\n }\n\n .thumb {\n position: absolute;\n border-radius: calc(var(--radius-xs, 0.25rem) * 0.80);\n background-color: var(--background);\n transition-property: background-color, width, height;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .vertical .thumb {\n width: 6px;\n margin-left: 6px;\n transition-property: background-color, width, margin-left;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .thumb:hover,\n .vertical[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n width: 8px;\n margin-left: 4px;\n }\n\n .horizontal .thumb {\n height: 6px;\n margin-top: 6px;\n transition-property: background-color, height, margin-top;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .horizontal .thumb:hover,\n .horizontal[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n height: 8px;\n margin-top: 4px;\n }\n}\n",
|
|
5128
5041
|
"cssTypes": "export const root: string;\nexport const vertical: string;\nexport const horizontal: string;\nexport const content: string;\nexport const track: string;\nexport const thumb: string;\n\ndeclare const styles: {\n root: string;\n vertical: string;\n horizontal: string;\n content: string;\n track: string;\n thumb: string;\n};\n\nexport default styles;\n"
|
|
5129
5042
|
},
|
|
5130
5043
|
"select": {
|
|
5131
5044
|
"tsx": "import * as React from \"react\"\nimport { Key } from \"@react-types/shared\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport styles from \"./Select.module.css\"\nimport { useListNavigation, handleListKeyDown, focusAdjacentTabStop, type ItemData } from \"./Select.shared\"\n\nexport type SelectItemData = ItemData\n\nexport type SelectTriggerMode = \"click\" | \"hover\"\nexport type SelectMode = \"single\" | \"multiple\"\n\nexport interface SelectStyleSlots {\n root?: StyleValue;\n}\n\nexport type SelectStylesProp = StylesProp<SelectStyleSlots>;\n\nexport interface SelectContextValue {\n isOpen: boolean\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>\n contentPlacement: \"top\" | \"bottom\"\n setContentPlacement: React.Dispatch<React.SetStateAction<\"top\" | \"bottom\">>\n triggerType: \"button\" | \"input\"\n mode: SelectMode\n selectedKey: Key | null\n selectedKeys?: Set<Key>\n selectedTextValue: string\n onSelect: (key: Key) => void\n onToggle?: (key: Key) => void\n triggerRef: React.MutableRefObject<HTMLElement | null>\n wrapperRef: React.MutableRefObject<HTMLElement | null>\n contentRef: React.MutableRefObject<HTMLElement | null>\n triggerProps: any\n isFocused: boolean\n isFocusVisible: boolean\n isPressed: boolean\n isHovered: boolean\n isDisabled: boolean\n items: SelectItemData[]\n registerItem: (key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => void\n unregisterItem: (key: Key) => void\n searchValue: string\n setSearchValue: React.Dispatch<React.SetStateAction<string>>\n filteredItems: SelectItemData[]\n visibleKeys: Set<Key>\n focusedKey: Key | null\n setFocusedKey: React.Dispatch<React.SetStateAction<Key | null>>\n navigateToNextItem: () => void\n navigateToPrevItem: () => void\n selectFocusedItem: () => void\n isFocusedItemSubmenu: () => boolean\n maxItems: number\n triggerMode: SelectTriggerMode\n handleHoverIntent: (isHovering: boolean) => void\n mouseMoveDetectedRef: React.MutableRefObject<boolean>\n keyboardScrollIntentRef: React.MutableRefObject<boolean>\n markKeyboardNavigation: () => void\n moveFocusFromTrigger: (direction: 1 | -1) => boolean\n filter?: (item: any) => boolean\n contentId: string\n hasExternalValue: boolean\n restoreFocus: (target?: \"auto\" | \"trigger\" | \"row\") => void\n}\n\nconst SelectContext = React.createContext<SelectContextValue | null>(null)\n\nexport function useSelectContext() {\n const context = React.useContext(SelectContext)\n if (!context) {\n throw new Error(\"Select component must be used within Select root\")\n }\n return context\n}\n\nexport interface SelectProps<T = any> extends React.HTMLAttributes<HTMLDivElement> {\n /** Selection mode: \"single\" for one item, \"multiple\" for multi-item selection */\n mode?: SelectMode\n /** External items array — used when items are provided as data rather than JSX */\n items?: Array<T>\n /** Controlled selected key for single-select mode */\n selectedKey?: Key | null\n /** Default selected key for uncontrolled single-select */\n defaultSelectedKey?: Key | null\n /** Controlled selected keys for multi-select mode */\n selectedKeys?: Key[]\n /** Default selected keys for uncontrolled multi-select */\n defaultSelectedKeys?: Key[]\n /** Default display text shown in the trigger when nothing is selected */\n defaultValue?: string\n /** Display text for the currently selected value — used for SSR/SSG to avoid\n * flash of placeholder before items register. Provide alongside selectedKey or\n * defaultSelectedKey so the correct label renders on the first pass. */\n valueLabel?: string\n /** Called when selection changes; receives a single key (single) or key array (multiple) */\n onSelectionChange?: (value: any) => void\n /** Disables the entire select and prevents interaction */\n isDisabled?: boolean\n /** Focuses the trigger automatically on mount */\n autoFocus?: boolean\n /** Maximum number of items visible before the dropdown scrolls */\n maxItems?: number\n /** Additional CSS class for the root wrapper */\n className?: string\n /** How the dropdown opens: \"click\" (default) or \"hover\" */\n trigger?: SelectTriggerMode\n /** Custom filter predicate applied to the items array */\n filter?: (item: T) => boolean\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: SelectStylesProp;\n}\n\nconst resolveSelectBaseStyles = createStylesResolver(['root'] as const);\n\nfunction resolveSelectStyles(styles: SelectStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveSelectBaseStyles(styles)\n const { root } = styles\n return resolveSelectBaseStyles({ root })\n}\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps<any>>(\n (\n {\n mode = \"single\",\n items: propItems = [],\n selectedKey: controlledSelectedKey,\n defaultSelectedKey,\n selectedKeys: controlledSelectedKeys,\n defaultSelectedKeys = [],\n defaultValue,\n valueLabel,\n onSelectionChange,\n isDisabled = false,\n autoFocus = false,\n maxItems = 6,\n children,\n className,\n trigger: triggerMode = \"click\",\n filter,\n styles: stylesProp,\n ...domProps\n },\n ref\n ) => {\n const triggerRef = React.useRef<HTMLElement>(null)\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const wrapperRef = React.useRef<HTMLDivElement>(null)\n const contentRef = React.useRef<HTMLElement>(null)\n const mouseMoveDetectedRef = React.useRef(true)\n const itemExtrasRef = React.useRef<Map<Key, { onSelect?: () => void; isSubmenuTrigger?: boolean }>>(new Map())\n const [isOpen, setIsOpen] = React.useState(false)\n const [contentPlacement, setContentPlacement] = React.useState<\"top\" | \"bottom\">(\"bottom\")\n const contentId = React.useId()\n const hoverTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const keyboardScrollIntentRef = React.useRef(false)\n\n const handleHoverIntent = React.useCallback((isHovering: boolean) => {\n if (triggerMode !== \"hover\" || isDisabled) return\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n hoverTimeoutRef.current = null\n }\n\n if (isHovering) {\n setIsOpen(true)\n } else {\n hoverTimeoutRef.current = setTimeout(() => {\n setIsOpen(false)\n }, 100)\n }\n }, [triggerMode, isDisabled])\n\n React.useEffect(() => {\n if (!isOpen || triggerMode !== \"hover\" || isDisabled) return\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n const isOver = wrapperRef.current?.contains(target) ||\n contentRef.current?.contains(target)\n\n if (!isOver) {\n handleHoverIntent(false)\n } else {\n handleHoverIntent(true)\n }\n }\n\n window.addEventListener(\"mousemove\", handleMouseMove)\n return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n }, [isOpen, triggerMode, isDisabled, handleHoverIntent])\n\n React.useEffect(() => {\n return () => {\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n }\n }\n }, [])\n\n const [uncontrolledSelectedKey, setUncontrolledSelectedKey] = React.useState<Key | null>(\n defaultSelectedKey ?? null\n )\n const [uncontrolledSelectedKeys, setUncontrolledSelectedKeys] = React.useState<Set<Key>>(\n new Set(defaultSelectedKeys)\n )\n const [selectedTextValue, setSelectedTextValue] = React.useState(valueLabel ?? defaultValue ?? \"\")\n const selectedKey = controlledSelectedKey !== undefined ? controlledSelectedKey : uncontrolledSelectedKey\n const selectedKeys = controlledSelectedKeys !== undefined ? new Set(controlledSelectedKeys) : uncontrolledSelectedKeys\n\n const nav = useListNavigation({\n isOpen,\n externalItems: propItems.length > 0 ? propItems : undefined,\n filter: filter ? (item: any) => filter({ ...item, label: item.textValue } as any) : undefined\n })\n\n const registerItem = React.useCallback((key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => {\n nav.registerItem(key, textValue, isDisabled)\n itemExtrasRef.current.set(key, { onSelect, isSubmenuTrigger })\n }, [nav.registerItem])\n\n const unregisterItem = React.useCallback((key: Key) => {\n nav.unregisterItem(key)\n itemExtrasRef.current.delete(key)\n }, [nav.unregisterItem])\n\n const isFocusedItemSubmenu = React.useCallback(() => {\n if (nav.focusedKey === null) return false\n return itemExtrasRef.current.get(nav.focusedKey)?.isSubmenuTrigger ?? false\n }, [nav.focusedKey])\n\n const markKeyboardNavigation = React.useCallback(() => {\n mouseMoveDetectedRef.current = false\n keyboardScrollIntentRef.current = true\n }, [])\n\n const moveFocusFromTrigger = React.useCallback((direction: 1 | -1) => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return false\n return focusAdjacentTabStop(triggerElement, direction, wrapperRef.current)\n }, [])\n\n const restoreFocus = React.useCallback((target: \"auto\" | \"trigger\" | \"row\" = \"auto\") => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return\n\n const ownerRow = triggerElement.closest<HTMLElement>('[data-list-focus-owner=\"true\"]')\n const focusTarget = target === \"row\"\n ? ownerRow\n : target === \"trigger\"\n ? triggerElement\n : ownerRow ?? triggerElement\n\n focusTarget?.focus({ preventScroll: true })\n }, [])\n\n const onSelect = React.useCallback((key: Key) => {\n const item = nav.items.find(i => i.key === key)\n if (item) {\n setSelectedTextValue(item.textValue)\n }\n if (controlledSelectedKey === undefined) {\n setUncontrolledSelectedKey(key)\n }\n onSelectionChange?.(key)\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n }, [controlledSelectedKey, onSelectionChange, nav.items, restoreFocus])\n\n const onToggle = React.useCallback((key: Key) => {\n const newKeys = new Set(selectedKeys)\n if (newKeys.has(key)) {\n newKeys.delete(key)\n } else {\n newKeys.add(key)\n }\n if (controlledSelectedKeys === undefined) {\n setUncontrolledSelectedKeys(newKeys)\n }\n onSelectionChange?.(Array.from(newKeys))\n }, [selectedKeys, controlledSelectedKeys, onSelectionChange])\n\n const selectFocusedItem = React.useCallback(() => {\n if (nav.focusedKey !== null) {\n const item = nav.enabledFilteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n const extras = itemExtrasRef.current.get(nav.focusedKey)\n if (extras?.onSelect) {\n extras.onSelect()\n } else if (mode === \"multiple\") {\n onToggle(nav.focusedKey)\n } else {\n onSelect(nav.focusedKey)\n }\n }\n }\n }, [nav.focusedKey, nav.enabledFilteredItems, onSelect, onToggle, mode])\n\n React.useEffect(() => {\n if (isOpen) {\n // Only initialize focusedKey if it's not already valid\n if (nav.focusedKey !== null && nav.visibleKeys.has(nav.focusedKey)) {\n const item = nav.filteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n return // Keep current keyboard focus, don't reset it\n }\n }\n\n const focusKey = mode === \"multiple\" && selectedKeys.size > 0\n ? Array.from(selectedKeys)[0]\n : selectedKey\n\n if (focusKey !== null && nav.visibleKeys.has(focusKey)) {\n const item = nav.filteredItems.find(item => item.key === focusKey)\n if (item && !item.isDisabled) {\n nav.setFocusedKey(focusKey)\n return\n }\n }\n if (nav.enabledFilteredItems.length > 0) {\n nav.setFocusedKey(nav.enabledFilteredItems[0].key)\n } else {\n nav.setFocusedKey(null)\n }\n }\n }, [isOpen, selectedKey, selectedKeys, nav.visibleKeys, nav.enabledFilteredItems, nav.filteredItems, mode, nav.focusedKey])\n\n const { buttonProps, isPressed } = useButton({\n isDisabled,\n onPress: (e) => {\n if (isDisabled) return\n // Keyboard interactions are handled by onKeyDown to prevent conflicts\n if (e.pointerType !== 'keyboard') {\n setIsOpen(prev => !prev)\n }\n },\n }, triggerRef)\n const { focusProps, isFocused, isFocusVisible } = useFocusRing()\n const { hoverProps, isHovered } = useHover({\n isDisabled,\n onHoverStart: () => handleHoverIntent(true),\n onHoverEnd: () => handleHoverIntent(false),\n })\n\n const triggerProps = mergeProps(buttonProps, focusProps, hoverProps, {\n 'aria-haspopup': 'listbox' as const,\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? contentId : undefined,\n 'aria-disabled': isDisabled || undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || (e.key === ' ' && !isDisabled)) {\n e.preventDefault()\n setIsOpen(true)\n }\n return\n }\n\n if (e.key === 'Tab') {\n e.preventDefault()\n const direction = e.shiftKey ? -1 : 1\n setIsOpen(false)\n nav.setSearchValue(\"\")\n moveFocusFromTrigger(direction as 1 | -1)\n return\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n markKeyboardNavigation()\n }\n\n handleListKeyDown(e, {\n navigateNext: nav.navigateToNextItem,\n navigatePrev: nav.navigateToPrevItem,\n confirm: selectFocusedItem,\n close: () => {\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n },\n filteredItems: nav.filteredItems,\n setFocusedKey: nav.setFocusedKey,\n })\n },\n })\n\n React.useEffect(() => {\n if (autoFocus && triggerRef.current) {\n triggerRef.current.focus({ preventScroll: true })\n }\n }, [autoFocus])\n\n React.useEffect(() => {\n if (mode === \"single\") {\n if (selectedKey === null) {\n setSelectedTextValue(\"\")\n } else {\n const selectedItem = nav.items.find(item => item.key === selectedKey)\n if (selectedItem) {\n setSelectedTextValue(selectedItem.textValue)\n } else if (valueLabel !== undefined) {\n setSelectedTextValue(valueLabel)\n } else if (defaultValue !== undefined && defaultValue !== null) {\n setSelectedTextValue(defaultValue)\n }\n }\n }\n }, [selectedKey, nav.items, mode, defaultValue, valueLabel])\n\n const childrenArray = React.Children.toArray(children)\n const trigger = childrenArray.find(child => React.isValidElement(child) && (\n (child.type as any)?.displayName === 'SelectTrigger' ||\n (child.type as any)?.displayName === 'SearchableTrigger'\n ))\n const contentItems = childrenArray.filter(child => React.isValidElement(child) && ((child.type as any)?.displayName === 'SelectContent' || (child.type as any)?.displayName === 'SearchableContent'))\n const otherContent = childrenArray.filter(child => !React.isValidElement(child) || (\n (child.type as any)?.displayName !== 'SelectTrigger' &&\n (child.type as any)?.displayName !== 'SearchableTrigger' &&\n (child.type as any)?.displayName !== 'SelectContent' &&\n (child.type as any)?.displayName !== 'SearchableContent'\n ))\n const hasExternalValue = otherContent.some(child => (\n React.isValidElement(child) && (child.type as any)?.displayName === 'SelectValue'\n ))\n const triggerType = React.isValidElement(trigger) && (trigger.type as any)?.displayName === 'SearchableTrigger'\n ? 'input'\n : 'button'\n\n const resolvedStyles = resolveSelectStyles(stylesProp);\n const mergedRootRef = useMergeRefs<HTMLDivElement>(scopeRef, wrapperRef, ref)\n const { indicatorProps } = useFocus({\n scopeRef,\n containerRef: wrapperRef,\n surfaceSelector: '[data-select-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n dependencies: [mode],\n });\n\n return (\n <SelectContext.Provider\n value={{\n isOpen,\n setIsOpen,\n contentPlacement,\n setContentPlacement,\n triggerType,\n mode,\n selectedKey,\n selectedKeys: mode === \"multiple\" ? selectedKeys : undefined,\n selectedTextValue,\n onSelect,\n onToggle: mode === \"multiple\" ? onToggle : undefined,\n triggerRef,\n wrapperRef,\n contentRef,\n triggerProps,\n isFocused,\n isFocusVisible,\n isPressed,\n isHovered,\n isDisabled,\n items: nav.items,\n registerItem,\n unregisterItem,\n searchValue: nav.searchValue,\n setSearchValue: nav.setSearchValue,\n filteredItems: nav.filteredItems,\n visibleKeys: nav.visibleKeys,\n focusedKey: nav.focusedKey,\n setFocusedKey: nav.setFocusedKey,\n navigateToNextItem: nav.navigateToNextItem,\n navigateToPrevItem: nav.navigateToPrevItem,\n selectFocusedItem,\n isFocusedItemSubmenu,\n maxItems,\n triggerMode,\n handleHoverIntent,\n mouseMoveDetectedRef,\n keyboardScrollIntentRef,\n markKeyboardNavigation,\n moveFocusFromTrigger,\n filter,\n contentId,\n hasExternalValue,\n restoreFocus,\n }}\n >\n <div\n ref={mergedRootRef}\n className={cn('select', styles.select, className, resolvedStyles.root)}\n data-mode={mode}\n data-select-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n {...domProps}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {otherContent}\n {trigger}\n {contentItems}\n </div>\n </SelectContext.Provider>\n )\n }\n)\nSelect.displayName = \"Select\"\n\nexport { Select, SelectContext }\n",
|
|
5132
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n
|
|
5045
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n transition: box-shadow 150ms var(--ease-snappy-pop), border-color 150ms var(--ease-snappy-pop);\n\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-in-from-bottom { from { opacity: 0; translate: 0 2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-from-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n @keyframes slide-out-from-bottom { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 2px; } }\n}\n",
|
|
5133
5046
|
"cssTypes": "declare const styles: {\n scope: string;\n select: string;\n \"select-split\": string;\n trigger: string;\n \"trigger-compact\": string;\n input: string;\n \"search-trigger\": string;\n \"search-value-section\": string;\n \"search-content-input\": string;\n \"search-icon-section\": string;\n \"search-wrapper\": string;\n \"empty-state\": string;\n \"value-section\": string;\n \"icon-section\": string;\n icon: string;\n value: string;\n \"value-icon\": string;\n \"value-text\": string;\n \"value-chevron\": string;\n \"content-root\": string;\n content: string;\n viewport: string;\n list: string;\n item: string;\n \"item-icon\": string;\n \"item-indicator\": string;\n \"item-text\": string;\n \"item-content\": string;\n \"item-description\": string;\n \"item-with-description\": string;\n \"item-icon-with-description\": string;\n \"item-indicator-with-description\": string;\n separator: string;\n \"scroll-button\": string;\n placeholder: string;\n \"icon-prefix\": string;\n \"sub-trigger\": string;\n \"sub-trigger-chevron\": string;\n \"sub-content-root\": string;\n \"sub-content\": string;\n};\n\nexport default styles;\n"
|
|
5134
5047
|
},
|
|
5135
5048
|
"slider": {
|
|
5136
5049
|
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\n\nimport css from \"./Slider.module.css\";\n\ntype SliderOrientation = \"horizontal\" | \"vertical\";\n\nexport interface SliderStyleSlots {\n root?: StyleValue;\n track?: StyleValue;\n range?: StyleValue;\n thumb?: StyleValue;\n}\n\nexport type SliderStylesProp = StylesProp<SliderStyleSlots>;\n\nconst resolveSliderBaseStyles = createStylesResolver([\n \"root\",\n \"track\",\n \"range\",\n \"thumb\",\n] as const);\n\nfunction resolveSliderStyles(styles: SliderStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveSliderBaseStyles(styles);\n }\n\n const { root, track, range, thumb } = styles;\n\n return resolveSliderBaseStyles({\n root,\n track,\n range,\n thumb,\n });\n}\n\nexport interface SliderProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"defaultValue\" | \"value\" | \"onChange\"> {\n /** Whether the slider is disabled. */\n disabled?: boolean;\n /** Minimum value of the slider range. */\n min?: number;\n /** Maximum value of the slider range. */\n max?: number;\n /** Step increment between values. */\n step?: number;\n /** Initial value or values for uncontrolled usage. */\n defaultValue?: number | number[];\n /** Controlled value or values for the slider thumbs. */\n value?: number | number[];\n /** Called when the slider value changes. */\n onValueChange?: (value: number[]) => void;\n /** Orientation of the slider track. */\n orientation?: SliderOrientation;\n /** Accessible label for the slider. */\n \"aria-label\"?: string;\n /** ID of an element that labels the slider. */\n \"aria-labelledby\"?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: SliderStylesProp;\n}\n\ninterface SliderThumbProps {\n index: number;\n value: number;\n min: number;\n max: number;\n step: number;\n disabled?: boolean;\n orientation: SliderOrientation;\n onValueChange: (index: number, value: number) => void;\n onThumbRef: (index: number, element: HTMLDivElement | null) => void;\n isDragging?: boolean;\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n className?: string;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction snapToStep(value: number, min: number, max: number, step: number): number {\n const effectiveStep = Number.isFinite(step) && step > 0 ? step : 1;\n const snapped = Math.round((value - min) / effectiveStep) * effectiveStep + min;\n const precision = Math.min(\n Math.max(getDecimalPrecision(effectiveStep), getDecimalPrecision(min), getDecimalPrecision(max)),\n 12\n );\n\n return clamp(Number(snapped.toFixed(precision)), min, max);\n}\n\nfunction normalizeValue(value: number | number[] | undefined): number[] | undefined {\n if (value === undefined) return undefined;\n return Array.isArray(value) ? value : [value];\n}\n\nfunction getValuePercent(value: number, min: number, max: number): number {\n if (max <= min) return 0;\n return ((value - min) / (max - min)) * 100;\n}\n\nfunction getDecimalPrecision(value: number): number {\n if (!Number.isFinite(value)) return 0;\n\n const valueString = value.toString();\n const exponentMatch = valueString.match(/e-(\\d+)$/);\n\n if (exponentMatch) {\n return Number(exponentMatch[1]);\n }\n\n return valueString.split(\".\")[1]?.length ?? 0;\n}\n\nfunction getClosestValueIndex(values: number[], targetValue: number): number {\n let closestIndex = 0;\n let closestDistance = Math.abs(values[0] - targetValue);\n\n for (let index = 1; index < values.length; index += 1) {\n const distance = Math.abs(values[index] - targetValue);\n if (distance < closestDistance) {\n closestDistance = distance;\n closestIndex = index;\n }\n }\n\n return closestIndex;\n}\n\nfunction getThumbIndexFromTarget(target: EventTarget | null): number | undefined {\n if (!(target instanceof Element)) return undefined;\n\n const thumb = target.closest<HTMLElement>(\"[data-slider-thumb-index]\");\n if (!thumb) return undefined;\n\n const index = Number(thumb.dataset.sliderThumbIndex);\n return Number.isInteger(index) ? index : undefined;\n}\n\nfunction getValueFromPointer(\n clientX: number,\n clientY: number,\n track: HTMLDivElement,\n orientation: SliderOrientation,\n min: number,\n max: number,\n step: number\n) {\n const rect = track.getBoundingClientRect();\n const size = orientation === \"vertical\" ? rect.height : rect.width;\n\n if (size <= 0) return min;\n\n const percent =\n orientation === \"vertical\"\n ? clamp((rect.bottom - clientY) / rect.height, 0, 1)\n : clamp((clientX - rect.left) / rect.width, 0, 1);\n\n const rawValue = percent * (max - min) + min;\n return snapToStep(rawValue, min, max, step);\n}\n\nfunction SliderThumb({\n index,\n value,\n min,\n max,\n step,\n disabled,\n orientation,\n onValueChange,\n onThumbRef,\n isDragging,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n className,\n}: SliderThumbProps) {\n const thumbRef = React.useRef<HTMLDivElement>(null);\n const [isPressed, setIsPressed] = React.useState(false);\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n const handleThumbRef = React.useCallback(\n (element: HTMLDivElement | null) => {\n onThumbRef(index, element);\n },\n [index, onThumbRef]\n );\n const mergedRef = useMergeRefs<HTMLDivElement>(thumbRef, handleThumbRef);\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef: thumbRef,\n containerRef: thumbRef,\n surfaceSelector: '[data-slider-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n dependencies: [value, orientation, disabled],\n });\n\n const percent = getValuePercent(value, min, max);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n\n let newValue = value;\n const largeStep = step * 10;\n const incrementValue = (amount: number) => snapToStep(value + amount, min, max, step);\n\n switch (event.key) {\n case \"ArrowRight\":\n newValue = orientation === \"horizontal\" ? incrementValue(step) : value;\n break;\n case \"ArrowUp\":\n newValue = incrementValue(step);\n break;\n case \"ArrowLeft\":\n newValue = orientation === \"horizontal\" ? incrementValue(-step) : value;\n break;\n case \"ArrowDown\":\n newValue = incrementValue(-step);\n break;\n case \"PageUp\":\n newValue = incrementValue(largeStep);\n break;\n case \"PageDown\":\n newValue = incrementValue(-largeStep);\n break;\n case \"Home\":\n newValue = min;\n break;\n case \"End\":\n newValue = max;\n break;\n default:\n return;\n }\n\n event.preventDefault();\n setIsPressed(true);\n\n if (newValue !== value) {\n onValueChange(index, newValue);\n }\n },\n [disabled, index, max, min, onValueChange, orientation, step, value]\n );\n\n const handleKeyUp = React.useCallback(() => {\n setIsPressed(false);\n }, []);\n\n const positionStyle =\n orientation === \"vertical\"\n ? { bottom: `${percent}%` }\n : { left: `${percent}%` };\n\n return (\n <div\n ref={mergedRef}\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-orientation={orientation}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-disabled={disabled || undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={cn(\"thumb\", scopeProps.className, css.thumb, className)}\n style={positionStyle}\n data-slider-thumb=\"true\"\n data-slider-thumb-index={index}\n data-disabled={disabled ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-pressed={isPressed || isDragging ? \"true\" : undefined}\n data-dragging={isDragging ? \"true\" : undefined}\n data-slider-focus-surface=\"true\"\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n {...asElementProps<\"div\">(mergeProps(focusProps, hoverProps))}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n </div>\n );\n}\n\nconst Slider = React.forwardRef<HTMLDivElement, SliderProps>(\n (\n {\n className,\n styles,\n disabled = false,\n style,\n defaultValue,\n value: controlledValue,\n onValueChange,\n min = 0,\n max = 100,\n step = 1,\n orientation = \"horizontal\",\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onLostPointerCapture,\n ...props\n },\n ref\n ) => {\n const rootRef = React.useRef<HTMLDivElement>(null);\n const trackRef = React.useRef<HTMLDivElement>(null);\n const thumbRefs = React.useRef<Array<HTMLDivElement | null>>([]);\n const activeDragRef = React.useRef<{ pointerId: number; thumbIndex: number } | null>(null);\n const [draggingThumbIndex, setDraggingThumbIndex] = React.useState<number | null>(null);\n\n const [internalValues, setInternalValues] = React.useState<number[]>(\n () => normalizeValue(defaultValue) ?? normalizeValue(controlledValue) ?? [min]\n );\n\n const isControlled = controlledValue !== undefined;\n const normalizedValues = isControlled\n ? normalizeValue(controlledValue) ?? [min]\n : internalValues;\n const values = normalizedValues.length > 0 ? normalizedValues : [min];\n\n const mergedRef = useMergeRefs(ref, rootRef);\n const resolved = resolveSliderStyles(styles);\n\n const setThumbRef = React.useCallback((index: number, element: HTMLDivElement | null) => {\n thumbRefs.current[index] = element;\n }, []);\n\n const handleValueChange = React.useCallback(\n (index: number, newValue: number) => {\n if (values[index] === newValue) return;\n\n const nextValues = [...values];\n nextValues[index] = newValue;\n\n if (!isControlled) {\n setInternalValues(nextValues);\n }\n\n onValueChange?.(nextValues);\n },\n [isControlled, onValueChange, values]\n );\n\n const updateValueFromPointer = React.useCallback(\n (thumbIndex: number, clientX: number, clientY: number) => {\n const track = trackRef.current;\n if (!track) return undefined;\n\n const newValue = getValueFromPointer(\n clientX,\n clientY,\n track,\n orientation,\n min,\n max,\n step\n );\n\n handleValueChange(thumbIndex, newValue);\n return newValue;\n },\n [handleValueChange, max, min, orientation, step]\n );\n\n const stopPointerDrag = React.useCallback((pointerId: number, releaseCapture = true) => {\n const activeDrag = activeDragRef.current;\n if (!activeDrag || activeDrag.pointerId !== pointerId) return;\n\n const root = rootRef.current;\n if (releaseCapture && root?.releasePointerCapture) {\n try {\n if (!root.hasPointerCapture || root.hasPointerCapture(pointerId)) {\n root.releasePointerCapture(pointerId);\n }\n } catch {\n // Pointer capture can already be gone after browser-level cancellation.\n }\n }\n\n activeDragRef.current = null;\n setDraggingThumbIndex(null);\n }, []);\n\n const startPointerDrag = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>, requestedThumbIndex?: number) => {\n if (disabled || event.button !== 0 || event.isPrimary === false) return;\n\n const track = trackRef.current;\n const root = rootRef.current ?? event.currentTarget;\n if (!track || !root) return;\n\n const nextValue = getValueFromPointer(\n event.clientX,\n event.clientY,\n track,\n orientation,\n min,\n max,\n step\n );\n const thumbIndex =\n requestedThumbIndex !== undefined && requestedThumbIndex >= 0 && requestedThumbIndex < values.length\n ? requestedThumbIndex\n : getClosestValueIndex(values, nextValue);\n\n event.preventDefault();\n\n activeDragRef.current = { pointerId: event.pointerId, thumbIndex };\n setDraggingThumbIndex(thumbIndex);\n\n if (root.setPointerCapture) {\n try {\n root.setPointerCapture(event.pointerId);\n } catch {\n // Some test and embedded environments expose the API without active pointer capture support.\n }\n }\n\n thumbRefs.current[thumbIndex]?.focus({ preventScroll: true });\n handleValueChange(thumbIndex, nextValue);\n },\n [disabled, handleValueChange, max, min, orientation, step, values]\n );\n\n const handleRootPointerDown = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event);\n if (event.defaultPrevented) return;\n\n startPointerDrag(event, getThumbIndexFromTarget(event.target));\n },\n [onPointerDown, startPointerDrag]\n );\n\n const handleRootPointerMove = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event);\n if (event.defaultPrevented || disabled) return;\n\n const activeDrag = activeDragRef.current;\n if (!activeDrag || activeDrag.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n updateValueFromPointer(activeDrag.thumbIndex, event.clientX, event.clientY);\n },\n [disabled, onPointerMove, updateValueFromPointer]\n );\n\n const handleRootPointerEnd = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerUp?.(event);\n stopPointerDrag(event.pointerId);\n },\n [onPointerUp, stopPointerDrag]\n );\n\n const handleRootPointerCancel = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onPointerCancel?.(event);\n stopPointerDrag(event.pointerId);\n },\n [onPointerCancel, stopPointerDrag]\n );\n\n const handleRootLostPointerCapture = React.useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n onLostPointerCapture?.(event);\n stopPointerDrag(event.pointerId, false);\n },\n [onLostPointerCapture, stopPointerDrag]\n );\n\n React.useEffect(() => {\n const activeDrag = activeDragRef.current;\n if (disabled && activeDrag) {\n stopPointerDrag(activeDrag.pointerId);\n }\n }, [disabled, stopPointerDrag]);\n\n const rangeStartPercent =\n values.length > 1 ? getValuePercent(values[0], min, max) : 0;\n const rangeEndPercent = getValuePercent(values[values.length - 1], min, max);\n\n const rangeStyle =\n orientation === \"vertical\"\n ? {\n bottom: `${rangeStartPercent}%`,\n height: `${Math.max(rangeEndPercent - rangeStartPercent, 0)}%`,\n }\n : {\n left: `${rangeStartPercent}%`,\n width: `${Math.max(rangeEndPercent - rangeStartPercent, 0)}%`,\n };\n\n return (\n <div\n ref={mergedRef}\n data-disabled={disabled ? \"true\" : undefined}\n data-orientation={orientation}\n style={style}\n className={cn(\n \"slider\",\n css.slider,\n className,\n resolved.root\n )}\n onPointerDown={handleRootPointerDown}\n onPointerMove={handleRootPointerMove}\n onPointerUp={handleRootPointerEnd}\n onPointerCancel={handleRootPointerCancel}\n onLostPointerCapture={handleRootLostPointerCapture}\n {...props}\n >\n <div\n ref={trackRef}\n className={cn(\"track\", css.track, resolved.track)}\n data-slider-track=\"true\"\n data-disabled={disabled ? \"true\" : undefined}\n data-orientation={orientation}\n >\n <div\n className={cn(\"range\", css.range, resolved.range)}\n data-slider-range=\"true\"\n data-disabled={disabled ? \"true\" : undefined}\n style={rangeStyle}\n />\n {values.map((sliderValue, index) => (\n <SliderThumb\n key={index}\n index={index}\n value={sliderValue}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n orientation={orientation}\n onValueChange={handleValueChange}\n onThumbRef={setThumbRef}\n isDragging={draggingThumbIndex === index}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className={resolved.thumb}\n />\n ))}\n </div>\n </div>\n );\n }\n);\n\nSlider.displayName = \"Slider\";\n\nconst SliderComponent = Object.assign(Slider, {\n Root: Slider,\n});\n\nexport { SliderComponent as Slider };\n",
|
|
5137
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .slider {\n --disabled-opacity: 0.6;\n --slider-track-size: 0.375rem;\n --slider-thumb-size: 1rem;\n\n @apply relative flex w-full items-center;\n min-inline-size: var(--slider-min-inline-size, 12rem);\n min-height: var(--slider-hit-size, 2rem);\n touch-action: none;\n user-select: none;\n }\n\n .track {\n @apply relative flex grow items-center;\n flex-grow: 1;\n height: var(--slider-track-size);\n overflow: visible;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n border: var(--slider-track-border, 0);\n background: var(--slider-track-background, var(--background));\n }\n\n .range {\n @apply absolute;\n display: var(--slider-range-display, block);\n pointer-events: none;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n background: var(--slider-range-background, var(--background));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb {\n @apply absolute block;\n top: 50%;\n width: var(--slider-thumb-size);\n height: var(--slider-thumb-size);\n transform: var(--slider-thumb-transform, translate(-50%, -50%));\n border-radius: var(--radius-full, 9999px);\n outline: none;\n background: var(--slider-thumb-background, var(--background));\n border: var(--slider-thumb-border, 1px solid var(--background-border));\n box-shadow: var(--slider-thumb-shadow, none);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .slider[data-orientation=\"horizontal\"] .range {\n top: 0;\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] {\n justify-content: center;\n min-inline-size: auto;\n width: fit-content;\n }\n\n .slider[data-orientation=\"vertical\"] .track {\n width: var(--slider-track-size);\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .range {\n left: 0;\n width: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .thumb {\n left: 50%;\n top: auto;\n --slider-thumb-transform: translate(-50%, 50%);\n }\n\n .slider[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .slider[data-disabled=\"true\"] .range {\n background: var(--slider-range-background-disabled, var(--background-disabled, var(--slider-range-background, var(--background))));\n }\n\n .thumb[data-disabled=\"true\"] {\n cursor: not-allowed;\n background: var(--slider-thumb-background-disabled, var(--background-disabled, var(--slider-thumb-background, var(--background))));\n }\n\n .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, -50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n\n .slider[data-orientation=\"vertical\"] .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, 50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n}\n",
|
|
5050
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .slider {\n --disabled-opacity: 0.6;\n --slider-track-size: 0.375rem;\n --slider-thumb-size: 1rem;\n\n @apply relative flex w-full items-center;\n min-inline-size: var(--slider-min-inline-size, 12rem);\n min-height: var(--slider-hit-size, 2rem);\n touch-action: none;\n user-select: none;\n }\n\n .track {\n @apply relative flex grow items-center;\n flex-grow: 1;\n height: var(--slider-track-size);\n overflow: visible;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n border: var(--slider-track-border, 0);\n background: var(\n --slider-track-background,\n var(--background, var(--background-800, transparent))\n );\n }\n\n .range {\n @apply absolute;\n display: var(--slider-range-display, block);\n pointer-events: none;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n background: var(--slider-range-background, var(--background));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb {\n @apply absolute block;\n top: 50%;\n width: var(--slider-thumb-size);\n height: var(--slider-thumb-size);\n transform: var(--slider-thumb-transform, translate(-50%, -50%));\n border-radius: var(--radius-full, 9999px);\n outline: none;\n background: var(--slider-thumb-background, var(--background));\n border: var(--slider-thumb-border, 1px solid var(--background-border));\n box-shadow: var(--slider-thumb-shadow, none);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .slider[data-orientation=\"horizontal\"] .range {\n top: 0;\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] {\n justify-content: center;\n min-inline-size: auto;\n width: fit-content;\n }\n\n .slider[data-orientation=\"vertical\"] .track {\n width: var(--slider-track-size);\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .range {\n left: 0;\n width: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .thumb {\n left: 50%;\n top: auto;\n --slider-thumb-transform: translate(-50%, 50%);\n }\n\n .slider[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .slider[data-disabled=\"true\"] .range {\n background: var(--slider-range-background-disabled, var(--background-disabled, var(--slider-range-background, var(--background))));\n }\n\n .thumb[data-disabled=\"true\"] {\n cursor: not-allowed;\n background: var(--slider-thumb-background-disabled, var(--background-disabled, var(--slider-thumb-background, var(--background))));\n }\n\n .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, -50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n\n .slider[data-orientation=\"vertical\"] .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, 50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n}\n",
|
|
5138
5051
|
"cssTypes": "declare const styles: {\n readonly slider: string;\n readonly track: string;\n readonly range: string;\n readonly thumb: string;\n};\n\nexport default styles;\n"
|
|
5139
5052
|
},
|
|
5140
5053
|
"switch": {
|
|
5141
5054
|
"tsx": "\"use client\";\n\nimport React from \"react\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useSwitch } from \"@react-aria/switch\";\n\nimport { useToggleState } from \"react-stately\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\n\nimport styles from \"./Switch.module.css\";\n\n\n\ninterface SwitchStyleSlots {\n root?: StyleValue;\n track?: StyleValue;\n thumb?: StyleValue;\n}\n\ntype SwitchStylesProp = StylesProp<SwitchStyleSlots>;\n\nconst resolveSwitchBaseStyles = createStylesResolver(['root', 'track', 'thumb'] as const) as (stylesProp?: SwitchStylesProp) => SwitchStyleSlots;\n\nexport interface SwitchProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"type\" | \"size\" | \"onChange\" | \"checked\" | \"defaultChecked\"> {\n /** Controlled selected (on) state */\n isSelected?: boolean;\n /** Called when the switch is toggled */\n onChange?: (isSelected: boolean) => void;\n /** Initial selected state for uncontrolled usage */\n defaultSelected?: boolean;\n\n /** Whether the switch is disabled */\n isDisabled?: boolean;\n /** Size of the switch */\n size?: \"default\" | \"sm\";\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: SwitchStylesProp;\n}\n\n\nconst Switch = React.forwardRef<HTMLInputElement, SwitchProps>(\n ({\n className,\n styles: stylesProp,\n isDisabled = false,\n isSelected: controlledSelected,\n onChange,\n defaultSelected,\n size = \"default\",\n ...props\n },\n ref\n ) => {\n const state = useToggleState({\n isSelected: controlledSelected,\n defaultSelected: defaultSelected ?? false,\n onChange,\n });\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const rootRef = React.useRef<HTMLDivElement>(null);\n\n // Extract aria-label from props if provided\n const { \"aria-label\": ariaLabel, \"aria-labelledby\": ariaLabelledby, ...otherProps } = props;\n\n const { inputProps, isSelected } = useSwitch(\n {\n isDisabled,\n ...(ariaLabel && { \"aria-label\": ariaLabel }),\n ...(ariaLabelledby && { \"aria-labelledby\": ariaLabelledby }),\n },\n state,\n inputRef\n );\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled });\n\n const { indicatorProps } = useFocus({\n scopeRef: rootRef,\n containerRef: rootRef,\n surfaceSelector: '[data-switch-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n });\n\n React.useImperativeHandle(ref, () => inputRef.current!);\n\n const resolved = resolveSwitchBaseStyles(stylesProp);\n\n return (\n <div\n ref={rootRef}\n className={cn(\n 'switch',\n styles.switch,\n size === \"sm\" && styles[\"switch-sm\"],\n className,\n resolved.root\n )}\n data-switch-focus-surface=\"true\"\n data-selected={isSelected || undefined}\n data-disabled={isDisabled || undefined}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n data-hovered={isHovered || undefined}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n className={cn(\n 'switch-track',\n styles[\"switch-track\"],\n resolved.track\n )}\n />\n <div\n className={cn(\n 'switch-thumb',\n styles[\"switch-thumb\"],\n resolved.thumb\n )}\n />\n <input\n ref={inputRef}\n type=\"checkbox\"\n className=\"absolute inset-0 w-full h-full opacity-0 cursor-pointer\"\n aria-checked={isSelected}\n {...mergeProps(inputProps, focusProps, hoverProps)}\n {...otherProps}\n />\n </div>\n );\n }\n);\n\nSwitch.displayName = \"Switch\";\n\nexport { Switch };\n",
|
|
5142
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .switch {\n --radius: 9999px;\n --inner-radius: calc(var(--radius) - var(--border-width-base));\n\n --width: 2.75rem;\n --height: 1.5rem;\n --thumb-size: 1rem;\n --thumb-offset: 0.25rem;\n\n --disabled-opacity: 0.6;\n\n @apply relative inline-flex cursor-pointer items-center;\n user-select: none;\n border-radius: var(--radius);\n width: var(--width);\n height: var(--height);\n }\n\n .switch-track {\n @apply absolute inset-0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-radius: var(--radius);\n }\n\n .switch:active:not([data-disabled]) .switch-track {\n transform: scale(0.98);\n }\n\n .switch-thumb {\n @apply absolute top-0 bottom-0 my-auto;\n left: var(--thumb-offset);\n width: var(--thumb-size);\n height: var(--thumb-size);\n transition: left 180ms var(--ease-snappy-pop), background-color 180ms var(--ease-snappy-pop);\n background-color: var(--foreground);\n border-radius: var(--inner-radius);\n z-index: 1;\n pointer-events: none;\n }\n\n .switch[data-selected] .switch-
|
|
5055
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .switch {\n --radius: 9999px;\n --inner-radius: calc(var(--radius) - var(--border-width-base));\n\n --width: 2.75rem;\n --height: 1.5rem;\n --thumb-size: 1rem;\n --thumb-offset: 0.25rem;\n\n --disabled-opacity: 0.6;\n\n @apply relative inline-flex cursor-pointer items-center;\n user-select: none;\n border-radius: var(--radius);\n width: var(--width);\n height: var(--height);\n }\n\n .switch-track {\n @apply absolute inset-0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n border: var(--border-width-base) solid var(--background-border);\n border-radius: var(--radius);\n }\n\n .switch:active:not([data-disabled]) .switch-track {\n transform: scale(0.98);\n }\n\n .switch-thumb {\n @apply absolute top-0 bottom-0 my-auto;\n left: var(--thumb-offset);\n width: var(--thumb-size);\n height: var(--thumb-size);\n transition: left 180ms var(--ease-snappy-pop), background-color 180ms var(--ease-snappy-pop);\n background-color: var(--foreground);\n border-radius: var(--inner-radius);\n z-index: 1;\n pointer-events: none;\n }\n\n .switch[data-selected] .switch-thumb {\n left: calc(var(--width) - var(--thumb-size) - var(--thumb-offset));\n }\n\n @media (hover: hover) {\n .switch[data-hovered=\"true\"]:not([data-disabled]) .switch-track {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .switch[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n\n .switch-sm {\n --width: 1.75rem;\n --height: 1rem;\n --thumb-size: 0.625rem;\n --thumb-offset: 0.1875rem;\n }\n}\n",
|
|
5143
5056
|
"cssTypes": "export interface Styles {\n switch: string;\n \"switch-track\": string;\n \"switch-thumb\": string;\n \"switch-sm\": string;\n\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
|
|
5144
5057
|
},
|
|
5145
5058
|
"table": {
|
|
5146
5059
|
"tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { Input } from \"@/components/Input\";\nimport { type StyleValue, cn } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\n\nimport css from \"./Table.module.css\";\n\nexport interface Column<T> {\n /** Key of the data row object to display in this column */\n key: keyof T;\n /** Column header label displayed in the table head */\n label: string;\n /** Whether the column supports sorting (reserved for future use) */\n sortable?: boolean;\n /** Whether a filter input is shown for this column when showFilters is enabled */\n filterable?: boolean;\n /** Custom render function for the cell; receives the cell value and full row */\n render?: (value: any, row: T) => React.ReactNode;\n}\n\ninterface TableStyleSlots {\n root?: StyleValue;\n container?: StyleValue;\n filterBar?: StyleValue;\n filterGrid?: StyleValue;\n filterLabel?: StyleValue;\n filterInput?: StyleValue;\n table?: StyleValue;\n header?: StyleValue;\n body?: StyleValue;\n headerRow?: StyleValue;\n headerCell?: StyleValue;\n row?: StyleValue;\n cell?: StyleValue;\n emptyRow?: StyleValue;\n emptyState?: StyleValue;\n}\n\ntype TableStylesProp = StylesProp<TableStyleSlots>;\n\nexport type TableSortState<T> = {\n column: keyof T | null;\n direction: \"ascending\" | \"descending\" | null;\n};\n\nexport type TableFilterState = Record<string, string>;\n\nexport interface TableProps<T extends Record<string, any>>\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"children\"> {\n /** Array of data rows to display */\n data: T[];\n /** Column definitions including key, label, and optional render function */\n columns: Column<T>[];\n /** Whether to show filter inputs above the table */\n showFilters?: boolean;\n /** Called when a table row is clicked */\n onRowClick?: (row: T) => void;\n /** Called when any column filter value changes */\n onFilterChange?: (filters: Record<string, string>) => void;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: TableStylesProp;\n /** Optional composed table content. When omitted, the default header/body renderer is used. */\n children?: React.ReactNode;\n}\n\ntype TableSlotKey = keyof TableStyleSlots;\ntype ResolvedTableStyles = Record<TableSlotKey, string>;\n\nexport interface TableContextValue<T extends Record<string, any> = Record<string, any>> {\n columns: Column<T>[];\n data: T[];\n filteredData: T[];\n selectedRows: Set<React.Key>;\n sortState: TableSortState<T>;\n filterState: TableFilterState;\n setFilterValue: (columnKey: string, value: string) => void;\n onRowClick?: (row: T) => void;\n styles: ResolvedTableStyles;\n}\n\nconst TableContext = React.createContext<TableContextValue | null>(null);\n\nfunction useTableContext<T extends Record<string, any> = Record<string, any>>() {\n const context = React.useContext(TableContext);\n if (!context) {\n throw new Error(\"Table component must be used within Table root\");\n }\n return context as TableContextValue<T>;\n}\n\nconst tableStyleSlotKeys = [\n \"root\",\n \"container\",\n \"filterBar\",\n \"filterGrid\",\n \"filterLabel\",\n \"filterInput\",\n \"table\",\n \"header\",\n \"body\",\n \"headerRow\",\n \"headerCell\",\n \"row\",\n \"cell\",\n \"emptyRow\",\n \"emptyState\",\n] as const;\n\nconst resolveTableBaseStyles = createStylesResolver(tableStyleSlotKeys);\n\nfunction normalizeTableStyles(styles: TableStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return styles;\n }\n\n return {\n root: styles.root,\n container: styles.container,\n filterBar: styles.filterBar,\n filterGrid: styles.filterGrid,\n filterLabel: styles.filterLabel,\n filterInput: styles.filterInput,\n table: styles.table,\n header: styles.header,\n body: styles.body,\n headerRow: styles.headerRow,\n headerCell: styles.headerCell,\n row: styles.row,\n cell: styles.cell,\n emptyRow: styles.emptyRow,\n emptyState: styles.emptyState,\n };\n}\n\nfunction getDefaultSortState<T extends Record<string, any>>(): TableSortState<T> {\n return {\n column: null,\n direction: null,\n };\n}\n\nfunction getRowKey(row: Record<string, any>, index: number): React.Key {\n return row.id ?? row.key ?? index;\n}\n\ntype TableComponent = (<T extends Record<string, any>>(\n props: TableProps<T> & React.RefAttributes<HTMLDivElement>\n) => React.ReactElement | null) & {\n displayName?: string;\n Header: typeof TableHeader;\n Body: typeof TableBody;\n Row: typeof TableRow;\n Cell: typeof TableCell;\n};\n\nconst TableRoot = <T extends Record<string, any>>(\n {\n data,\n columns,\n showFilters = false,\n onRowClick,\n onFilterChange,\n styles,\n className,\n children,\n \"aria-label\": ariaLabel = \"Data table\",\n ...props\n }: TableProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>\n) => {\n const [filterState, setFilterState] = React.useState<TableFilterState>({});\n const [sortState] = React.useState<TableSortState<T>>(() => getDefaultSortState<T>());\n const selectedRows = React.useMemo(() => new Set<React.Key>(), []);\n const resolved = resolveTableBaseStyles(normalizeTableStyles(styles));\n const filterableColumns = React.useMemo(\n () => columns.filter((column) => column.filterable),\n [columns]\n );\n\n const setFilterValue = React.useCallback(\n (columnKey: string, value: string) => {\n setFilterState((currentFilters) => {\n const nextFilters = { ...currentFilters, [columnKey]: value };\n onFilterChange?.(nextFilters);\n return nextFilters;\n });\n },\n [onFilterChange]\n );\n\n const filteredData = React.useMemo(\n () =>\n data.filter((row) =>\n Object.entries(filterState).every(([key, filterValue]) => {\n if (!filterValue) return true;\n const cellValue = String(row[key] ?? \"\").toLowerCase();\n return cellValue.includes(filterValue.toLowerCase());\n })\n ),\n [data, filterState]\n );\n\n const contextValue = React.useMemo<TableContextValue<T>>(\n () => ({\n columns,\n data,\n filteredData,\n selectedRows,\n sortState,\n filterState,\n setFilterValue,\n onRowClick,\n styles: resolved,\n }),\n [\n columns,\n data,\n filteredData,\n selectedRows,\n sortState,\n filterState,\n setFilterValue,\n onRowClick,\n resolved,\n ]\n );\n\n return (\n <TableContext.Provider value={contextValue as TableContextValue}>\n <div\n ref={ref}\n className={cn(\"table\", css.root, className, resolved.root)}\n role=\"region\"\n aria-label={ariaLabel}\n {...props}\n >\n {showFilters && filterableColumns.length > 0 && (\n <div\n className={cn(\"filter-bar\", css.filterBar, resolved.filterBar)}\n data-slot=\"filter-bar\"\n >\n <div\n className={cn(\"filter-grid\", css.filterGrid, resolved.filterGrid)}\n data-slot=\"filter-grid\"\n >\n {filterableColumns.map((column) => {\n const columnKey = String(column.key);\n const inputId = `table-filter-${columnKey}`;\n\n return (\n <div key={columnKey} className={css.filterField}>\n <label\n className={cn(\"filter-label\", css.filterLabel, resolved.filterLabel)}\n data-slot=\"filter-label\"\n htmlFor={inputId}\n >\n {column.label}\n </label>\n <Input\n id={inputId}\n type=\"text\"\n value={filterState[columnKey] || \"\"}\n onChange={(event) => setFilterValue(columnKey, event.target.value)}\n placeholder={`Filter by ${column.label.toLowerCase()}`}\n aria-label={`Filter by ${column.label}`}\n className={cn(css.filterInput, resolved.filterInput)}\n />\n </div>\n );\n })}\n </div>\n </div>\n )}\n\n <div className={cn(\"container\", css.container, resolved.container)} data-slot=\"container\">\n <table\n className={cn(\"element\", css.table, resolved.table)}\n data-slot=\"element\"\n role=\"table\"\n aria-label={ariaLabel}\n >\n {children ?? (\n <>\n <TableHeader />\n <TableBody />\n </>\n )}\n </table>\n </div>\n </div>\n </TableContext.Provider>\n );\n};\n\nconst Table = React.forwardRef(TableRoot) as unknown as TableComponent;\n\nTable.displayName = \"Table\";\n\ninterface TableHeaderProps extends React.HTMLAttributes<HTMLTableSectionElement> {\n /** Optional header content. When omitted, columns from Table context are rendered. */\n children?: React.ReactNode;\n}\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, TableHeaderProps>(\n ({ className, children, ...props }, ref) => {\n const { columns, styles } = useTableContext();\n\n return (\n <thead\n ref={ref}\n className={cn(\"header\", css.header, styles.header, className)}\n data-slot=\"header\"\n role=\"rowgroup\"\n {...props}\n >\n {children ?? (\n <tr\n className={cn(\"header-row\", css.headerRow, styles.headerRow)}\n data-slot=\"header-row\"\n role=\"row\"\n >\n {columns.map((column) => (\n <th\n key={String(column.key)}\n className={cn(\"header-cell\", css.headerCell, styles.headerCell)}\n data-slot=\"header-cell\"\n scope=\"col\"\n role=\"columnheader\"\n aria-sort=\"none\"\n data-sortable={column.sortable ? \"true\" : undefined}\n >\n {column.label}\n </th>\n ))}\n </tr>\n )}\n </thead>\n );\n }\n);\n\nTableHeader.displayName = \"Table.Header\";\n\ninterface TableBodyProps<T extends Record<string, any> = Record<string, any>>\n extends React.HTMLAttributes<HTMLTableSectionElement> {\n /** Optional body content. When omitted, filtered rows from Table context are rendered. */\n children?: React.ReactNode;\n /** Optional rows for custom body composition. Defaults to filtered context data. */\n rows?: T[];\n}\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, TableBodyProps>(\n ({ className, children, rows, ...props }, ref) => {\n const { columns, filteredData, styles } = useTableContext();\n const bodyRows = rows ?? filteredData;\n\n return (\n <tbody\n ref={ref}\n className={cn(\"body\", css.body, styles.body, className)}\n data-slot=\"body\"\n role=\"rowgroup\"\n {...props}\n >\n {children ?? (\n bodyRows.length > 0 ? (\n bodyRows.map((row, index) => (\n <TableRow key={getRowKey(row, index)} row={row} rowIndex={index} />\n ))\n ) : (\n <tr\n className={cn(\"empty-row\", css.emptyRow, styles.emptyRow)}\n data-slot=\"empty-row\"\n role=\"row\"\n >\n <td\n colSpan={columns.length}\n className={cn(\"empty-state\", css.emptyState, styles.emptyState)}\n data-slot=\"empty-state\"\n role=\"cell\"\n >\n No data available\n </td>\n </tr>\n )\n )}\n </tbody>\n );\n }\n);\n\nTableBody.displayName = \"Table.Body\";\n\ninterface TableRowProps<T extends Record<string, any> = Record<string, any>>\n extends React.HTMLAttributes<HTMLTableRowElement> {\n /** Row data used to render default cells. */\n row?: T;\n /** Zero-based index for generated rows. */\n rowIndex?: number;\n /** Marks the row as selected for styling and assistive technology. */\n selected?: boolean;\n /** Marks the row as disabled for future interactive behavior. */\n disabled?: boolean;\n children?: React.ReactNode;\n}\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(\n ({ className, row, rowIndex = 0, selected, disabled, children, onClick, ...props }, ref) => {\n const { columns, selectedRows, onRowClick, styles } = useTableContext();\n const rowKey = row ? getRowKey(row, rowIndex) : rowIndex;\n const isSelected = selected ?? selectedRows.has(rowKey);\n const isInteractive = Boolean(row && onRowClick && !disabled);\n\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLTableRowElement>) => {\n if (!disabled && row) {\n onRowClick?.(row);\n }\n onClick?.(event);\n },\n [disabled, row, onClick, onRowClick]\n );\n\n return (\n <tr\n ref={ref}\n className={cn(\"row\", css.row, styles.row, isInteractive && css.interactive, className)}\n data-slot=\"row\"\n role=\"row\"\n tabIndex={isInteractive ? 0 : undefined}\n aria-selected={isSelected || undefined}\n aria-disabled={disabled || undefined}\n data-selected={isSelected ? \"true\" : undefined}\n data-interactive={isInteractive ? \"true\" : undefined}\n data-disabled={disabled ? \"true\" : undefined}\n onClick={handleClick}\n {...props}\n >\n {children ?? columns.map((column, columnIndex) => (\n <TableCell\n key={String(column.key)}\n row={row}\n column={column}\n columnIndex={columnIndex}\n />\n ))}\n </tr>\n );\n }\n);\n\nTableRow.displayName = \"Table.Row\";\n\ninterface TableCellProps<T extends Record<string, any> = Record<string, any>>\n extends React.TdHTMLAttributes<HTMLTableCellElement> {\n /** Row data used with the column render function. */\n row?: T;\n /** Column definition for this cell. Inferred by columnIndex when omitted. */\n column?: Column<T>;\n /** Zero-based column index used to read the column from context. */\n columnIndex?: number;\n /** Explicit cell value. Defaults to row[column.key]. */\n value?: React.ReactNode;\n}\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>(\n ({ className, row, column, columnIndex, value, children, ...props }, ref) => {\n const { columns, styles } = useTableContext();\n const resolvedColumn = column ?? (columnIndex !== undefined ? columns[columnIndex] : undefined);\n const resolvedValue =\n value ?? (row && resolvedColumn ? row[resolvedColumn.key] : undefined);\n const content =\n children ??\n (resolvedColumn?.render && row\n ? resolvedColumn.render(resolvedValue, row)\n : String(resolvedValue ?? \"\"));\n\n return (\n <td\n ref={ref}\n className={cn(\"cell\", css.cell, styles.cell, className)}\n data-slot=\"cell\"\n role=\"cell\"\n data-column={resolvedColumn ? String(resolvedColumn.key) : undefined}\n {...props}\n >\n {content}\n </td>\n );\n }\n);\n\nTableCell.displayName = \"Table.Cell\";\n\nTable.Header = TableHeader;\nTable.Body = TableBody;\nTable.Row = TableRow;\nTable.Cell = TableCell;\n\nexport { Table, TableHeader, TableBody, TableRow, TableCell, useTableContext };\n",
|
|
5147
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply w-full;\n }\n\n .container {\n @apply w-full overflow-x-auto rounded-
|
|
5060
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply w-full;\n }\n\n .container {\n @apply w-full overflow-x-auto rounded-sm;\n border: var(--border-width-base) solid var(--border, var(--background-border));\n background-color: var(--container-background, var(--background));\n }\n\n .container {\n display: block;\n max-width: none;\n }\n\n .table {\n @apply w-full;\n display: table;\n border-collapse: collapse;\n min-width: max-content;\n background-color: var(--background, transparent);\n color: var(--foreground);\n font-size: var(--text-xs);\n }\n\n .header {\n display: table-header-group;\n background-color: var(--background);\n }\n\n .body {\n display: table-row-group;\n background-color: var(--background);\n }\n\n .headerRow {\n display: table-row;\n background-color: var(--background);\n }\n\n .headerCell {\n @apply px-4 py-3 text-left;\n display: table-cell;\n background-color: var(--background);\n color: var(--foreground);\n font-weight: var(--header-font-weight, var(--font-weight-semibold));\n white-space: nowrap;\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n }\n\n .headerCell:first-child {\n border-top-left-radius: var(--radius-xs);\n }\n\n .headerCell:last-child {\n border-top-right-radius: var(--radius-xs);\n }\n\n .row {\n display: table-row;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row[data-interactive=\"true\"] {\n @apply cursor-pointer;\n }\n\n .row:hover:not([data-disabled=\"true\"]) .cell {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .row[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.5);\n }\n\n .row:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: -2px;\n }\n\n .interactive {\n @apply cursor-pointer;\n }\n\n .cell {\n @apply px-4 py-3 align-middle;\n display: table-cell;\n background-color: var(--background, transparent);\n color: var(--foreground);\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row:last-child .cell {\n border-bottom: none;\n }\n\n .row:last-child .cell:first-child {\n border-bottom-left-radius: var(--radius-xs);\n }\n\n .row:last-child .cell:last-child {\n border-bottom-right-radius: var(--radius-xs);\n }\n\n .emptyRow {\n border-bottom: none;\n }\n\n .emptyRow {\n display: table-row;\n }\n\n .emptyState {\n @apply px-4 py-8 text-center;\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .emptyState {\n display: table-cell;\n }\n\n .filterBar {\n @apply mb-4 rounded-xs border p-4;\n border: var(--border-width-base) solid var(--background-border);\n background-color: var(--background);\n }\n\n .filterBar {\n display: block;\n }\n\n .filterGrid {\n @apply grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3;\n background-color: var(--background);\n }\n\n .filterGrid {\n display: grid;\n }\n\n .filterField {\n @apply min-w-0;\n }\n\n .filterLabel {\n @apply mb-2 block;\n color: var(--foreground);\n font-size: var(--filter-label-font-size, var(--text-xs));\n font-weight: var(--filter-label-font-weight, var(--font-weight-medium));\n }\n\n .filterLabel {\n display: block;\n }\n\n .filterInput {\n @apply w-full;\n }\n}\n",
|
|
5148
5061
|
"cssTypes": "declare const styles: {\n root: string;\n container: string;\n table: string;\n header: string;\n body: string;\n headerRow: string;\n headerCell: string;\n row: string;\n interactive: string;\n cell: string;\n emptyRow: string;\n emptyState: string;\n filterBar: string;\n filterGrid: string;\n filterField: string;\n filterLabel: string;\n filterInput: string;\n};\n\nexport default styles;\n"
|
|
5149
5062
|
},
|
|
5150
5063
|
"tabs": {
|
|
5151
|
-
"tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { useFocusRing } from \"react-aria\"\nimport { useInteractionModality } from \"@react-aria/interactions\"\nimport { cn } from \"./utils\"\nimport { StyleValue } from \"./utils\"\nimport { asElementProps } from \"@/lib/react-aria\"\nimport { StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport css from \"./Tabs.module.css\"\n\ntype TabsVariant = \"underline\"\ntype TabsOrientation = \"horizontal\" | \"vertical\"\n\ninterface IndicatorPosition {\n left: number\n top: number\n width: number\n height: number\n}\n\ninterface ListDimensions {\n width: number\n height: number\n}\n\ninterface TabsContextValue {\n selectedValue: string\n setSelectedValue: (value: string) => void\n variant?: TabsVariant\n orientation: TabsOrientation\n isDisabledTab: (value: string) => boolean\n indicatorReady: boolean\n setIndicatorReady: (ready: boolean) => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\nconst TABS_INDICATOR_INSET = 4\nconst TABS_UNDERLINE_THICKNESS = 2\nconst TABS_UNDERLINE_OFFSET = 2\nconst TABS_UNDERLINE_GUTTER = TABS_UNDERLINE_THICKNESS + TABS_UNDERLINE_OFFSET\nconst TABS_UNDERLINE_FALLBACK_GUTTER = TABS_UNDERLINE_GUTTER + TABS_UNDERLINE_THICKNESS\n\ninterface TabsListContextValue {\n indicatorClassName: string\n}\n\nconst TabsListContext = React.createContext<TabsListContextValue | null>(null)\n\nfunction useTabsContext() {\n const context = React.useContext(TabsContext)\n if (!context) {\n throw new Error(\"Tabs component must be used within Tabs root\")\n }\n return context\n}\n\nfunction useTabsListContext() {\n return React.useContext(TabsListContext)\n}\n\nfunction getTabsIndicatorClassName(indicator: string, variant?: TabsVariant) {\n return cn(\n \"tabs\",\n \"indicator\",\n variant === \"underline\" && \"underline\",\n variant === \"underline\" && \"indicator-underline\",\n css.indicator,\n {\n [css[\"indicator-underline\"]]: variant === \"underline\",\n },\n indicator\n )\n}\n\nexport interface TabsStyleSlots {\n root?: StyleValue\n}\n\ninterface TabsProps {\n /** Optional alternate visual style of the tab list indicator */\n variant?: TabsVariant\n /** Direction of the tab list layout */\n orientation?: TabsOrientation\n /** Initially selected tab value for uncontrolled usage */\n default?: string\n /** Controlled selected tab value */\n value?: string\n /** Called when the selected tab changes */\n onValueChange?: (value: string) => void\n /** Additional CSS class for the tabs root */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsStyleSlots>\n children?: React.ReactNode\n}\n\nconst resolveTabsBaseStyles = createStylesResolver(['root'] as const)\n\nconst TabsRoot = React.forwardRef<HTMLDivElement, TabsProps>(\n (\n {\n variant,\n orientation = \"horizontal\",\n default: defaultTab,\n value: controlledValue,\n onValueChange,\n className,\n styles: stylesProp,\n children,\n },\n ref\n ) => {\n const { root } = resolveTabsBaseStyles(stylesProp)\n\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultTab || \"\")\n const [disabledTabs, setDisabledTabs] = React.useState<Set<string>>(new Set())\n\n const selectedValue = controlledValue !== undefined ? controlledValue : uncontrolledValue\n const isDisabledTab = React.useCallback(\n (value: string) => disabledTabs.has(value),\n [disabledTabs]\n )\n\n const setSelectedValue = React.useCallback(\n (newValue: string) => {\n if (!isDisabledTab(newValue)) {\n if (controlledValue === undefined) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n }\n },\n [controlledValue, isDisabledTab, onValueChange]\n )\n\n const registerDisabledTab = React.useCallback((value: string) => {\n setDisabledTabs((prev) => new Set(prev).add(value))\n }, [])\n\n const unregisterDisabledTab = React.useCallback((value: string) => {\n setDisabledTabs((prev) => {\n const newSet = new Set(prev)\n newSet.delete(value)\n return newSet\n })\n }, [])\n\n const [indicatorReady, setIndicatorReady] = React.useState(false)\n\n return (\n <TabsContext.Provider\n value={{\n selectedValue,\n setSelectedValue,\n variant,\n orientation,\n isDisabledTab,\n indicatorReady,\n setIndicatorReady,\n }}\n >\n <div\n ref={ref}\n className={cn(\"tabs\", css.tabs, root, className)}\n data-orientation={orientation}\n >\n {React.Children.map(children, (child) =>\n React.isValidElement(child) && child.type === TabsTrigger\n ? React.cloneElement(child, {\n _registerDisabled: registerDisabledTab,\n _unregisterDisabled: unregisterDisabledTab,\n } as any)\n : child\n )}\n </div>\n </TabsContext.Provider>\n )\n }\n)\nTabsRoot.displayName = \"Tabs\"\n\nexport interface TabsListStyleSlots {\n root?: StyleValue\n indicator?: StyleValue\n}\n\ninterface TabsListProps {\n /** Additional CSS class names */\n className?: string\n children?: React.ReactNode\n /** Accessible label for the tab list */\n \"aria-label\"?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsListStyleSlots>\n}\n\nconst resolveTabsListBaseStyles = createStylesResolver(['root', 'indicator'] as const);\n\n/** Container for the row of tab trigger buttons */\nconst TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n ({ className, children, \"aria-label\": ariaLabel, styles: stylesProp }, ref) => {\n const { selectedValue, variant, orientation, setIndicatorReady } = useTabsContext()\n const { root, indicator } = resolveTabsListBaseStyles(stylesProp)\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const { scopeProps: focusScopeProps, indicatorProps: focusProps } = useFocus({\n scopeRef,\n containerRef: listRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"ring\",\n dependencies: [selectedValue, orientation, variant],\n })\n const [indicatorPosition, setIndicatorPosition] = React.useState<IndicatorPosition>({\n left: 0,\n top: 0,\n width: 0,\n height: 0,\n })\n const [listDimensions, setListDimensions] = React.useState<ListDimensions>({\n width: 0,\n height: 0,\n })\n\n const indicatorClassName = React.useMemo(\n () => getTabsIndicatorClassName(indicator, variant),\n [indicator, variant]\n )\n const tabsListContext = React.useMemo(\n () => ({ indicatorClassName }),\n [indicatorClassName]\n )\n\n const measureTrigger = React.useCallback((element: HTMLElement | null) => {\n if (!element) return null\n\n const rect = element.getBoundingClientRect()\n const listRect = listRef.current?.getBoundingClientRect()\n\n if (!listRect) return null\n\n const relativeLeft = rect.left - listRect.left\n const relativeTop = rect.top - listRect.top\n\n return {\n left: relativeLeft,\n top: relativeTop,\n width: rect.width,\n height: rect.height,\n }\n }, [])\n\n const measureList = React.useCallback(() => {\n if (!listRef.current) return\n const rect = listRef.current.getBoundingClientRect()\n setListDimensions({\n width: rect.width,\n height: rect.height,\n })\n }, [])\n\n const updateIndicator = React.useCallback(\n (value: string) => {\n if (!listRef.current) return\n\n const trigger = listRef.current.querySelector(\n `[data-tabs-value=\"${value}\"]`\n ) as HTMLElement | null\n\n if (trigger) {\n const position = measureTrigger(trigger)\n if (position) {\n setIndicatorPosition(position)\n }\n }\n },\n [measureTrigger]\n )\n\n React.useLayoutEffect(() => {\n measureList()\n updateIndicator(selectedValue)\n setIndicatorReady(true)\n }, [selectedValue, updateIndicator, measureList, setIndicatorReady])\n\n React.useEffect(() => {\n if (!listRef.current) return\n\n const resizeObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => {\n measureList()\n updateIndicator(selectedValue)\n })\n })\n\n resizeObserver.observe(listRef.current)\n return () => resizeObserver.disconnect()\n }, [selectedValue, updateIndicator, measureList])\n\n React.useEffect(() => {\n const handleWindowResize = () => {\n requestAnimationFrame(() => {\n measureList()\n updateIndicator(selectedValue)\n })\n }\n\n window.addEventListener(\"resize\", handleWindowResize)\n return () => window.removeEventListener(\"resize\", handleWindowResize)\n }, [selectedValue, updateIndicator, measureList])\n\n const getIndicatorStyle = React.useMemo<React.CSSProperties>(() => {\n const baseStyle: React.CSSProperties = {\n position: \"absolute\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n willChange: \"transform\",\n pointerEvents: \"none\",\n margin: 0,\n opacity: indicatorPosition.width === 0 && indicatorPosition.height === 0 ? 0 : 1,\n }\n\n if (indicatorPosition.width === 0 && indicatorPosition.height === 0) {\n return baseStyle\n }\n\n if (orientation === \"vertical\") {\n if (variant === \"underline\") {\n return {\n ...baseStyle,\n left: indicatorPosition.left - TABS_UNDERLINE_GUTTER,\n top: indicatorPosition.top,\n width: TABS_UNDERLINE_THICKNESS,\n height: indicatorPosition.height,\n }\n }\n const horizontalPadding = TABS_INDICATOR_INSET\n const adjustedWidth = Math.max(0, listDimensions.width - horizontalPadding * 2)\n return {\n ...baseStyle,\n left: horizontalPadding,\n top: indicatorPosition.top,\n width: adjustedWidth,\n height: indicatorPosition.height,\n }\n }\n\n if (variant === \"underline\") {\n return {\n ...baseStyle,\n left: indicatorPosition.left,\n top: indicatorPosition.top + indicatorPosition.height + TABS_UNDERLINE_OFFSET,\n width: indicatorPosition.width,\n height: TABS_UNDERLINE_THICKNESS,\n }\n }\n\n return {\n ...baseStyle,\n left: indicatorPosition.left,\n top: indicatorPosition.top,\n width: indicatorPosition.width,\n height: indicatorPosition.height,\n }\n }, [indicatorPosition, listDimensions, variant, orientation])\n\n const mergedRef = useMergeRefs(listRef, ref)\n\n return (\n <TabsListContext.Provider value={tabsListContext}>\n <div ref={scopeRef} className={cn(\"tabs-scope\", focusScopeProps.className)}>\n <div {...focusProps} />\n <div\n ref={mergedRef}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation={orientation}\n className={cn(\"tabs\", \"list\", css.list, root, className)}\n data-variant={variant}\n data-orientation={orientation}\n style={{ position: \"relative\" }}\n >\n {children}\n {indicatorPosition.width > 0 && (\n <div\n aria-hidden=\"true\"\n className={indicatorClassName}\n style={getIndicatorStyle}\n />\n )}\n </div>\n </div>\n </TabsListContext.Provider>\n )\n }\n)\nTabsList.displayName = \"TabsList\"\n\ninterface TabsTriggerIconStyles {\n left?: StyleValue\n right?: StyleValue\n}\n\ninterface TabsTriggerIconSlots {\n left?: React.ReactNode\n right?: React.ReactNode\n}\n\nexport interface TabsTriggerStyleSlots {\n root?: StyleValue\n icon?: StyleValue | TabsTriggerIconStyles\n}\n\ninterface TabsTriggerProps {\n /** Unique identifier matching the associated TabsContent value */\n value: string\n /** Whether the tab trigger is disabled */\n disabled?: boolean\n /** Icon element(s) rendered inside the trigger. Pass a node for left-only, or { left, right } for both sides. */\n icon?: React.ReactNode | TabsTriggerIconSlots\n /** Additional CSS class names */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsTriggerStyleSlots>\n children?: React.ReactNode\n _registerDisabled?: (value: string) => void\n _unregisterDisabled?: (value: string) => void\n}\n\nconst resolveTabsTriggerBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight'] as const);\n\nfunction isTabsTriggerIconSlots(icon: TabsTriggerProps[\"icon\"]): icon is TabsTriggerIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && ('left' in icon || 'right' in icon)\n}\n\nfunction resolveTabsTriggerIcon(icon: TabsTriggerProps[\"icon\"]): TabsTriggerIconSlots | undefined {\n if (!icon) return undefined\n if (isTabsTriggerIconSlots(icon)) return icon\n return { left: icon }\n}\n\nfunction resolveTabsTriggerStyles(styles: StylesProp<TabsTriggerStyleSlots> | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveTabsTriggerBaseStyles(styles)\n const { root, icon } = styles\n\n let iconLeft: StyleValue | undefined\n let iconRight: StyleValue | undefined\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon\n iconRight = icon\n } else {\n iconLeft = icon.left\n iconRight = icon.right\n }\n }\n\n return resolveTabsTriggerBaseStyles({ root, iconLeft, iconRight })\n}\n\n/** A tab button that activates its associated content panel */\nconst TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n (\n {\n value,\n disabled = false,\n icon,\n className,\n styles: stylesProp,\n children,\n _registerDisabled,\n _unregisterDisabled,\n },\n ref\n ) => {\n const { selectedValue, setSelectedValue, indicatorReady, orientation, variant } = useTabsContext()\n const tabsListContext = useTabsListContext()\n const resolved = resolveTabsTriggerStyles(stylesProp)\n const resolvedIcon = resolveTabsTriggerIcon(icon)\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const isSelected = value === selectedValue\n const showIndicatorFallback = isSelected && !indicatorReady && !!tabsListContext\n const fallbackIndicatorStyle = React.useMemo<React.CSSProperties>(() => {\n if (variant === \"underline\") {\n if (orientation === \"vertical\") {\n return {\n top: 0,\n bottom: 0,\n left: -TABS_UNDERLINE_FALLBACK_GUTTER,\n width: TABS_UNDERLINE_THICKNESS,\n height: \"100%\",\n margin: 0,\n }\n }\n\n return {\n left: 0,\n right: 0,\n bottom: -TABS_UNDERLINE_FALLBACK_GUTTER,\n width: \"100%\",\n height: TABS_UNDERLINE_THICKNESS,\n margin: 0,\n }\n }\n\n return {\n inset: 0,\n margin: 0,\n }\n }, [orientation, variant])\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing()\n const interactionModality = useInteractionModality()\n const showFocusVisible = isFocused && interactionModality !== \"pointer\" && isFocusVisible\n\n React.useEffect(() => {\n if (disabled) {\n _registerDisabled?.(value)\n } else {\n _unregisterDisabled?.(value)\n }\n }, [disabled, value, _registerDisabled, _unregisterDisabled])\n\n const handleClick = React.useCallback(() => {\n if (!disabled) {\n setSelectedValue(value)\n }\n }, [disabled, value, setSelectedValue])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return\n\n const listElement = buttonRef.current?.parentElement\n if (!listElement) return\n\n const triggers = Array.from(\n listElement.querySelectorAll('[data-tabs-value]')\n ) as HTMLButtonElement[]\n const currentIndex = triggers.findIndex((el) => el.getAttribute(\"data-tabs-value\") === value)\n\n let nextValue: string | null = null\n\n if (e.key === \"Tab\") {\n const nextIndex = e.shiftKey ? currentIndex - 1 : currentIndex + 1\n const nextTrigger = triggers[nextIndex]\n\n if (nextTrigger) {\n e.preventDefault()\n nextTrigger.focus()\n }\n return\n }\n\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % triggers.length\n nextValue = triggers[nextIndex].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault()\n const prevIndex = currentIndex === 0 ? triggers.length - 1 : currentIndex - 1\n nextValue = triggers[prevIndex].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"Home\") {\n e.preventDefault()\n nextValue = triggers[0].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"End\") {\n e.preventDefault()\n nextValue = triggers[triggers.length - 1].getAttribute(\"data-tabs-value\")\n }\n\n if (nextValue) {\n setSelectedValue(nextValue)\n setTimeout(() => {\n const nextTrigger = listElement.querySelector(\n `[data-tabs-value=\"${nextValue}\"]`\n ) as HTMLButtonElement | null\n nextTrigger?.focus()\n }, 0)\n }\n },\n [value, disabled, setSelectedValue]\n )\n\n const mergedRef = useMergeRefs(buttonRef, ref)\n\n return (\n <button\n {...asElementProps<\"button\">(focusProps)}\n ref={mergedRef}\n id={`${value}-trigger`}\n role=\"tab\"\n aria-selected={isSelected}\n aria-controls={`${value}-content`}\n tabIndex={isSelected ? 0 : -1}\n disabled={disabled}\n data-tabs-value={value}\n data-focus-surface=\"true\"\n className={cn(\"tabs\", \"trigger\", css.trigger, resolved.root, className)}\n data-selected={isSelected ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-focus-visible={showFocusVisible ? \"true\" : \"false\"}\n data-indicator-ready={isSelected && indicatorReady ? \"true\" : undefined}\n data-indicator-fallback={showIndicatorFallback ? \"true\" : undefined}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n >\n {showIndicatorFallback && tabsListContext && (\n <span\n aria-hidden=\"true\"\n className={cn(tabsListContext.indicatorClassName, css[\"indicator-fallback\"])}\n style={fallbackIndicatorStyle}\n />\n )}\n {resolvedIcon?.left && <span className={cn(css.icon, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(css.icon, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </button>\n )\n }\n)\nTabsTrigger.displayName = \"Tab\"\n\nexport interface TabsContentStyleSlots {\n root?: StyleValue\n}\n\ninterface TabsContentProps {\n /** Unique identifier matching the associated TabsTrigger value */\n value: string\n /** Additional CSS class names */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsContentStyleSlots>\n children?: React.ReactNode\n}\n\nconst resolveTabsContentBaseStyles = createStylesResolver(['root'] as const);\n\n/** Content panel shown when its corresponding tab is active */\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n ({ value, className, children, styles: stylesProp }, ref) => {\n const { selectedValue, orientation } = useTabsContext()\n const { root } = resolveTabsContentBaseStyles(stylesProp);\n const isVisible = value === selectedValue\n\n return (\n <div\n ref={ref}\n role=\"tabpanel\"\n aria-labelledby={`${value}-trigger`}\n id={`${value}-content`}\n className={cn(\"tabs\", \"content\", css.content, root, className)}\n data-orientation={orientation}\n hidden={!isVisible}\n >\n {isVisible && children}\n </div>\n )\n }\n)\nTabsContent.displayName = \"TabsContent\"\n\nconst Tabs = Object.assign(TabsRoot, {\n List: TabsList,\n Trigger: TabsTrigger,\n Content: TabsContent,\n})\n\nexport { Tabs }\nexport type { TabsProps, TabsListProps, TabsTriggerProps, TabsContentProps }\n",
|
|
5152
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .tabs {\n @apply flex w-full flex-col;\n\n &[data-orientation=\"vertical\"] {\n flex-direction: row;\n }\n }\n\n .list {\n @apply relative flex w-full flex-row items-center gap-3 py-1;\n border-radius: var(--radius-sm);\n\n &[data-orientation=\"vertical\"] {\n flex-direction: column;\n width: fit-content;\n min-width: 0;\n height: auto;\n align-self: flex-start;\n }\n\n &[data-variant=\"underline\"] {\n background-color: transparent;\n border-radius: 0;\n padding: 0 0 4px;\n }\n\n &[data-variant=\"underline\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-left: var(--border-width-base) solid var(--border);\n align-items: stretch;\n padding: 0 0 0 4px;\n }\n }\n\n .indicator {\n @apply absolute;\n background-color: var(--background);\n box-sizing: border-box;\n border-radius: var(--radius-sm);\n z-index: 0;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: none;\n }\n\n .indicator-fallback {\n z-index: -1;\n }\n\n .indicator-underline {\n border-radius: 0;\n }\n\n .trigger {\n @apply relative z-[1] flex shrink-0 items-center justify-center gap-2 px-2 py-1.5 cursor-pointer select-none;\n height: auto;\n background-color: var(--background);\n border: none;\n color: var(--foreground);\n outline: none;\n box-shadow: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n\n
|
|
5064
|
+
"tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { mergeProps, useFocusRing, usePress } from \"react-aria\"\nimport { useHover, useInteractionModality } from \"@react-aria/interactions\"\nimport { cn } from \"./utils\"\nimport { StyleValue } from \"./utils\"\nimport { asElementProps } from \"@/lib/react-aria\"\nimport { StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport css from \"./Tabs.module.css\"\n\ntype TabsVariant = \"underline\"\ntype TabsOrientation = \"horizontal\" | \"vertical\"\n\ninterface IndicatorPosition {\n left: number\n top: number\n width: number\n height: number\n}\n\ninterface ListDimensions {\n width: number\n height: number\n}\n\ninterface TabsContextValue {\n selectedValue: string\n setSelectedValue: (value: string) => void\n variant?: TabsVariant\n orientation: TabsOrientation\n isDisabledTab: (value: string) => boolean\n indicatorReady: boolean\n setIndicatorReady: (ready: boolean) => void\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null)\nconst TABS_INDICATOR_INSET = 4\nconst TABS_UNDERLINE_THICKNESS = 2\nconst TABS_UNDERLINE_OFFSET = 2\nconst TABS_UNDERLINE_GUTTER = TABS_UNDERLINE_THICKNESS + TABS_UNDERLINE_OFFSET\nconst TABS_UNDERLINE_FALLBACK_GUTTER = TABS_UNDERLINE_GUTTER\n\ninterface TabsListContextValue {\n indicatorClassName: string\n}\n\nconst TabsListContext = React.createContext<TabsListContextValue | null>(null)\n\nfunction useTabsContext() {\n const context = React.useContext(TabsContext)\n if (!context) {\n throw new Error(\"Tabs component must be used within Tabs root\")\n }\n return context\n}\n\nfunction useTabsListContext() {\n return React.useContext(TabsListContext)\n}\n\nfunction getTabsIndicatorClassName(indicator: string, variant?: TabsVariant) {\n return cn(\n \"tabs\",\n \"indicator\",\n variant === \"underline\" && \"underline\",\n variant === \"underline\" && \"indicator-underline\",\n css.indicator,\n {\n [css[\"indicator-underline\"]]: variant === \"underline\",\n },\n indicator\n )\n}\n\nexport interface TabsStyleSlots {\n root?: StyleValue\n}\n\ninterface TabsProps {\n /** Optional alternate visual style of the tab list indicator */\n variant?: TabsVariant\n /** Direction of the tab list layout */\n orientation?: TabsOrientation\n /** Initially selected tab value for uncontrolled usage */\n default?: string\n /** Controlled selected tab value */\n value?: string\n /** Called when the selected tab changes */\n onValueChange?: (value: string) => void\n /** Additional CSS class for the tabs root */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsStyleSlots>\n children?: React.ReactNode\n}\n\nconst resolveTabsBaseStyles = createStylesResolver(['root'] as const)\n\nconst TabsRoot = React.forwardRef<HTMLDivElement, TabsProps>(\n (\n {\n variant,\n orientation = \"horizontal\",\n default: defaultTab,\n value: controlledValue,\n onValueChange,\n className,\n styles: stylesProp,\n children,\n },\n ref\n ) => {\n const { root } = resolveTabsBaseStyles(stylesProp)\n\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultTab || \"\")\n const [disabledTabs, setDisabledTabs] = React.useState<Set<string>>(new Set())\n\n const selectedValue = controlledValue !== undefined ? controlledValue : uncontrolledValue\n const isDisabledTab = React.useCallback(\n (value: string) => disabledTabs.has(value),\n [disabledTabs]\n )\n\n const setSelectedValue = React.useCallback(\n (newValue: string) => {\n if (!isDisabledTab(newValue)) {\n if (controlledValue === undefined) {\n setUncontrolledValue(newValue)\n }\n onValueChange?.(newValue)\n }\n },\n [controlledValue, isDisabledTab, onValueChange]\n )\n\n const registerDisabledTab = React.useCallback((value: string) => {\n setDisabledTabs((prev) => new Set(prev).add(value))\n }, [])\n\n const unregisterDisabledTab = React.useCallback((value: string) => {\n setDisabledTabs((prev) => {\n const newSet = new Set(prev)\n newSet.delete(value)\n return newSet\n })\n }, [])\n\n const [indicatorReady, setIndicatorReady] = React.useState(false)\n\n return (\n <TabsContext.Provider\n value={{\n selectedValue,\n setSelectedValue,\n variant,\n orientation,\n isDisabledTab,\n indicatorReady,\n setIndicatorReady,\n }}\n >\n <div\n ref={ref}\n className={cn(\"tabs\", css.tabs, root, className)}\n data-orientation={orientation}\n >\n {React.Children.map(children, (child) =>\n React.isValidElement(child) && child.type === TabsTrigger\n ? React.cloneElement(child, {\n _registerDisabled: registerDisabledTab,\n _unregisterDisabled: unregisterDisabledTab,\n } as any)\n : child\n )}\n </div>\n </TabsContext.Provider>\n )\n }\n)\nTabsRoot.displayName = \"Tabs\"\n\nexport interface TabsListStyleSlots {\n root?: StyleValue\n indicator?: StyleValue\n}\n\ninterface TabsListProps {\n /** Additional CSS class names */\n className?: string\n children?: React.ReactNode\n /** Accessible label for the tab list */\n \"aria-label\"?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsListStyleSlots>\n}\n\nconst resolveTabsListBaseStyles = createStylesResolver(['root', 'indicator'] as const);\n\n/** Container for the row of tab trigger buttons */\nconst TabsList = React.forwardRef<HTMLDivElement, TabsListProps>(\n ({ className, children, \"aria-label\": ariaLabel, styles: stylesProp }, ref) => {\n const { selectedValue, variant, orientation, setIndicatorReady } = useTabsContext()\n const { root, indicator } = resolveTabsListBaseStyles(stylesProp)\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const listRef = React.useRef<HTMLDivElement>(null)\n const { scopeProps: focusScopeProps, indicatorProps: focusProps } = useFocus({\n scopeRef,\n containerRef: listRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"ring\",\n dependencies: [selectedValue, orientation, variant],\n })\n const [indicatorPosition, setIndicatorPosition] = React.useState<IndicatorPosition>({\n left: 0,\n top: 0,\n width: 0,\n height: 0,\n })\n const [listDimensions, setListDimensions] = React.useState<ListDimensions>({\n width: 0,\n height: 0,\n })\n\n const indicatorClassName = React.useMemo(\n () => getTabsIndicatorClassName(indicator, variant),\n [indicator, variant]\n )\n const tabsListContext = React.useMemo(\n () => ({ indicatorClassName }),\n [indicatorClassName]\n )\n\n const measureTrigger = React.useCallback((element: HTMLElement | null) => {\n if (!element) return null\n\n const rect = element.getBoundingClientRect()\n const listRect = listRef.current?.getBoundingClientRect()\n\n if (!listRect) return null\n\n const relativeLeft = rect.left - listRect.left\n const relativeTop = rect.top - listRect.top\n\n return {\n left: relativeLeft,\n top: relativeTop,\n width: rect.width,\n height: rect.height,\n }\n }, [])\n\n const measureList = React.useCallback(() => {\n if (!listRef.current) return\n const rect = listRef.current.getBoundingClientRect()\n setListDimensions({\n width: rect.width,\n height: rect.height,\n })\n }, [])\n\n const updateIndicator = React.useCallback(\n (value: string) => {\n if (!listRef.current) return\n\n const trigger = listRef.current.querySelector(\n `[data-tabs-value=\"${value}\"]`\n ) as HTMLElement | null\n\n if (trigger) {\n const position = measureTrigger(trigger)\n if (position) {\n setIndicatorPosition(position)\n }\n }\n },\n [measureTrigger]\n )\n\n React.useLayoutEffect(() => {\n measureList()\n updateIndicator(selectedValue)\n setIndicatorReady(true)\n }, [selectedValue, updateIndicator, measureList, setIndicatorReady])\n\n React.useEffect(() => {\n if (!listRef.current) return\n\n const resizeObserver = new ResizeObserver(() => {\n requestAnimationFrame(() => {\n measureList()\n updateIndicator(selectedValue)\n })\n })\n\n resizeObserver.observe(listRef.current)\n return () => resizeObserver.disconnect()\n }, [selectedValue, updateIndicator, measureList])\n\n React.useEffect(() => {\n const handleWindowResize = () => {\n requestAnimationFrame(() => {\n measureList()\n updateIndicator(selectedValue)\n })\n }\n\n window.addEventListener(\"resize\", handleWindowResize)\n return () => window.removeEventListener(\"resize\", handleWindowResize)\n }, [selectedValue, updateIndicator, measureList])\n\n const getIndicatorStyle = React.useMemo<React.CSSProperties>(() => {\n const baseStyle: React.CSSProperties = {\n position: \"absolute\",\n transition: \"all 0.2s cubic-bezier(0.4, 0, 0.2, 1)\",\n willChange: \"transform\",\n pointerEvents: \"none\",\n margin: 0,\n opacity: indicatorPosition.width === 0 && indicatorPosition.height === 0 ? 0 : 1,\n }\n\n if (indicatorPosition.width === 0 && indicatorPosition.height === 0) {\n return baseStyle\n }\n\n if (orientation === \"vertical\") {\n if (variant === \"underline\") {\n return {\n ...baseStyle,\n left: indicatorPosition.left - TABS_UNDERLINE_GUTTER,\n top: indicatorPosition.top,\n width: TABS_UNDERLINE_THICKNESS,\n height: indicatorPosition.height,\n }\n }\n const horizontalPadding = TABS_INDICATOR_INSET\n const adjustedWidth = Math.max(0, listDimensions.width - horizontalPadding * 2)\n return {\n ...baseStyle,\n left: horizontalPadding,\n top: indicatorPosition.top,\n width: adjustedWidth,\n height: indicatorPosition.height,\n }\n }\n\n if (variant === \"underline\") {\n return {\n ...baseStyle,\n left: indicatorPosition.left,\n top: indicatorPosition.top + indicatorPosition.height + TABS_UNDERLINE_OFFSET,\n width: indicatorPosition.width,\n height: TABS_UNDERLINE_THICKNESS,\n }\n }\n\n return {\n ...baseStyle,\n left: indicatorPosition.left,\n top: indicatorPosition.top,\n width: indicatorPosition.width,\n height: indicatorPosition.height,\n }\n }, [indicatorPosition, listDimensions, variant, orientation])\n\n const mergedRef = useMergeRefs(listRef, ref)\n\n return (\n <TabsListContext.Provider value={tabsListContext}>\n <div ref={scopeRef} className={cn(\"tabs-scope\", focusScopeProps.className)}>\n <div {...focusProps} />\n <div\n ref={mergedRef}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation={orientation}\n className={cn(\"tabs\", \"list\", css.list, root, className)}\n data-variant={variant}\n data-orientation={orientation}\n style={{ position: \"relative\" }}\n >\n {children}\n {indicatorPosition.width > 0 && (\n <div\n aria-hidden=\"true\"\n className={indicatorClassName}\n style={getIndicatorStyle}\n />\n )}\n </div>\n </div>\n </TabsListContext.Provider>\n )\n }\n)\nTabsList.displayName = \"TabsList\"\n\ninterface TabsTriggerIconStyles {\n left?: StyleValue\n right?: StyleValue\n}\n\ninterface TabsTriggerIconSlots {\n left?: React.ReactNode\n right?: React.ReactNode\n}\n\nexport interface TabsTriggerStyleSlots {\n root?: StyleValue\n icon?: StyleValue | TabsTriggerIconStyles\n}\n\ninterface TabsTriggerProps {\n /** Unique identifier matching the associated TabsContent value */\n value: string\n /** Whether the tab trigger is disabled */\n disabled?: boolean\n /** Icon element(s) rendered inside the trigger. Pass a node for left-only, or { left, right } for both sides. */\n icon?: React.ReactNode | TabsTriggerIconSlots\n /** Additional CSS class names */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsTriggerStyleSlots>\n children?: React.ReactNode\n _registerDisabled?: (value: string) => void\n _unregisterDisabled?: (value: string) => void\n}\n\nconst resolveTabsTriggerBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight'] as const);\n\nfunction isTabsTriggerIconSlots(icon: TabsTriggerProps[\"icon\"]): icon is TabsTriggerIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && ('left' in icon || 'right' in icon)\n}\n\nfunction resolveTabsTriggerIcon(icon: TabsTriggerProps[\"icon\"]): TabsTriggerIconSlots | undefined {\n if (!icon) return undefined\n if (isTabsTriggerIconSlots(icon)) return icon\n return { left: icon }\n}\n\nfunction resolveTabsTriggerStyles(styles: StylesProp<TabsTriggerStyleSlots> | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveTabsTriggerBaseStyles(styles)\n const { root, icon } = styles\n\n let iconLeft: StyleValue | undefined\n let iconRight: StyleValue | undefined\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon\n iconRight = icon\n } else {\n iconLeft = icon.left\n iconRight = icon.right\n }\n }\n\n return resolveTabsTriggerBaseStyles({ root, iconLeft, iconRight })\n}\n\n/** A tab button that activates its associated content panel */\nconst TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(\n (\n {\n value,\n disabled = false,\n icon,\n className,\n styles: stylesProp,\n children,\n _registerDisabled,\n _unregisterDisabled,\n },\n ref\n ) => {\n const { selectedValue, setSelectedValue, indicatorReady, orientation, variant } = useTabsContext()\n const tabsListContext = useTabsListContext()\n const resolved = resolveTabsTriggerStyles(stylesProp)\n const resolvedIcon = resolveTabsTriggerIcon(icon)\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const isSelected = value === selectedValue\n const showIndicatorFallback = isSelected && !indicatorReady && !!tabsListContext\n const fallbackIndicatorStyle = React.useMemo<React.CSSProperties>(() => {\n if (variant === \"underline\") {\n if (orientation === \"vertical\") {\n return {\n top: 0,\n bottom: 0,\n left: -TABS_UNDERLINE_FALLBACK_GUTTER,\n width: TABS_UNDERLINE_THICKNESS,\n height: \"100%\",\n margin: 0,\n }\n }\n\n return {\n left: 0,\n right: 0,\n bottom: -TABS_UNDERLINE_FALLBACK_GUTTER,\n width: \"100%\",\n height: TABS_UNDERLINE_THICKNESS,\n margin: 0,\n }\n }\n\n return {\n inset: 0,\n margin: 0,\n }\n }, [orientation, variant])\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing()\n const interactionModality = useInteractionModality()\n const showFocusVisible = isFocused && interactionModality !== \"pointer\" && isFocusVisible\n\n React.useEffect(() => {\n if (disabled) {\n _registerDisabled?.(value)\n } else {\n _unregisterDisabled?.(value)\n }\n }, [disabled, value, _registerDisabled, _unregisterDisabled])\n\n const handlePress = React.useCallback(() => {\n if (!disabled) {\n setSelectedValue(value)\n }\n }, [disabled, value, setSelectedValue])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return\n\n const listElement = buttonRef.current?.parentElement\n if (!listElement) return\n\n const triggers = Array.from(\n listElement.querySelectorAll('[data-tabs-value]')\n ) as HTMLButtonElement[]\n const currentIndex = triggers.findIndex((el) => el.getAttribute(\"data-tabs-value\") === value)\n\n let nextValue: string | null = null\n\n if (e.key === \"Tab\") {\n const nextIndex = e.shiftKey ? currentIndex - 1 : currentIndex + 1\n const nextTrigger = triggers[nextIndex]\n\n if (nextTrigger) {\n e.preventDefault()\n nextTrigger.focus()\n }\n return\n }\n\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % triggers.length\n nextValue = triggers[nextIndex].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault()\n const prevIndex = currentIndex === 0 ? triggers.length - 1 : currentIndex - 1\n nextValue = triggers[prevIndex].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"Home\") {\n e.preventDefault()\n nextValue = triggers[0].getAttribute(\"data-tabs-value\")\n } else if (e.key === \"End\") {\n e.preventDefault()\n nextValue = triggers[triggers.length - 1].getAttribute(\"data-tabs-value\")\n }\n\n if (nextValue) {\n setSelectedValue(nextValue)\n setTimeout(() => {\n const nextTrigger = listElement.querySelector(\n `[data-tabs-value=\"${nextValue}\"]`\n ) as HTMLButtonElement | null\n nextTrigger?.focus()\n }, 0)\n }\n },\n [value, disabled, setSelectedValue]\n )\n\n const mergedRef = useMergeRefs(buttonRef, ref)\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled })\n const { pressProps, isPressed } = usePress({\n isDisabled: disabled,\n onPress: handlePress,\n })\n const triggerProps = mergeProps(\n asElementProps<\"button\">(focusProps),\n hoverProps,\n pressProps,\n { onKeyDown: handleKeyDown }\n )\n\n return (\n <button\n {...triggerProps}\n ref={mergedRef}\n id={`${value}-trigger`}\n role=\"tab\"\n aria-selected={isSelected}\n aria-controls={`${value}-content`}\n tabIndex={isSelected ? 0 : -1}\n disabled={disabled}\n data-tabs-value={value}\n data-focus-surface=\"true\"\n className={cn(\"tabs\", \"trigger\", css.trigger, resolved.root, className)}\n data-selected={isSelected ? \"true\" : \"false\"}\n data-disabled={disabled ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-focus-visible={showFocusVisible ? \"true\" : \"false\"}\n data-indicator-ready={isSelected && indicatorReady ? \"true\" : undefined}\n data-indicator-fallback={showIndicatorFallback ? \"true\" : undefined}\n >\n {showIndicatorFallback && tabsListContext && (\n <span\n aria-hidden=\"true\"\n className={cn(tabsListContext.indicatorClassName, css[\"indicator-fallback\"])}\n style={fallbackIndicatorStyle}\n />\n )}\n {resolvedIcon?.left && <span className={cn(css.icon, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(css.icon, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </button>\n )\n }\n)\nTabsTrigger.displayName = \"Tab\"\n\nexport interface TabsContentStyleSlots {\n root?: StyleValue\n}\n\ninterface TabsContentProps {\n /** Unique identifier matching the associated TabsTrigger value */\n value: string\n /** Additional CSS class names */\n className?: string\n /** Custom styles for the component slots */\n styles?: StylesProp<TabsContentStyleSlots>\n children?: React.ReactNode\n}\n\nconst resolveTabsContentBaseStyles = createStylesResolver(['root'] as const);\n\n/** Content panel shown when its corresponding tab is active */\nconst TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(\n ({ value, className, children, styles: stylesProp }, ref) => {\n const { selectedValue, orientation } = useTabsContext()\n const { root } = resolveTabsContentBaseStyles(stylesProp);\n const isVisible = value === selectedValue\n\n return (\n <div\n ref={ref}\n role=\"tabpanel\"\n aria-labelledby={`${value}-trigger`}\n id={`${value}-content`}\n className={cn(\"tabs\", \"content\", css.content, root, className)}\n data-orientation={orientation}\n hidden={!isVisible}\n >\n {isVisible && children}\n </div>\n )\n }\n)\nTabsContent.displayName = \"TabsContent\"\n\nconst Tabs = Object.assign(TabsRoot, {\n List: TabsList,\n Trigger: TabsTrigger,\n Content: TabsContent,\n})\n\nexport { Tabs }\nexport type { TabsProps, TabsListProps, TabsTriggerProps, TabsContentProps }\n",
|
|
5065
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .tabs {\n @apply flex w-full flex-col;\n\n &[data-orientation=\"vertical\"] {\n flex-direction: row;\n }\n }\n\n .list {\n @apply relative flex w-full flex-row items-center gap-3 py-1;\n border-radius: var(--radius-sm);\n\n &[data-orientation=\"vertical\"] {\n flex-direction: column;\n width: fit-content;\n min-width: 0;\n height: auto;\n align-self: flex-start;\n }\n\n &[data-variant=\"underline\"] {\n background-color: transparent;\n border-radius: 0;\n padding: 0 0 4px;\n }\n\n &[data-variant=\"underline\"][data-orientation=\"vertical\"] {\n border-bottom: none;\n border-left: var(--border-width-base) solid var(--border);\n align-items: stretch;\n padding: 0 0 0 4px;\n }\n }\n\n .indicator {\n @apply absolute;\n background-color: var(--background);\n box-sizing: border-box;\n border-radius: var(--radius-sm);\n z-index: 0;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n pointer-events: none;\n }\n\n .indicator-fallback {\n z-index: -1;\n }\n\n .indicator-underline {\n border-radius: 0;\n }\n\n .trigger {\n @apply relative z-[1] flex shrink-0 items-center justify-center gap-2 px-2 py-1.5 cursor-pointer select-none;\n height: auto;\n background-color: var(--background);\n border: none;\n color: var(--foreground);\n outline: none;\n box-shadow: none;\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-selected=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-selected=\"true\"] {\n cursor: pointer;\n }\n\n &[data-selected=\"true\"]:not([data-indicator-ready=\"true\"]):not([data-indicator-fallback=\"true\"]) {\n .list[data-variant=\"underline\"] & {\n border-bottom-color: var(--underline-border);\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] & {\n border-bottom-color: transparent;\n border-left-color: var(--underline-border);\n }\n }\n\n &:focus,\n &:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n }\n\n &[data-disabled=\"true\"] {\n --disabled-opacity: 0.5;\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .list[data-variant=\"underline\"] & {\n background-color: var(--background);\n background-clip: padding-box;\n border-radius: var(--radius-sm);\n border-bottom: 2px solid transparent;\n }\n\n .list[data-variant=\"underline\"] &:focus,\n .list[data-variant=\"underline\"] &:focus-visible {\n outline: none !important;\n box-shadow: none !important;\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] & {\n border-bottom: none;\n border-left: 2px solid transparent;\n }\n\n .list[data-variant=\"underline\"][data-orientation=\"vertical\"] &[data-selected=\"true\"]:not([data-indicator-ready=\"true\"]):not([data-indicator-fallback=\"true\"]) {\n border-left-color: var(--underline-border);\n border-bottom: none;\n }\n }\n\n .icon {\n @apply flex h-4 w-4 shrink-0 items-center justify-center;\n }\n\n .content {\n @apply w-full p-0 outline-none;\n flex: 1;\n padding-top: 1rem;\n\n &[data-orientation=\"vertical\"] {\n flex: 1;\n width: 100%;\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n }\n\n @media (max-width: 640px) {\n .list {\n padding: 0.125rem;\n\n &[data-variant=\"underline\"] {\n padding: 0 0 4px;\n }\n }\n\n .trigger {\n @apply px-1 py-1;\n .list[data-variant=\"underline\"] & {\n margin: 0.5rem 0.75rem;\n }\n }\n }\n}\n",
|
|
5153
5066
|
"cssTypes": "declare const styles: {\n tabs: string;\n list: string;\n indicator: string;\n \"indicator-fallback\": string;\n \"indicator-underline\": string;\n trigger: string;\n icon: string;\n content: string;\n};\n\nexport default styles;\n"
|
|
5154
5067
|
},
|
|
5155
5068
|
"textarea": {
|
|
5156
|
-
"tsx": "\"use client\";\n\nimport React, { forwardRef, useState, type ComponentPropsWithoutRef } from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { mergeProps } from \"@react-aria/utils\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Scroll } from \"@/components/Scroll\";\nimport css from \"./Textarea.module.css\";\n\ntype TextareaSize = \"sm\" | \"md\" | \"lg\";\ntype ResizeAxis = \"both\" | \"x\" | \"y\" | \"none\";\n\nexport interface TextareaResizeHandleStyles {\n both?: StyleValue;\n x?: StyleValue;\n y?: StyleValue;\n}\n\nexport interface TextareaStyleSlots {\n root?: StyleValue;\n container?: StyleValue;\n surface?: StyleValue;\n scrollWrapper?: StyleValue;\n resizeHandle?: StyleValue | TextareaResizeHandleStyles;\n characterCount?: StyleValue;\n}\n\nexport type TextareaStylesProp = StylesProp<TextareaStyleSlots>;\nexport type TextAreaStyleSlots = TextareaStyleSlots;\nexport type TextAreaStylesProp = TextareaStylesProp;\n\nconst resolveTextareaBaseStyles = createStylesResolver([\n \"root\",\n \"container\",\n \"surface\",\n \"scrollWrapper\",\n \"resizeHandleBoth\",\n \"resizeHandleX\",\n \"resizeHandleY\",\n \"characterCount\",\n] as const);\n\nfunction resolveTextareaStyles(styles: TextareaStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveTextareaBaseStyles(styles);\n }\n\n const { root, container, surface, scrollWrapper, resizeHandle, characterCount } = styles;\n\n let resizeHandleBoth: StyleValue | undefined;\n let resizeHandleX: StyleValue | undefined;\n let resizeHandleY: StyleValue | undefined;\n\n if (resizeHandle) {\n if (typeof resizeHandle === \"string\" || Array.isArray(resizeHandle)) {\n resizeHandleBoth = resizeHandle;\n resizeHandleX = resizeHandle;\n resizeHandleY = resizeHandle;\n } else {\n resizeHandleBoth = resizeHandle.both;\n resizeHandleX = resizeHandle.x;\n resizeHandleY = resizeHandle.y;\n }\n }\n\n return resolveTextareaBaseStyles({\n root,\n container,\n surface,\n scrollWrapper,\n resizeHandleBoth,\n resizeHandleX,\n resizeHandleY,\n characterCount,\n });\n}\n\nexport interface TextareaProps extends Omit<ComponentPropsWithoutRef<\"textarea\">, \"size\"> {\n /** Size of the textarea. */\n size?: TextareaSize;\n /** Whether to apply error styling. */\n error?: boolean;\n /** Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis. */\n resizable?: boolean;\n /** Whether to display a character count below the textarea. */\n showCharacterCount?: boolean;\n /** Maximum number of characters allowed. */\n maxCharacters?: number;\n /** Maximum height before the custom scrollbar activates. */\n maxHeight?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: TextareaStylesProp;\n}\n\nexport type TextAreaProps = TextareaProps;\n\nconst resizeClassMap: Record<string, ResizeAxis> = {\n resize: \"both\",\n \"resize-x\": \"x\",\n \"resize-y\": \"y\",\n \"resize-none\": \"none\",\n};\n\nconst sizeMap: Record<TextareaSize, string> = {\n sm: css[\"size-sm\"],\n md: css[\"size-md\"],\n lg: css[\"size-lg\"],\n};\n\nconst resizeHandleClassMap: Record<Exclude<ResizeAxis, \"none\">, string> = {\n both: css[\"resize-handle-both\"],\n x: css[\"resize-handle-x\"],\n y: css[\"resize-handle-y\"],\n};\n\nfunction resolveResizeAxis(className: string | undefined, resizable: boolean): ResizeAxis {\n if (!resizable) return \"none\";\n\n let axis: ResizeAxis | undefined;\n for (const token of className?.split(/\\s+/) ?? []) {\n const nextAxis = resizeClassMap[token];\n if (nextAxis) axis = nextAxis;\n }\n\n return axis ?? \"both\";\n}\n\nfunction stripResizeClasses(className: string | undefined) {\n if (!className) return className;\n\n const filtered = className\n .split(/\\s+/)\n .filter((token) => token && !resizeClassMap[token])\n .join(\" \");\n\n return filtered || undefined;\n}\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n className,\n size = \"md\",\n error = false,\n disabled,\n resizable = true,\n showCharacterCount = false,\n maxCharacters,\n maxHeight,\n value: controlledValue,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n style: propStyle,\n styles,\n ...props\n },\n ref\n ) => {\n const [internalValue, setInternalValue] = useState(controlledValue ?? defaultValue ?? \"\");\n const [isFocused, setIsFocused] = React.useState(false);\n const [internalHeight, setInternalHeight] = React.useState<number | null>(null);\n const [internalWidth, setInternalWidth] = React.useState<number | null>(null);\n\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const surfaceRef = React.useRef<HTMLDivElement>(null);\n const scrollWrapperRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const mergedRef = useMergeRefs(ref, textareaRef);\n\n const { focusProps, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({ isDisabled: disabled });\n const { indicatorProps } = useFocus({\n scopeRef,\n containerRef,\n surfaceSelector: '[data-textarea-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n dependencies: [maxHeight, size],\n });\n\n const currentValue = controlledValue !== undefined ? controlledValue : internalValue;\n const charCount = typeof currentValue === \"string\" ? currentValue.length : 0;\n const isOverLimit = maxCharacters ? charCount > maxCharacters : false;\n const hasScrollSurface = maxHeight !== undefined;\n const resizeAxis = resolveResizeAxis(className, resizable);\n const canResize = resizeAxis !== \"none\" && !disabled;\n const textareaClassName = stripResizeClasses(className);\n const resolved = resolveTextareaStyles(styles);\n\n const handleFocus = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(true);\n onFocus?.(event);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(false);\n onBlur?.(event);\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const nextValue = event.target.value;\n\n if (maxCharacters && nextValue.length > maxCharacters) {\n const truncatedValue = nextValue.slice(0, maxCharacters);\n\n if (controlledValue === undefined) {\n setInternalValue(truncatedValue);\n }\n\n onChange?.({\n ...event,\n target: { ...event.target, value: truncatedValue },\n } as React.ChangeEvent<HTMLTextAreaElement>);\n return;\n }\n\n if (controlledValue === undefined) {\n setInternalValue(nextValue);\n }\n\n onChange?.(event);\n };\n\n const handleResizeMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!canResize) return;\n\n event.preventDefault();\n\n const textarea = textareaRef.current;\n const surface = surfaceRef.current;\n const scrollWrapper = scrollWrapperRef.current;\n if (!textarea || !surface) return;\n\n const computed = window.getComputedStyle(textarea);\n const minHeight = Number.parseFloat(computed.minHeight) || 60;\n const minWidth = Number.parseFloat(computed.minWidth) || 160;\n const startX = event.clientX;\n const startY = event.clientY;\n const startWidth = surface.getBoundingClientRect().width;\n const startHeight = hasScrollSurface\n ? (scrollWrapper?.getBoundingClientRect().height ?? surface.getBoundingClientRect().height)\n : surface.getBoundingClientRect().height;\n\n const onMouseMove = (nextEvent: MouseEvent) => {\n if (resizeAxis === \"x\" || resizeAxis === \"both\") {\n const deltaX = nextEvent.clientX - startX;\n setInternalWidth(Math.max(minWidth, startWidth + deltaX));\n }\n\n if (resizeAxis === \"y\" || resizeAxis === \"both\") {\n const deltaY = nextEvent.clientY - startY;\n setInternalHeight(Math.max(minHeight, startHeight + deltaY));\n }\n };\n\n const onMouseUp = () => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"mouseup\", onMouseUp);\n document.body.style.userSelect = \"\";\n };\n\n document.addEventListener(\"mousemove\", onMouseMove);\n document.addEventListener(\"mouseup\", onMouseUp);\n document.body.style.userSelect = \"none\";\n },\n [canResize, hasScrollSurface, resizeAxis]\n );\n\n const effectiveMaxHeight = internalHeight !== null ? `${internalHeight}px` : maxHeight;\n\n const autoResize = React.useCallback(() => {\n const element = textareaRef.current;\n if (!element || !maxHeight) return;\n\n element.style.height = \"auto\";\n element.style.height = `${element.scrollHeight}px`;\n }, [maxHeight]);\n\n React.useLayoutEffect(() => {\n autoResize();\n }, [autoResize, currentValue]);\n\n const surfaceStyle: React.CSSProperties = {\n ...(internalWidth !== null ? { width: `${internalWidth}px`, maxWidth: \"100%\" } : {}),\n ...(maxHeight === undefined && internalHeight !== null ? { height: `${internalHeight}px` } : {}),\n };\n\n const textareaStyle: React.CSSProperties = {\n ...propStyle,\n resize: \"none\",\n ...(maxHeight === undefined && internalHeight !== null ? { height: \"100%\" } : {}),\n };\n\n const resolvedResizeHandle =\n resizeAxis === \"none\"\n ? undefined\n : resizeAxis === \"x\"\n ? resolved.resizeHandleX\n : resizeAxis === \"y\"\n ? resolved.resizeHandleY\n : resolved.resizeHandleBoth;\n\n const textareaElement = (\n <textarea\n ref={mergedRef}\n disabled={disabled}\n data-size={size}\n data-scroll={hasScrollSurface ? \"true\" : undefined}\n data-resize-axis={resizeAxis}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-textarea-focus-surface={hasScrollSurface ? undefined : \"true\"}\n className={cn(\n \"textarea\",\n css.textarea,\n sizeMap[size],\n textareaClassName,\n resolved.root\n )}\n style={textareaStyle}\n value={currentValue}\n {...mergeProps(focusProps, hoverProps, {\n onFocus: handleFocus,\n onBlur: handleBlur,\n onChange: handleChange,\n ...props,\n })}\n />\n );\n\n return (\n <div ref={scopeRef} className={cn(\"textarea-scope\", css.scope)}>\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n ref={containerRef}\n className={cn(\"container\", css.container, resolved.container)}\n >\n <div\n ref={surfaceRef}\n className={cn(\"surface\", css.surface, resolved.surface)}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-resize-axis={resizeAxis}\n style={surfaceStyle}\n >\n {hasScrollSurface ? (\n <div\n ref={scrollWrapperRef}\n data-textarea-focus-surface=\"true\"\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n className={cn(\n \"textarea\",\n \"scroll-wrapper\",\n css[\"scroll-wrapper\"],\n resolved.scrollWrapper\n )}\n >\n <Scroll maxHeight={effectiveMaxHeight} style={{ height: \"auto\" }}>\n {textareaElement}\n </Scroll>\n </div>\n ) : (\n textareaElement\n )}\n {canResize && (\n <div\n aria-hidden=\"true\"\n data-axis={resizeAxis}\n data-slot=\"resize-handle\"\n className={cn(\n \"textarea\",\n \"resize-handle\",\n css[\"resize-handle\"],\n resizeHandleClassMap[resizeAxis],\n resolvedResizeHandle\n )}\n onMouseDown={handleResizeMouseDown}\n />\n )}\n </div>\n {showCharacterCount && (\n <div\n className={cn(\n \"textarea\",\n \"character-count\",\n css[\"character-count\"],\n resolved.characterCount\n )}\n data-over-limit={isOverLimit ? \"true\" : undefined}\n >\n {charCount}\n {maxCharacters ? ` / ${maxCharacters}` : \"\"} characters\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nTextarea.displayName = \"Textarea\";\n\nconst TextArea = Textarea;\n\nexport { Textarea, TextArea };\n",
|
|
5157
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .textarea {\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n\n @apply block w-full px-3 py-2;\n box-sizing: border-box;\n resize: none;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n color: var(--foreground);\n font-family: inherit;\n font-size: var(--text-
|
|
5069
|
+
"tsx": "\"use client\";\n\nimport React, { forwardRef, useState, type ComponentPropsWithoutRef } from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { Scroll } from \"@/components/Scroll\";\nimport css from \"./Textarea.module.css\";\n\ntype TextareaSize = \"sm\" | \"md\" | \"lg\";\ntype ResizeAxis = \"both\" | \"x\" | \"y\" | \"none\";\n\nexport interface TextareaResizeHandleStyles {\n both?: StyleValue;\n x?: StyleValue;\n y?: StyleValue;\n}\n\nexport interface TextareaStyleSlots {\n root?: StyleValue;\n container?: StyleValue;\n surface?: StyleValue;\n scrollWrapper?: StyleValue;\n resizeHandle?: StyleValue | TextareaResizeHandleStyles;\n characterCount?: StyleValue;\n}\n\nexport type TextareaStylesProp = StylesProp<TextareaStyleSlots>;\nexport type TextAreaStyleSlots = TextareaStyleSlots;\nexport type TextAreaStylesProp = TextareaStylesProp;\n\nconst resolveTextareaBaseStyles = createStylesResolver([\n \"root\",\n \"container\",\n \"surface\",\n \"scrollWrapper\",\n \"resizeHandleBoth\",\n \"resizeHandleX\",\n \"resizeHandleY\",\n \"characterCount\",\n] as const);\n\nfunction resolveTextareaStyles(styles: TextareaStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return resolveTextareaBaseStyles(styles);\n }\n\n const { root, container, surface, scrollWrapper, resizeHandle, characterCount } = styles;\n\n let resizeHandleBoth: StyleValue | undefined;\n let resizeHandleX: StyleValue | undefined;\n let resizeHandleY: StyleValue | undefined;\n\n if (resizeHandle) {\n if (typeof resizeHandle === \"string\" || Array.isArray(resizeHandle)) {\n resizeHandleBoth = resizeHandle;\n resizeHandleX = resizeHandle;\n resizeHandleY = resizeHandle;\n } else {\n resizeHandleBoth = resizeHandle.both;\n resizeHandleX = resizeHandle.x;\n resizeHandleY = resizeHandle.y;\n }\n }\n\n return resolveTextareaBaseStyles({\n root,\n container,\n surface,\n scrollWrapper,\n resizeHandleBoth,\n resizeHandleX,\n resizeHandleY,\n characterCount,\n });\n}\n\nexport interface TextareaProps extends Omit<ComponentPropsWithoutRef<\"textarea\">, \"size\"> {\n /** Size of the textarea. */\n size?: TextareaSize;\n /** Whether to apply error styling. */\n error?: boolean;\n /** Whether the textarea can be manually resized by the user. When enabled, `className` may include Tailwind `resize`, `resize-x`, `resize-y`, or `resize-none` to select the resize axis. Defaults to vertical resizing. */\n resizable?: boolean;\n /** Whether to display a character count below the textarea. */\n showCharacterCount?: boolean;\n /** Maximum number of characters allowed. */\n maxCharacters?: number;\n /** Maximum height before the custom scrollbar activates. */\n maxHeight?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: TextareaStylesProp;\n}\n\nexport type TextAreaProps = TextareaProps;\n\nconst resizeClassMap: Record<string, ResizeAxis> = {\n resize: \"y\",\n \"resize-x\": \"x\",\n \"resize-y\": \"y\",\n \"resize-none\": \"none\",\n};\n\nconst sizeMap: Record<TextareaSize, string> = {\n sm: css[\"size-sm\"],\n md: css[\"size-md\"],\n lg: css[\"size-lg\"],\n};\n\nconst resizeHandleClassMap: Record<Exclude<ResizeAxis, \"none\">, string> = {\n both: css[\"resize-handle-both\"],\n x: css[\"resize-handle-x\"],\n y: css[\"resize-handle-y\"],\n};\n\nfunction resolveResizeAxis(className: string | undefined, resizable: boolean): ResizeAxis {\n if (!resizable) return \"none\";\n\n let axis: ResizeAxis | undefined;\n for (const token of className?.split(/\\s+/) ?? []) {\n const nextAxis = resizeClassMap[token];\n if (nextAxis) axis = nextAxis;\n }\n\n return axis ?? \"y\";\n}\n\nfunction stripResizeClasses(className: string | undefined) {\n if (!className) return className;\n\n const filtered = className\n .split(/\\s+/)\n .filter((token) => token && !resizeClassMap[token])\n .join(\" \");\n\n return filtered || undefined;\n}\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n className,\n size = \"md\",\n error = false,\n disabled,\n resizable = true,\n showCharacterCount = false,\n maxCharacters,\n maxHeight,\n value: controlledValue,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n style: propStyle,\n styles,\n ...props\n },\n ref\n ) => {\n const [internalValue, setInternalValue] = useState(controlledValue ?? defaultValue ?? \"\");\n const [isFocused, setIsFocused] = React.useState(false);\n const [internalHeight, setInternalHeight] = React.useState<number | null>(null);\n const [internalWidth, setInternalWidth] = React.useState<number | null>(null);\n\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const surfaceRef = React.useRef<HTMLDivElement>(null);\n const scrollWrapperRef = React.useRef<HTMLDivElement>(null);\n const textareaRef = React.useRef<HTMLTextAreaElement>(null);\n const mergedRef = useMergeRefs(ref, textareaRef);\n\n const { focusProps, isFocusVisible } = useFocusRing();\n const { indicatorProps } = useFocus({\n scopeRef,\n containerRef,\n surfaceSelector: '[data-textarea-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n dependencies: [maxHeight, size],\n });\n\n const currentValue = controlledValue !== undefined ? controlledValue : internalValue;\n const charCount = typeof currentValue === \"string\" ? currentValue.length : 0;\n const isOverLimit = maxCharacters ? charCount > maxCharacters : false;\n const hasScrollSurface = maxHeight !== undefined;\n const resizeAxis = resolveResizeAxis(className, resizable);\n const canResize = resizeAxis !== \"none\" && !disabled;\n const textareaClassName = stripResizeClasses(className);\n const resolved = resolveTextareaStyles(styles);\n\n const handleFocus = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(true);\n onFocus?.(event);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n setIsFocused(false);\n onBlur?.(event);\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n const nextValue = event.target.value;\n\n if (maxCharacters && nextValue.length > maxCharacters) {\n const truncatedValue = nextValue.slice(0, maxCharacters);\n\n if (controlledValue === undefined) {\n setInternalValue(truncatedValue);\n }\n\n onChange?.({\n ...event,\n target: { ...event.target, value: truncatedValue },\n } as React.ChangeEvent<HTMLTextAreaElement>);\n return;\n }\n\n if (controlledValue === undefined) {\n setInternalValue(nextValue);\n }\n\n onChange?.(event);\n };\n\n const handleResizeMouseDown = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!canResize) return;\n\n event.preventDefault();\n\n const textarea = textareaRef.current;\n const surface = surfaceRef.current;\n const scrollWrapper = scrollWrapperRef.current;\n if (!textarea || !surface) return;\n\n const computed = window.getComputedStyle(textarea);\n const minHeight = Number.parseFloat(computed.minHeight) || 60;\n const minWidth = Number.parseFloat(computed.minWidth) || 160;\n const startX = event.clientX;\n const startY = event.clientY;\n const startWidth = surface.getBoundingClientRect().width;\n const startHeight = hasScrollSurface\n ? (scrollWrapper?.getBoundingClientRect().height ?? surface.getBoundingClientRect().height)\n : surface.getBoundingClientRect().height;\n\n const onMouseMove = (nextEvent: MouseEvent) => {\n if (resizeAxis === \"x\" || resizeAxis === \"both\") {\n const deltaX = nextEvent.clientX - startX;\n setInternalWidth(Math.max(minWidth, startWidth + deltaX));\n }\n\n if (resizeAxis === \"y\" || resizeAxis === \"both\") {\n const deltaY = nextEvent.clientY - startY;\n setInternalHeight(Math.max(minHeight, startHeight + deltaY));\n }\n };\n\n const onMouseUp = () => {\n document.removeEventListener(\"mousemove\", onMouseMove);\n document.removeEventListener(\"mouseup\", onMouseUp);\n document.body.style.userSelect = \"\";\n };\n\n document.addEventListener(\"mousemove\", onMouseMove);\n document.addEventListener(\"mouseup\", onMouseUp);\n document.body.style.userSelect = \"none\";\n },\n [canResize, hasScrollSurface, resizeAxis]\n );\n\n const effectiveMaxHeight = internalHeight !== null ? `${internalHeight}px` : maxHeight;\n\n const autoResize = React.useCallback(() => {\n const element = textareaRef.current;\n if (!element || !maxHeight) return;\n\n element.style.height = \"auto\";\n element.style.height = `${element.scrollHeight}px`;\n }, [maxHeight]);\n\n React.useLayoutEffect(() => {\n autoResize();\n }, [autoResize, currentValue]);\n\n const surfaceStyle: React.CSSProperties = {\n ...(internalWidth !== null ? { width: `${internalWidth}px`, maxWidth: \"100%\" } : {}),\n ...(maxHeight === undefined && internalHeight !== null ? { height: `${internalHeight}px` } : {}),\n };\n\n const textareaStyle: React.CSSProperties = {\n ...propStyle,\n resize: \"none\",\n ...(maxHeight === undefined && internalHeight !== null ? { height: \"100%\" } : {}),\n };\n\n const resolvedResizeHandle =\n resizeAxis === \"none\"\n ? undefined\n : resizeAxis === \"x\"\n ? resolved.resizeHandleX\n : resizeAxis === \"y\"\n ? resolved.resizeHandleY\n : resolved.resizeHandleBoth;\n\n const textareaElement = (\n <textarea\n ref={mergedRef}\n disabled={disabled}\n data-size={size}\n data-scroll={hasScrollSurface ? \"true\" : undefined}\n data-resize-axis={resizeAxis}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-textarea-focus-surface={hasScrollSurface ? undefined : \"true\"}\n className={cn(\n \"textarea\",\n css.textarea,\n sizeMap[size],\n textareaClassName,\n resolved.root\n )}\n style={textareaStyle}\n value={currentValue}\n {...mergeProps(focusProps, {\n onFocus: handleFocus,\n onBlur: handleBlur,\n onChange: handleChange,\n ...props,\n })}\n />\n );\n\n return (\n <div ref={scopeRef} className={cn(\"textarea-scope\", css.scope)}>\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n <div\n ref={containerRef}\n className={cn(\"container\", css.container, resolved.container)}\n >\n <div\n ref={surfaceRef}\n className={cn(\"surface\", css.surface, resolved.surface)}\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-resize-axis={resizeAxis}\n style={surfaceStyle}\n >\n {hasScrollSurface ? (\n <div\n ref={scrollWrapperRef}\n data-textarea-focus-surface=\"true\"\n data-disabled={disabled ? \"true\" : undefined}\n data-error={error || isOverLimit ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n className={cn(\n \"textarea\",\n \"scroll-wrapper\",\n css[\"scroll-wrapper\"],\n resolved.scrollWrapper\n )}\n >\n <Scroll maxHeight={effectiveMaxHeight} style={{ height: \"auto\" }}>\n {textareaElement}\n </Scroll>\n </div>\n ) : (\n textareaElement\n )}\n {canResize && (\n <div\n aria-hidden=\"true\"\n data-axis={resizeAxis}\n data-slot=\"resize-handle\"\n className={cn(\n \"textarea\",\n \"resize-handle\",\n css[\"resize-handle\"],\n resizeHandleClassMap[resizeAxis],\n resolvedResizeHandle\n )}\n onMouseDown={handleResizeMouseDown}\n />\n )}\n </div>\n {showCharacterCount && (\n <div\n className={cn(\n \"textarea\",\n \"character-count\",\n css[\"character-count\"],\n resolved.characterCount\n )}\n data-over-limit={isOverLimit ? \"true\" : undefined}\n >\n {charCount}\n {maxCharacters ? ` / ${maxCharacters}` : \"\"} characters\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nTextarea.displayName = \"Textarea\";\n\nconst TextArea = Textarea;\n\nexport { Textarea, TextArea };\n",
|
|
5070
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .textarea {\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n\n @apply block w-full px-3 py-2;\n box-sizing: border-box;\n resize: none;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n color: var(--foreground);\n font-family: inherit;\n font-size: var(--text-xs);\n line-height: var(--leading-snug);\n outline: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &::placeholder {\n color: var(--placeholder);\n }\n\n &[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity);\n }\n\n &[data-resize-axis=\"x\"],\n &[data-resize-axis=\"both\"] {\n padding-inline-end: calc(var(--padding-inline) + 1rem);\n }\n\n &[data-resize-axis=\"y\"],\n &[data-resize-axis=\"both\"] {\n padding-block-end: calc(var(--padding-block) + 1rem);\n }\n\n &[data-scroll=\"true\"] {\n border: none;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n overflow: hidden;\n\n &[data-disabled=\"true\"] {\n opacity: 1;\n }\n }\n }\n\n .size-sm {\n min-height: 5rem;\n --padding-inline: 0.5rem;\n --padding-block: 0.25rem;\n font-size: var(--text-sm);\n @apply px-2 py-1;\n }\n\n .size-md {\n min-height: 6rem;\n --padding-inline: 0.75rem;\n --padding-block: 0.5rem;\n font-size: var(--text-sm);\n @apply px-3 py-2;\n }\n\n .size-lg {\n min-height: 8rem;\n --padding-inline: 1rem;\n --padding-block: 0.75rem;\n font-size: var(--text-md);\n @apply px-4 py-3;\n }\n\n .container {\n min-width: 0;\n @apply w-full;\n }\n\n .scope {\n @apply relative flex w-full;\n overflow: visible;\n }\n\n .surface {\n min-width: 0;\n @apply relative w-full;\n }\n\n .scroll-wrapper {\n @apply w-full overflow-hidden;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n background-color: var(--background);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n }\n }\n\n .resize-handle {\n position: absolute;\n z-index: 1;\n touch-action: none;\n user-select: none;\n\n &::before,\n &::after {\n content: \"\";\n position: absolute;\n border-radius: var(--radius-full);\n background-color: var(--background);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n &:hover::before,\n &:hover::after {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .resize-handle-both {\n right: 3px;\n bottom: 3px;\n width: 1.5rem;\n height: 1.5rem;\n cursor: nwse-resize;\n\n &::before {\n right: 0.15rem;\n bottom: 0.35rem;\n width: 0.5rem;\n height: 0.125rem;\n transform: rotate(-45deg);\n transform-origin: center;\n }\n\n &::after {\n right: 0.2rem;\n bottom: 0.6rem;\n width: 1rem;\n height: 0.125rem;\n transform: rotate(-45deg);\n transform-origin: center;\n }\n }\n\n .resize-handle-x {\n top: 50%;\n right: 0;\n width: 0.75rem;\n height: 2rem;\n cursor: ew-resize;\n transform: translateY(-50%);\n\n &::before {\n top: 50%;\n left: 50%;\n width: 0.125rem;\n height: 1.5rem;\n transform: translate(-50%, -50%);\n }\n\n &::after {\n display: none;\n }\n }\n\n .resize-handle-y {\n left: 50%;\n bottom: 0;\n width: 2rem;\n height: 0.75rem;\n cursor: ns-resize;\n transform: translateX(-50%);\n\n &::before {\n top: 50%;\n left: 50%;\n width: 1.5rem;\n height: 0.125rem;\n transform: translate(-50%, -50%);\n }\n\n &::after {\n display: none;\n }\n }\n\n .character-count {\n @apply mt-1;\n color: var(--foreground);\n font-size: var(--text-sm);\n transition: color 0.15s var(--ease-snappy-pop);\n }\n\n .character-count[data-over-limit=\"true\"] {\n color: var(--foreground-error);\n }\n}\n",
|
|
5158
5071
|
"cssTypes": "declare const styles: {\n scope: string;\n textarea: string;\n \"size-sm\": string;\n \"size-md\": string;\n \"size-lg\": string;\n container: string;\n surface: string;\n \"character-count\": string;\n \"scroll-wrapper\": string;\n \"resize-handle\": string;\n \"resize-handle-both\": string;\n \"resize-handle-x\": string;\n \"resize-handle-y\": string;\n};\n\nexport default styles;\n"
|
|
5159
5072
|
},
|
|
5160
5073
|
"toast": {
|
|
5161
|
-
"tsx": "\"use client\";\n\nimport React, { forwardRef, useImperativeHandle, useRef, useEffect, useCallback } from 'react';\nimport gsap from 'gsap';\nimport { useGSAP } from \"@gsap/react\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from '@/lib/styles';\nimport css from './Toast.module.css';\nimport { ToastProps as ToastData, dispatch } from \"./Toast.Store\";\n\nimport { Info, CircleCheck, TriangleAlert, CircleAlert, type LucideIcon } from \"lucide-react\";\n\nimport { X } from 'lucide-react';\n\nconst DRAG_DISMISS_THRESHOLD = 100;\nconst DRAG_LEFT_RESISTANCE = 20;\n\nexport interface ToastStyleSlots {\n root?: StyleValue;\n iconWrap?: StyleValue;\n icon?: StyleValue;\n content?: StyleValue;\n title?: StyleValue;\n description?: StyleValue;\n close?: StyleValue;\n closeIcon?: StyleValue;\n}\n\nexport type ToastStylesProp = StylesProp<ToastStyleSlots>;\n\nconst resolveToastBaseStyles = createStylesResolver([\n 'root',\n 'iconWrap',\n 'icon',\n 'content',\n 'title',\n 'description',\n 'close',\n 'closeIcon'\n] as const);\n\nfunction resolveToastStyles(styles: ToastStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveToastBaseStyles(styles);\n\n const { root, iconWrap, icon, content, title, description, close, closeIcon } = styles;\n\n return resolveToastBaseStyles({ root, iconWrap, icon, content, title, description, close, closeIcon });\n}\n\nconst toastIcons: Record<string, LucideIcon | null> = {\n danger: TriangleAlert,\n success: CircleCheck,\n info: Info,\n warning: CircleAlert,\n default: null,\n};\n\ninterface ToastComponentProps {\n /** Toast data object containing content and display options */\n toast: ToastData;\n /** Whether the auto-dismiss timer pauses on mouse hover */\n pauseOnHover?: boolean;\n onDragStart?: () => void;\n onDragEnd?: () => void;\n onDismissStart?: () => void;\n onDismissEnd?: () => void;\n}\n\nexport const Toast = forwardRef<HTMLDivElement, ToastComponentProps>(function Toast(\n { toast, pauseOnHover = false, onDragStart, onDragEnd, onDismissStart, onDismissEnd },\n ref\n) {\n const innerRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => innerRef.current!);\n\n const {\n id,\n title,\n description,\n jsx,\n variant = 'default',\n duration = 5000,\n onDismiss,\n position = 'bottom-right',\n styles,\n } = toast;\n\n const resolved = resolveToastStyles(styles);\n const isTop = position.startsWith('top');\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({});\n const closeInteractionProps = mergeProps(focusProps, hoverProps) as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n // Time tracking refs\n const elapsedRef = useRef(0);\n const lastTimeRef = useRef<number>(Date.now());\n const animationFrameRef = useRef<number | null>(null);\n\n // Use a ref for paused state to avoid restarting the effect on every hover change\n const isPausedRef = useRef(pauseOnHover);\n useEffect(() => {\n isPausedRef.current = pauseOnHover;\n }, [pauseOnHover]);\n\n // Drag state refs\n const dragStartXRef = useRef(0);\n const currentDeltaRef = useRef(0);\n const dragPausedRef = useRef(false);\n\n const handleDismiss = useCallback(() => {\n // Change absolute numbers to relative strings\n const yOffset = isTop ? \"-=20\" : \"+=20\";\n\n if (innerRef.current) {\n innerRef.current.dataset.dismissing = \"true\";\n onDismissStart?.();\n dispatch({ type: 'CLOSE_TOAST', toastId: id });\n gsap.killTweensOf(innerRef.current);\n gsap.to(innerRef.current, {\n opacity: 0,\n y: yOffset, // Animates relative to its current layout position\n scale: 0.9,\n duration: 0.35,\n ease: \"expo.out\",\n onComplete: () => {\n onDismissEnd?.();\n onDismiss?.();\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n },\n });\n } else {\n onDismiss?.();\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n }\n }, [id, isTop, onDismiss]);\n\n useGSAP(() => {\n if (!
|
|
5162
|
-
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply flex w-full max-w-[28rem] items-start gap-3 px-4 py-2.5 select-none;\n background: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-shadow: var(--background-shadow);\n font-family: inherit;\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n touch-action: pan-y;\n }\n\n .icon-wrap {\n @apply mr-4 mt-2 h-5 w-5 shrink-0;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--foreground);\n }\n\n .content {\n @apply min-w-0 flex-1;\n }\n\n .title {\n @apply m-0;\n --foreground: inherit;\n font-weight: var(--font-weight-semibold);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n color: var(--foreground);\n }\n\n .description {\n @apply mt-1 mb-0;\n --foreground: inherit;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n color: var(--foreground);\n }\n\n .close {\n @apply flex shrink-0 items-center justify-center p-2 cursor-pointer;\n --foreground: currentColor;\n
|
|
5074
|
+
"tsx": "\"use client\";\n\nimport React, { forwardRef, useImperativeHandle, useRef, useEffect, useCallback } from 'react';\nimport gsap from 'gsap';\nimport { useGSAP } from \"@gsap/react\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from '@/lib/styles';\nimport css from './Toast.module.css';\nimport { ToastProps as ToastData, dispatch } from \"./Toast.Store\";\n\nimport { Info, CircleCheck, TriangleAlert, CircleAlert, type LucideIcon } from \"lucide-react\";\n\nimport { X } from 'lucide-react';\n\nconst DRAG_DISMISS_THRESHOLD = 100;\nconst DRAG_LEFT_RESISTANCE = 20;\nconst VIEWPORT_SPAWN_OFFSET = 24;\n\nfunction getViewportSpawnY(element: HTMLElement, direction: 'top' | 'bottom') {\n if (typeof window === 'undefined') return direction === 'top' ? -80 : 80;\n\n const rect = element.getBoundingClientRect();\n\n if (direction === 'top') {\n return -(rect.bottom + VIEWPORT_SPAWN_OFFSET);\n }\n\n return window.innerHeight - rect.top + VIEWPORT_SPAWN_OFFSET;\n}\n\nexport interface ToastStyleSlots {\n root?: StyleValue;\n iconWrap?: StyleValue;\n icon?: StyleValue;\n content?: StyleValue;\n title?: StyleValue;\n description?: StyleValue;\n close?: StyleValue;\n closeIcon?: StyleValue;\n}\n\nexport type ToastStylesProp = StylesProp<ToastStyleSlots>;\n\nconst resolveToastBaseStyles = createStylesResolver([\n 'root',\n 'iconWrap',\n 'icon',\n 'content',\n 'title',\n 'description',\n 'close',\n 'closeIcon'\n] as const);\n\nfunction resolveToastStyles(styles: ToastStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveToastBaseStyles(styles);\n\n const { root, iconWrap, icon, content, title, description, close, closeIcon } = styles;\n\n return resolveToastBaseStyles({ root, iconWrap, icon, content, title, description, close, closeIcon });\n}\n\nconst toastIcons: Record<string, LucideIcon | null> = {\n danger: TriangleAlert,\n success: CircleCheck,\n info: Info,\n warning: CircleAlert,\n default: null,\n};\n\ninterface ToastComponentProps {\n /** Toast data object containing content and display options */\n toast: ToastData;\n /** Whether the auto-dismiss timer pauses on mouse hover */\n pauseOnHover?: boolean;\n onDragStart?: () => void;\n onDragEnd?: () => void;\n onDismissStart?: () => void;\n onDismissEnd?: () => void;\n}\n\nexport const Toast = forwardRef<HTMLDivElement, ToastComponentProps>(function Toast(\n { toast, pauseOnHover = false, onDragStart, onDragEnd, onDismissStart, onDismissEnd },\n ref\n) {\n const innerRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => innerRef.current!);\n\n const {\n id,\n title,\n description,\n jsx,\n variant = 'default',\n duration = 5000,\n onDismiss,\n position = 'bottom-right',\n styles,\n } = toast;\n\n const resolved = resolveToastStyles(styles);\n const isTop = position.startsWith('top');\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({});\n const closeInteractionProps = mergeProps(focusProps, hoverProps) as React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n // Time tracking refs\n const elapsedRef = useRef(0);\n const lastTimeRef = useRef<number>(Date.now());\n const animationFrameRef = useRef<number | null>(null);\n\n // Use a ref for paused state to avoid restarting the effect on every hover change\n const isPausedRef = useRef(pauseOnHover);\n useEffect(() => {\n isPausedRef.current = pauseOnHover;\n }, [pauseOnHover]);\n\n // Drag state refs\n const dragStartXRef = useRef(0);\n const currentDeltaRef = useRef(0);\n const dragPausedRef = useRef(false);\n\n const handleDismiss = useCallback(() => {\n // Change absolute numbers to relative strings\n const yOffset = isTop ? \"-=20\" : \"+=20\";\n\n if (innerRef.current) {\n innerRef.current.dataset.dismissing = \"true\";\n onDismissStart?.();\n dispatch({ type: 'CLOSE_TOAST', toastId: id });\n gsap.killTweensOf(innerRef.current);\n gsap.to(innerRef.current, {\n opacity: 0,\n y: yOffset, // Animates relative to its current layout position\n scale: 0.9,\n duration: 0.35,\n ease: \"expo.out\",\n onComplete: () => {\n onDismissEnd?.();\n onDismiss?.();\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n },\n });\n } else {\n onDismiss?.();\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n }\n }, [id, isTop, onDismiss]);\n\n useGSAP(() => {\n const element = innerRef.current;\n if (!element) return;\n\n const spawnDir = toast.spawnDirection ?? (isTop ? 'top' : 'bottom');\n const fromY = getViewportSpawnY(element, spawnDir);\n\n gsap.fromTo(element, {\n opacity: 0,\n y: fromY,\n scale: 0.96,\n }, {\n opacity: 1,\n y: 0,\n scale: 1,\n duration: 0.45,\n ease: \"expo.out\",\n overwrite: \"auto\",\n });\n }, { scope: innerRef });\n\n const handlePointerDown = useCallback((e: React.PointerEvent) => {\n if (innerRef.current?.dataset.dismissing) return;\n dragStartXRef.current = e.clientX;\n currentDeltaRef.current = 0;\n dragPausedRef.current = true;\n onDragStart?.();\n gsap.killTweensOf(innerRef.current);\n\n const onMove = (ev: PointerEvent) => {\n if (!innerRef.current) return;\n const delta = ev.clientX - dragStartXRef.current;\n currentDeltaRef.current = delta;\n\n if (delta >= 0) {\n const progress = Math.min(delta / DRAG_DISMISS_THRESHOLD, 1);\n gsap.set(innerRef.current, { x: delta, opacity: 1 - progress * 0.5 });\n } else {\n const x = -DRAG_LEFT_RESISTANCE * (1 - Math.exp(delta / DRAG_LEFT_RESISTANCE));\n gsap.set(innerRef.current, { x, opacity: 1 });\n }\n };\n\n const onUp = () => {\n dragPausedRef.current = false;\n onDragEnd?.();\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n document.removeEventListener('pointercancel', onUp);\n\n const delta = currentDeltaRef.current;\n currentDeltaRef.current = 0;\n\n if (delta >= DRAG_DISMISS_THRESHOLD) {\n if (innerRef.current) {\n innerRef.current.dataset.dismissing = \"true\";\n onDismissStart?.();\n // Dispatch CLOSE_TOAST immediately to signal stack adjustment\n dispatch({ type: 'CLOSE_TOAST', toastId: id });\n gsap.killTweensOf(innerRef.current);\n gsap.to(innerRef.current, {\n x: \"+=200\",\n opacity: 0,\n duration: 0.25,\n ease: \"power2.in\",\n onComplete: () => {\n onDismissEnd?.();\n onDismiss?.();\n // Dispatch DISMISS_TOAST after animation completes\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n },\n });\n } else {\n // If innerRef.current is null, just dismiss immediately\n onDismiss?.();\n dispatch({ type: 'DISMISS_TOAST', toastId: id });\n }\n } else if (innerRef.current) {\n gsap.to(innerRef.current, {\n x: 0,\n opacity: 1,\n duration: 0.55,\n ease: \"elastic.out(1, 0.55)\",\n });\n }\n };\n\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerup', onUp);\n document.addEventListener('pointercancel', onUp);\n }, [id, isTop, onDismiss, onDragStart, onDragEnd, onDismissStart, onDismissEnd]);\n\n // Animation Frame Timer Logic\n useEffect(() => {\n if (duration === Infinity || duration <= 0) return;\n lastTimeRef.current = Date.now();\n\n const loop = () => {\n const now = Date.now();\n const delta = now - lastTimeRef.current;\n lastTimeRef.current = now;\n\n if (!isPausedRef.current && !dragPausedRef.current) {\n elapsedRef.current += delta;\n\n if (elapsedRef.current >= duration) {\n handleDismiss();\n return;\n }\n }\n\n animationFrameRef.current = requestAnimationFrame(loop);\n };\n\n animationFrameRef.current = requestAnimationFrame(loop);\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, [duration, handleDismiss]);\n\n const Icon = toastIcons[variant as keyof typeof toastIcons];\n\n return (\n <div\n ref={innerRef}\n className={cn('toast', css.root, variant, resolved.root)}\n role=\"alert\"\n onPointerDown={handlePointerDown}\n >\n {Icon && (\n <div className={cn(\"icon-wrap\", css[\"icon-wrap\"], resolved.iconWrap)}>\n <Icon className={cn(\"icon\", css.icon, resolved.icon)} />\n </div>\n )}\n <div className={cn('content', css.content, resolved.content)}>\n {jsx || (\n <>\n {title && <h4 className={cn('title', css.title, resolved.title)}>{title}</h4>}\n {description && <p className={cn('description', css.description, resolved.description)}>{description}</p>}\n </>\n )}\n {toast.action}\n </div>\n <button\n {...closeInteractionProps}\n onClick={handleDismiss}\n className={cn('close', css.close, resolved.close)}\n aria-label=\"Close\"\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n <X className={cn(\"close-icon\", css[\"close-icon\"], resolved.closeIcon)} />\n </button>\n </div>\n );\n});\n",
|
|
5075
|
+
"css": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply flex w-full max-w-[28rem] items-start gap-3 px-4 py-2.5 select-none;\n background: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-shadow: var(--background-shadow);\n font-family: inherit;\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n touch-action: pan-y;\n }\n\n .icon-wrap {\n @apply mr-4 mt-2 h-5 w-5 shrink-0;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--foreground);\n }\n\n .content {\n @apply min-w-0 flex-1;\n }\n\n .title {\n @apply m-0;\n --foreground: inherit;\n font-weight: var(--font-weight-semibold);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n color: var(--foreground);\n }\n\n .description {\n @apply mt-1 mb-0;\n --foreground: inherit;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-normal, 1.5);\n color: var(--foreground);\n }\n\n .close {\n @apply flex shrink-0 items-center justify-center p-2 cursor-pointer;\n --foreground: currentColor;\n background-color: var(--background, transparent);\n border: none;\n border-radius: var(--radius-sm, 0.375rem);\n color: var(--foreground);\n opacity: 0.6;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-settle-in, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-settle-in, ease-out));\n\n &[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 var(--border-width-base, 1px) var(--focus-visible);\n outline: none;\n }\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n opacity: 1;\n }\n }\n\n .close-icon {\n @apply h-4 w-4;\n }\n}\n",
|
|
5163
5076
|
"cssTypes": "declare const styles: {\n root: string;\n \"icon-wrap\": string;\n icon: string;\n content: string;\n title: string;\n description: string;\n close: string;\n \"close-icon\": string;\n};\n\nexport default styles;\n"
|
|
5164
5077
|
},
|
|
5165
5078
|
"tooltip": {
|
|
@@ -5400,6 +5313,6 @@ export const generatedCorePeerDependencies = [
|
|
|
5400
5313
|
"react-dom"
|
|
5401
5314
|
];
|
|
5402
5315
|
export const packageMetadata = {
|
|
5403
|
-
"version": "0.3.
|
|
5316
|
+
"version": "0.3.46"
|
|
5404
5317
|
};
|
|
5405
5318
|
//# sourceMappingURL=generated-data.js.map
|