@pk-design/react-tailwind 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/Accordion/Accordion.js +61 -0
- package/dist/cjs/components/Accordion/Accordion.js.map +1 -0
- package/dist/cjs/components/ActionSheet/ActionSheet.js +38 -0
- package/dist/cjs/components/ActionSheet/ActionSheet.js.map +1 -0
- package/dist/cjs/components/Alert/Alert.js +34 -0
- package/dist/cjs/components/Alert/Alert.js.map +1 -0
- package/dist/cjs/components/Badge/Badge.js +33 -0
- package/dist/cjs/components/Badge/Badge.js.map +1 -0
- package/dist/cjs/components/Banner/Banner.js +41 -0
- package/dist/cjs/components/Banner/Banner.js.map +1 -0
- package/dist/cjs/components/BodyText/BodyText.js +59 -0
- package/dist/cjs/components/BodyText/BodyText.js.map +1 -0
- package/dist/cjs/components/BottomNavigation/BottomNavigation.js +52 -0
- package/dist/cjs/components/BottomNavigation/BottomNavigation.js.map +1 -0
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js +63 -0
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/cjs/components/Button/Button.js +118 -0
- package/dist/cjs/components/Button/Button.js.map +1 -0
- package/dist/cjs/components/ButtonGroup/ButtonGroup.js +100 -0
- package/dist/cjs/components/ButtonGroup/ButtonGroup.js.map +1 -0
- package/dist/cjs/components/Card/Card.js +65 -0
- package/dist/cjs/components/Card/Card.js.map +1 -0
- package/dist/cjs/components/Checkbox/Checkbox.js +64 -0
- package/dist/cjs/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/cjs/components/CheckboxGroup/CheckboxGroup.js +82 -0
- package/dist/cjs/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
- package/dist/cjs/components/DataList/DataList.js +287 -0
- package/dist/cjs/components/DataList/DataList.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.icons.js +20 -0
- package/dist/cjs/components/DataTable/DataTable.icons.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.js +110 -0
- package/dist/cjs/components/DataTable/DataTable.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.utils.js +87 -0
- package/dist/cjs/components/DataTable/DataTable.utils.js.map +1 -0
- package/dist/cjs/components/DetailedInformation/DetailedInformation.js +67 -0
- package/dist/cjs/components/DetailedInformation/DetailedInformation.js.map +1 -0
- package/dist/cjs/components/Dot/index.js +12 -0
- package/dist/cjs/components/Dot/index.js.map +1 -0
- package/dist/cjs/components/Drawer/Drawer.js +67 -0
- package/dist/cjs/components/Drawer/Drawer.js.map +1 -0
- package/dist/cjs/components/Dropdown/Dropdown.js +50 -0
- package/dist/cjs/components/Dropdown/Dropdown.js.map +1 -0
- package/dist/cjs/components/EmptyState/index.js +14 -0
- package/dist/cjs/components/EmptyState/index.js.map +1 -0
- package/dist/cjs/components/Flex/Flex.js +25 -0
- package/dist/cjs/components/Flex/Flex.js.map +1 -0
- package/dist/cjs/components/FloatingActionButton/FloatingActionButton.js +71 -0
- package/dist/cjs/components/FloatingActionButton/FloatingActionButton.js.map +1 -0
- package/dist/cjs/components/Grid/Grid.js +33 -0
- package/dist/cjs/components/Grid/Grid.js.map +1 -0
- package/dist/cjs/components/HeadingText/HeadingText.js +89 -0
- package/dist/cjs/components/HeadingText/HeadingText.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownAZ.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownAZ.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownNarrowWide.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownNarrowWide.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownWideNarrow.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownWideNarrow.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownZA.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownZA.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowUpDown.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowUpDown.svg.js.map +1 -0
- package/dist/cjs/components/Icons/BadgeCheck.svg.js +48 -0
- package/dist/cjs/components/Icons/BadgeCheck.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Check.svg.js +46 -0
- package/dist/cjs/components/Icons/Check.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronDown.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronDown.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronLeft.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronLeft.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronRight.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronRight.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleAlert.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleAlert.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleCheck.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleCheck.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CirclePlus.svg.js +50 -0
- package/dist/cjs/components/Icons/CirclePlus.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleX.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleX.svg.js.map +1 -0
- package/dist/cjs/components/Icons/FolderPlus.svg.js +46 -0
- package/dist/cjs/components/Icons/FolderPlus.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Info.svg.js +50 -0
- package/dist/cjs/components/Icons/Info.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Search.svg.js +50 -0
- package/dist/cjs/components/Icons/Search.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Slash.svg.js +46 -0
- package/dist/cjs/components/Icons/Slash.svg.js.map +1 -0
- package/dist/cjs/components/Icons/TriangleAlert.svg.js +46 -0
- package/dist/cjs/components/Icons/TriangleAlert.svg.js.map +1 -0
- package/dist/cjs/components/Icons/X.svg.js +46 -0
- package/dist/cjs/components/Icons/X.svg.js.map +1 -0
- package/dist/cjs/components/Input/Input.js +85 -0
- package/dist/cjs/components/Input/Input.js.map +1 -0
- package/dist/cjs/components/Label/Label.js +14 -0
- package/dist/cjs/components/Label/Label.js.map +1 -0
- package/dist/cjs/components/Loader/index.js +18 -0
- package/dist/cjs/components/Loader/index.js.map +1 -0
- package/dist/cjs/components/MobileHeader/MobileHeader.js +45 -0
- package/dist/cjs/components/MobileHeader/MobileHeader.js.map +1 -0
- package/dist/cjs/components/MobilePicker/MobilePicker.js +368 -0
- package/dist/cjs/components/MobilePicker/MobilePicker.js.map +1 -0
- package/dist/cjs/components/MobileStepper/MobileStepper.js +33 -0
- package/dist/cjs/components/MobileStepper/MobileStepper.js.map +1 -0
- package/dist/cjs/components/Pagination/Pagination.js +33 -0
- package/dist/cjs/components/Pagination/Pagination.js.map +1 -0
- package/dist/cjs/components/Pagination/usePagination.js +33 -0
- package/dist/cjs/components/Pagination/usePagination.js.map +1 -0
- package/dist/cjs/components/PasswordInput/PasswordInput.js +56 -0
- package/dist/cjs/components/PasswordInput/PasswordInput.js.map +1 -0
- package/dist/cjs/components/PinInput/PinInput.js +98 -0
- package/dist/cjs/components/PinInput/PinInput.js.map +1 -0
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js +83 -0
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js.map +1 -0
- package/dist/cjs/components/QuantityStepper/QuantityStepper.js +77 -0
- package/dist/cjs/components/QuantityStepper/QuantityStepper.js.map +1 -0
- package/dist/cjs/components/Radio/Radio.js +34 -0
- package/dist/cjs/components/Radio/Radio.js.map +1 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.js +50 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/cjs/components/RadioSwitch/RadioSwitch.js +116 -0
- package/dist/cjs/components/RadioSwitch/RadioSwitch.js.map +1 -0
- package/dist/cjs/components/RangeInput/RangeInput.js +66 -0
- package/dist/cjs/components/RangeInput/RangeInput.js.map +1 -0
- package/dist/cjs/components/RangeSlider/RangeSlider.js +167 -0
- package/dist/cjs/components/RangeSlider/RangeSlider.js.map +1 -0
- package/dist/cjs/components/SegmentedControl/SegmentedControl.js +64 -0
- package/dist/cjs/components/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/cjs/components/SelectBox/SelectBox.js +305 -0
- package/dist/cjs/components/SelectBox/SelectBox.js.map +1 -0
- package/dist/cjs/components/Skeleton/Skeleton.js +36 -0
- package/dist/cjs/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/cjs/components/StatusPill/StatusPill.js +46 -0
- package/dist/cjs/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js +22 -0
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js.map +1 -0
- package/dist/cjs/components/SwipeableRow/SwipeableRow.js +187 -0
- package/dist/cjs/components/SwipeableRow/SwipeableRow.js.map +1 -0
- package/dist/cjs/components/SwipeableTabs/SwipeableTabs.js +91 -0
- package/dist/cjs/components/SwipeableTabs/SwipeableTabs.js.map +1 -0
- package/dist/cjs/components/Table/Table.js +57 -0
- package/dist/cjs/components/Table/Table.js.map +1 -0
- package/dist/cjs/components/Tabs/Tabs.js +53 -0
- package/dist/cjs/components/Tabs/Tabs.js.map +1 -0
- package/dist/cjs/components/TextContent/TextContent.js +47 -0
- package/dist/cjs/components/TextContent/TextContent.js.map +1 -0
- package/dist/cjs/components/Textarea/Textarea.js +64 -0
- package/dist/cjs/components/Textarea/Textarea.js.map +1 -0
- package/dist/cjs/components/Toast/Toast.js +96 -0
- package/dist/cjs/components/Toast/Toast.js.map +1 -0
- package/dist/cjs/components/Toast/ToastProvider.js +151 -0
- package/dist/cjs/components/Toast/ToastProvider.js.map +1 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedDataTable.js +122 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedDataTable.js.map +1 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedRow.js +48 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedRow.js.map +1 -0
- package/dist/cjs/components/WheelPicker/WheelPicker.js +82 -0
- package/dist/cjs/components/WheelPicker/WheelPicker.js.map +1 -0
- package/dist/cjs/components/common-responsive.js +310 -0
- package/dist/cjs/components/common-responsive.js.map +1 -0
- package/dist/cjs/hooks/use-debounce.js +31 -0
- package/dist/cjs/hooks/use-debounce.js.map +1 -0
- package/dist/cjs/hooks/use-is-mobile.js +24 -0
- package/dist/cjs/hooks/use-is-mobile.js.map +1 -0
- package/dist/cjs/hooks/use-is-tablet-or-mobile.js +13 -0
- package/dist/cjs/hooks/use-is-tablet-or-mobile.js.map +1 -0
- package/dist/cjs/hooks/use-is-tablet.js +21 -0
- package/dist/cjs/hooks/use-is-tablet.js.map +1 -0
- package/dist/cjs/index.js +163 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/react-tailwind.css +2 -0
- package/dist/cjs/react-tailwind.css.map +1 -0
- package/dist/cjs/utils/build-classname.js +8 -0
- package/dist/cjs/utils/build-classname.js.map +1 -0
- package/dist/cjs/utils/get.js +20 -0
- package/dist/cjs/utils/get.js.map +1 -0
- package/dist/cjs/utils/is-array.js +12 -0
- package/dist/cjs/utils/is-array.js.map +1 -0
- package/dist/cjs/utils/is-empty.js +26 -0
- package/dist/cjs/utils/is-empty.js.map +1 -0
- package/dist/es/components/Accordion/Accordion.js +59 -0
- package/dist/es/components/Accordion/Accordion.js.map +1 -0
- package/dist/es/components/ActionSheet/ActionSheet.js +36 -0
- package/dist/es/components/ActionSheet/ActionSheet.js.map +1 -0
- package/dist/es/components/Alert/Alert.js +32 -0
- package/dist/es/components/Alert/Alert.js.map +1 -0
- package/dist/es/components/Badge/Badge.js +31 -0
- package/dist/es/components/Badge/Badge.js.map +1 -0
- package/dist/es/components/Banner/Banner.js +39 -0
- package/dist/es/components/Banner/Banner.js.map +1 -0
- package/dist/es/components/BodyText/BodyText.js +57 -0
- package/dist/es/components/BodyText/BodyText.js.map +1 -0
- package/dist/es/components/BottomNavigation/BottomNavigation.js +50 -0
- package/dist/es/components/BottomNavigation/BottomNavigation.js.map +1 -0
- package/dist/es/components/Breadcrumb/Breadcrumb.js +61 -0
- package/dist/es/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/es/components/Button/Button.js +116 -0
- package/dist/es/components/Button/Button.js.map +1 -0
- package/dist/es/components/ButtonGroup/ButtonGroup.js +98 -0
- package/dist/es/components/ButtonGroup/ButtonGroup.js.map +1 -0
- package/dist/es/components/Card/Card.js +57 -0
- package/dist/es/components/Card/Card.js.map +1 -0
- package/dist/es/components/Checkbox/Checkbox.js +62 -0
- package/dist/es/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/es/components/CheckboxGroup/CheckboxGroup.js +80 -0
- package/dist/es/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
- package/dist/es/components/DataList/DataList.js +285 -0
- package/dist/es/components/DataList/DataList.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.icons.js +17 -0
- package/dist/es/components/DataTable/DataTable.icons.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.js +108 -0
- package/dist/es/components/DataTable/DataTable.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.utils.js +83 -0
- package/dist/es/components/DataTable/DataTable.utils.js.map +1 -0
- package/dist/es/components/DetailedInformation/DetailedInformation.js +65 -0
- package/dist/es/components/DetailedInformation/DetailedInformation.js.map +1 -0
- package/dist/es/components/Dot/index.js +10 -0
- package/dist/es/components/Dot/index.js.map +1 -0
- package/dist/es/components/Drawer/Drawer.js +65 -0
- package/dist/es/components/Drawer/Drawer.js.map +1 -0
- package/dist/es/components/Dropdown/Dropdown.js +48 -0
- package/dist/es/components/Dropdown/Dropdown.js.map +1 -0
- package/dist/es/components/EmptyState/index.js +12 -0
- package/dist/es/components/EmptyState/index.js.map +1 -0
- package/dist/es/components/Flex/Flex.js +22 -0
- package/dist/es/components/Flex/Flex.js.map +1 -0
- package/dist/es/components/FloatingActionButton/FloatingActionButton.js +69 -0
- package/dist/es/components/FloatingActionButton/FloatingActionButton.js.map +1 -0
- package/dist/es/components/Grid/Grid.js +30 -0
- package/dist/es/components/Grid/Grid.js.map +1 -0
- package/dist/es/components/HeadingText/HeadingText.js +87 -0
- package/dist/es/components/HeadingText/HeadingText.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownAZ.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownAZ.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownNarrowWide.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownNarrowWide.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownWideNarrow.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownWideNarrow.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownZA.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownZA.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowUpDown.svg.js +23 -0
- package/dist/es/components/Icons/ArrowUpDown.svg.js.map +1 -0
- package/dist/es/components/Icons/BadgeCheck.svg.js +25 -0
- package/dist/es/components/Icons/BadgeCheck.svg.js.map +1 -0
- package/dist/es/components/Icons/Check.svg.js +23 -0
- package/dist/es/components/Icons/Check.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronDown.svg.js +23 -0
- package/dist/es/components/Icons/ChevronDown.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronLeft.svg.js +23 -0
- package/dist/es/components/Icons/ChevronLeft.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronRight.svg.js +23 -0
- package/dist/es/components/Icons/ChevronRight.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleAlert.svg.js +27 -0
- package/dist/es/components/Icons/CircleAlert.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleCheck.svg.js +27 -0
- package/dist/es/components/Icons/CircleCheck.svg.js.map +1 -0
- package/dist/es/components/Icons/CirclePlus.svg.js +27 -0
- package/dist/es/components/Icons/CirclePlus.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleX.svg.js +27 -0
- package/dist/es/components/Icons/CircleX.svg.js.map +1 -0
- package/dist/es/components/Icons/FolderPlus.svg.js +23 -0
- package/dist/es/components/Icons/FolderPlus.svg.js.map +1 -0
- package/dist/es/components/Icons/Info.svg.js +27 -0
- package/dist/es/components/Icons/Info.svg.js.map +1 -0
- package/dist/es/components/Icons/Search.svg.js +27 -0
- package/dist/es/components/Icons/Search.svg.js.map +1 -0
- package/dist/es/components/Icons/Slash.svg.js +23 -0
- package/dist/es/components/Icons/Slash.svg.js.map +1 -0
- package/dist/es/components/Icons/TriangleAlert.svg.js +23 -0
- package/dist/es/components/Icons/TriangleAlert.svg.js.map +1 -0
- package/dist/es/components/Icons/X.svg.js +23 -0
- package/dist/es/components/Icons/X.svg.js.map +1 -0
- package/dist/es/components/Input/Input.js +82 -0
- package/dist/es/components/Input/Input.js.map +1 -0
- package/dist/es/components/Label/Label.js +12 -0
- package/dist/es/components/Label/Label.js.map +1 -0
- package/dist/es/components/Loader/index.js +16 -0
- package/dist/es/components/Loader/index.js.map +1 -0
- package/dist/es/components/MobileHeader/MobileHeader.js +43 -0
- package/dist/es/components/MobileHeader/MobileHeader.js.map +1 -0
- package/dist/es/components/MobilePicker/MobilePicker.js +366 -0
- package/dist/es/components/MobilePicker/MobilePicker.js.map +1 -0
- package/dist/es/components/MobileStepper/MobileStepper.js +31 -0
- package/dist/es/components/MobileStepper/MobileStepper.js.map +1 -0
- package/dist/es/components/Pagination/Pagination.js +31 -0
- package/dist/es/components/Pagination/Pagination.js.map +1 -0
- package/dist/es/components/Pagination/usePagination.js +30 -0
- package/dist/es/components/Pagination/usePagination.js.map +1 -0
- package/dist/es/components/PasswordInput/PasswordInput.js +51 -0
- package/dist/es/components/PasswordInput/PasswordInput.js.map +1 -0
- package/dist/es/components/PinInput/PinInput.js +96 -0
- package/dist/es/components/PinInput/PinInput.js.map +1 -0
- package/dist/es/components/PullToRefresh/PullToRefresh.js +81 -0
- package/dist/es/components/PullToRefresh/PullToRefresh.js.map +1 -0
- package/dist/es/components/QuantityStepper/QuantityStepper.js +75 -0
- package/dist/es/components/QuantityStepper/QuantityStepper.js.map +1 -0
- package/dist/es/components/Radio/Radio.js +32 -0
- package/dist/es/components/Radio/Radio.js.map +1 -0
- package/dist/es/components/RadioGroup/RadioGroup.js +48 -0
- package/dist/es/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/es/components/RadioSwitch/RadioSwitch.js +114 -0
- package/dist/es/components/RadioSwitch/RadioSwitch.js.map +1 -0
- package/dist/es/components/RangeInput/RangeInput.js +64 -0
- package/dist/es/components/RangeInput/RangeInput.js.map +1 -0
- package/dist/es/components/RangeSlider/RangeSlider.js +165 -0
- package/dist/es/components/RangeSlider/RangeSlider.js.map +1 -0
- package/dist/es/components/SegmentedControl/SegmentedControl.js +62 -0
- package/dist/es/components/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/es/components/SelectBox/SelectBox.js +303 -0
- package/dist/es/components/SelectBox/SelectBox.js.map +1 -0
- package/dist/es/components/Skeleton/Skeleton.js +34 -0
- package/dist/es/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/es/components/StatusPill/StatusPill.js +44 -0
- package/dist/es/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/es/components/StickyActionBar/StickyActionBar.js +20 -0
- package/dist/es/components/StickyActionBar/StickyActionBar.js.map +1 -0
- package/dist/es/components/SwipeableRow/SwipeableRow.js +185 -0
- package/dist/es/components/SwipeableRow/SwipeableRow.js.map +1 -0
- package/dist/es/components/SwipeableTabs/SwipeableTabs.js +89 -0
- package/dist/es/components/SwipeableTabs/SwipeableTabs.js.map +1 -0
- package/dist/es/components/Table/Table.js +48 -0
- package/dist/es/components/Table/Table.js.map +1 -0
- package/dist/es/components/Tabs/Tabs.js +51 -0
- package/dist/es/components/Tabs/Tabs.js.map +1 -0
- package/dist/es/components/TextContent/TextContent.js +45 -0
- package/dist/es/components/TextContent/TextContent.js.map +1 -0
- package/dist/es/components/Textarea/Textarea.js +62 -0
- package/dist/es/components/Textarea/Textarea.js.map +1 -0
- package/dist/es/components/Toast/Toast.js +94 -0
- package/dist/es/components/Toast/Toast.js.map +1 -0
- package/dist/es/components/Toast/ToastProvider.js +148 -0
- package/dist/es/components/Toast/ToastProvider.js.map +1 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedDataTable.js +120 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedDataTable.js.map +1 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedRow.js +46 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedRow.js.map +1 -0
- package/dist/es/components/WheelPicker/WheelPicker.js +80 -0
- package/dist/es/components/WheelPicker/WheelPicker.js.map +1 -0
- package/dist/es/components/common-responsive.js +287 -0
- package/dist/es/components/common-responsive.js.map +1 -0
- package/dist/es/hooks/use-debounce.js +28 -0
- package/dist/es/hooks/use-debounce.js.map +1 -0
- package/dist/es/hooks/use-is-mobile.js +22 -0
- package/dist/es/hooks/use-is-mobile.js.map +1 -0
- package/dist/es/hooks/use-is-tablet-or-mobile.js +11 -0
- package/dist/es/hooks/use-is-tablet-or-mobile.js.map +1 -0
- package/dist/es/hooks/use-is-tablet.js +19 -0
- package/dist/es/hooks/use-is-tablet.js.map +1 -0
- package/dist/es/index.js +67 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react-tailwind.css +2 -0
- package/dist/es/react-tailwind.css.map +1 -0
- package/dist/es/utils/build-classname.js +6 -0
- package/dist/es/utils/build-classname.js.map +1 -0
- package/dist/es/utils/get.js +18 -0
- package/dist/es/utils/get.js.map +1 -0
- package/dist/es/utils/is-array.js +10 -0
- package/dist/es/utils/is-array.js.map +1 -0
- package/dist/es/utils/is-empty.js +24 -0
- package/dist/es/utils/is-empty.js.map +1 -0
- package/dist/react-tailwind.cjs.js +2298 -472
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +2284 -474
- package/dist/react-tailwind.es.js.map +1 -1
- package/dist/types/components/ActionSheet/ActionSheet.d.ts +5 -0
- package/dist/types/components/ActionSheet/ActionSheet.test.d.ts +1 -0
- package/dist/types/components/ActionSheet/ActionSheet.types.d.ts +44 -0
- package/dist/types/components/ActionSheet/index.d.ts +2 -0
- package/dist/types/components/Badge/Badge.types.d.ts +1 -1
- package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +5 -0
- package/dist/types/components/BottomNavigation/BottomNavigation.test.d.ts +1 -0
- package/dist/types/components/BottomNavigation/BottomNavigation.types.d.ts +41 -0
- package/dist/types/components/BottomNavigation/index.d.ts +2 -0
- package/dist/types/components/Card/Card.types.d.ts +25 -0
- package/dist/types/components/DataList/DataList.d.ts +5 -0
- package/dist/types/components/DataList/DataList.test.d.ts +1 -0
- package/dist/types/components/DataList/DataList.types.d.ts +81 -0
- package/dist/types/components/DataList/index.d.ts +2 -0
- package/dist/types/components/DataTable/DataTable.d.ts +1 -1
- package/dist/types/components/DataTable/DataTable.types.d.ts +10 -0
- package/dist/types/components/Flex/Flex.d.ts +3 -0
- package/dist/types/components/Flex/Flex.test.d.ts +1 -0
- package/dist/types/components/Flex/Flex.types.d.ts +92 -0
- package/dist/types/components/Flex/index.d.ts +2 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.test.d.ts +1 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.types.d.ts +48 -0
- package/dist/types/components/FloatingActionButton/index.d.ts +2 -0
- package/dist/types/components/Grid/Grid.d.ts +3 -0
- package/dist/types/components/Grid/Grid.test.d.ts +1 -0
- package/dist/types/components/Grid/Grid.types.d.ts +136 -0
- package/dist/types/components/Grid/index.d.ts +2 -0
- package/dist/types/components/Input/Input.types.d.ts +3 -3
- package/dist/types/components/MobileHeader/MobileHeader.d.ts +5 -0
- package/dist/types/components/MobileHeader/MobileHeader.test.d.ts +1 -0
- package/dist/types/components/MobileHeader/MobileHeader.types.d.ts +49 -0
- package/dist/types/components/MobileHeader/index.d.ts +2 -0
- package/dist/types/components/MobilePicker/MobilePicker.d.ts +6 -0
- package/dist/types/components/MobilePicker/MobilePicker.test.d.ts +1 -0
- package/dist/types/components/MobilePicker/MobilePicker.types.d.ts +90 -0
- package/dist/types/components/MobilePicker/index.d.ts +2 -0
- package/dist/types/components/MobileStepper/MobileStepper.d.ts +5 -0
- package/dist/types/components/MobileStepper/MobileStepper.test.d.ts +1 -0
- package/dist/types/components/MobileStepper/MobileStepper.types.d.ts +28 -0
- package/dist/types/components/MobileStepper/index.d.ts +2 -0
- package/dist/types/components/PinInput/PinInput.d.ts +5 -0
- package/dist/types/components/PinInput/PinInput.test.d.ts +1 -0
- package/dist/types/components/PinInput/PinInput.types.d.ts +29 -0
- package/dist/types/components/PinInput/index.d.ts +2 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.d.ts +5 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.test.d.ts +1 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.types.d.ts +23 -0
- package/dist/types/components/PullToRefresh/index.d.ts +2 -0
- package/dist/types/components/QuantityStepper/QuantityStepper.types.d.ts +18 -1
- package/dist/types/components/SelectBox/SelectBox.types.d.ts +9 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.d.ts +3 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.test.d.ts +1 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.types.d.ts +42 -0
- package/dist/types/components/SwipeableRow/index.d.ts +2 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.d.ts +5 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.test.d.ts +1 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.types.d.ts +38 -0
- package/dist/types/components/SwipeableTabs/index.d.ts +2 -0
- package/dist/types/components/WheelPicker/WheelPicker.d.ts +5 -0
- package/dist/types/components/WheelPicker/WheelPicker.test.d.ts +1 -0
- package/dist/types/components/WheelPicker/WheelPicker.types.d.ts +35 -0
- package/dist/types/components/WheelPicker/index.d.ts +2 -0
- package/dist/types/components/common-responsive.d.ts +57 -0
- package/dist/types/index.d.ts +14 -0
- package/package.json +11 -3
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React__default, { forwardRef } from 'react';
|
|
2
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
3
|
+
|
|
4
|
+
const sizeClassMap = {
|
|
5
|
+
xs: 'text-xs/5',
|
|
6
|
+
sm: 'text-sm/6',
|
|
7
|
+
md: 'text-base/7',
|
|
8
|
+
lg: 'text-lg/8',
|
|
9
|
+
xl: 'text-xl/9',
|
|
10
|
+
};
|
|
11
|
+
const weightClassMap = {
|
|
12
|
+
light: 'font-light',
|
|
13
|
+
normal: 'font-normal',
|
|
14
|
+
medium: 'font-medium',
|
|
15
|
+
semibold: 'font-semibold',
|
|
16
|
+
bold: 'font-bold',
|
|
17
|
+
};
|
|
18
|
+
const alignClassMap = {
|
|
19
|
+
left: 'text-left',
|
|
20
|
+
center: 'text-center',
|
|
21
|
+
right: 'text-right',
|
|
22
|
+
justify: 'text-justify',
|
|
23
|
+
};
|
|
24
|
+
const clampClassMap = {
|
|
25
|
+
1: 'line-clamp-1',
|
|
26
|
+
2: 'line-clamp-2',
|
|
27
|
+
3: 'line-clamp-3',
|
|
28
|
+
4: 'line-clamp-4',
|
|
29
|
+
};
|
|
30
|
+
const BodyText = forwardRef((props, ref) => {
|
|
31
|
+
const { as = 'p', size, weight, small = false, strong = false, muted = false, error = false, success = false, warning = false, info = false, inline = false, invert = false, align, truncate = false, clamp, className, children, ...rest } = props;
|
|
32
|
+
const textColorClass = error
|
|
33
|
+
? 'text-[var(--ui-text-danger)]'
|
|
34
|
+
: success
|
|
35
|
+
? 'text-[var(--ui-success)]'
|
|
36
|
+
: warning
|
|
37
|
+
? 'text-[var(--ui-warning)]'
|
|
38
|
+
: info
|
|
39
|
+
? 'text-[var(--ui-info)]'
|
|
40
|
+
: muted
|
|
41
|
+
? invert
|
|
42
|
+
? 'text-gray-300 dark:text-gray-600'
|
|
43
|
+
: 'text-[var(--ui-text-muted)]'
|
|
44
|
+
: invert
|
|
45
|
+
? 'text-white dark:text-black'
|
|
46
|
+
: 'text-[var(--ui-text)]';
|
|
47
|
+
return React__default.createElement(as, {
|
|
48
|
+
ref,
|
|
49
|
+
className: buildClassName(textColorClass, size ? sizeClassMap[size] : small && 'text-sm/6', weight ? weightClassMap[weight] : strong && 'font-semibold', align && alignClassMap[align], inline && 'inline-flex items-center gap-2', truncate && 'truncate', clamp && clampClassMap[clamp], className),
|
|
50
|
+
...rest,
|
|
51
|
+
children,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
BodyText.displayName = 'BodyText';
|
|
55
|
+
|
|
56
|
+
export { BodyText };
|
|
57
|
+
//# sourceMappingURL=BodyText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BodyText.js","sources":["../../../../../src/components/BodyText/BodyText.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport type { BodyTextAlign, BodyTextProps, BodyTextSize, BodyTextWeight } from './BodyText.types'\n\nconst sizeClassMap: Record<BodyTextSize, string> = {\n xs: 'text-xs/5',\n sm: 'text-sm/6',\n md: 'text-base/7',\n lg: 'text-lg/8',\n xl: 'text-xl/9',\n}\n\nconst weightClassMap: Record<BodyTextWeight, string> = {\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n}\n\nconst alignClassMap: Record<BodyTextAlign, string> = {\n left: 'text-left',\n center: 'text-center',\n right: 'text-right',\n justify: 'text-justify',\n}\n\nconst clampClassMap = {\n 1: 'line-clamp-1',\n 2: 'line-clamp-2',\n 3: 'line-clamp-3',\n 4: 'line-clamp-4',\n}\n\nexport const BodyText = forwardRef<HTMLParagraphElement, BodyTextProps>((props, ref) => {\n const {\n as = 'p',\n size,\n weight,\n small = false,\n strong = false,\n muted = false,\n error = false,\n success = false,\n warning = false,\n info = false,\n inline = false,\n invert = false,\n align,\n truncate = false,\n clamp,\n className,\n children,\n ...rest\n } = props\n\n const textColorClass = error\n ? 'text-[var(--ui-text-danger)]'\n : success\n ? 'text-[var(--ui-success)]'\n : warning\n ? 'text-[var(--ui-warning)]'\n : info\n ? 'text-[var(--ui-info)]'\n : muted\n ? invert\n ? 'text-gray-300 dark:text-gray-600'\n : 'text-[var(--ui-text-muted)]'\n : invert\n ? 'text-white dark:text-black'\n : 'text-[var(--ui-text)]'\n\n return React.createElement(as, {\n ref,\n className: buildClassName(\n textColorClass,\n size ? sizeClassMap[size] : small && 'text-sm/6',\n weight ? weightClassMap[weight] : strong && 'font-semibold',\n align && alignClassMap[align],\n inline && 'inline-flex items-center gap-2',\n truncate && 'truncate',\n clamp && clampClassMap[clamp],\n className,\n ),\n ...rest,\n children,\n })\n})\n\nBodyText.displayName = 'BodyText'\n"],"names":["React"],"mappings":";;;AAIA,MAAM,YAAY,GAAiC;AACjD,IAAA,EAAE,EAAE,WAAW;AACf,IAAA,EAAE,EAAE,WAAW;AACf,IAAA,EAAE,EAAE,aAAa;AACjB,IAAA,EAAE,EAAE,WAAW;AACf,IAAA,EAAE,EAAE,WAAW;CAChB;AAED,MAAM,cAAc,GAAmC;AACrD,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,MAAM,EAAE,aAAa;AACrB,IAAA,MAAM,EAAE,aAAa;AACrB,IAAA,QAAQ,EAAE,eAAe;AACzB,IAAA,IAAI,EAAE,WAAW;CAClB;AAED,MAAM,aAAa,GAAkC;AACnD,IAAA,IAAI,EAAE,WAAW;AACjB,IAAA,MAAM,EAAE,aAAa;AACrB,IAAA,KAAK,EAAE,YAAY;AACnB,IAAA,OAAO,EAAE,cAAc;CACxB;AAED,MAAM,aAAa,GAAG;AACpB,IAAA,CAAC,EAAE,cAAc;AACjB,IAAA,CAAC,EAAE,cAAc;AACjB,IAAA,CAAC,EAAE,cAAc;AACjB,IAAA,CAAC,EAAE,cAAc;CAClB;AAEM,MAAM,QAAQ,GAAG,UAAU,CAAsC,CAAC,KAAK,EAAE,GAAG,KAAI;AACrF,IAAA,MAAM,EACJ,EAAE,GAAG,GAAG,EACR,IAAI,EACJ,MAAM,EACN,KAAK,GAAG,KAAK,EACb,MAAM,GAAG,KAAK,EACd,KAAK,GAAG,KAAK,EACb,KAAK,GAAG,KAAK,EACb,OAAO,GAAG,KAAK,EACf,OAAO,GAAG,KAAK,EACf,IAAI,GAAG,KAAK,EACZ,MAAM,GAAG,KAAK,EACd,MAAM,GAAG,KAAK,EACd,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,KAAK,EACL,SAAS,EACT,QAAQ,EACR,GAAG,IAAI,EACR,GAAG,KAAK;IAET,MAAM,cAAc,GAAG;AACrB,UAAE;AACF,UAAE;AACA,cAAE;AACF,cAAE;AACA,kBAAE;AACF,kBAAE;AACA,sBAAE;AACF,sBAAE;AACA,0BAAE;AACA,8BAAE;AACF,8BAAE;AACJ,0BAAE;AACA,8BAAE;8BACA,uBAAuB;AAErC,IAAA,OAAOA,cAAK,CAAC,aAAa,CAAC,EAAE,EAAE;QAC7B,GAAG;QACH,SAAS,EAAE,cAAc,CACvB,cAAc,EACd,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,WAAW,EAChD,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,eAAe,EAC3D,KAAK,IAAI,aAAa,CAAC,KAAK,CAAC,EAC7B,MAAM,IAAI,gCAAgC,EAC1C,QAAQ,IAAI,UAAU,EACtB,KAAK,IAAI,aAAa,CAAC,KAAK,CAAC,EAC7B,SAAS,CACV;AACD,QAAA,GAAG,IAAI;QACP,QAAQ;AACT,KAAA,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,WAAW,GAAG,UAAU;;;;"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
3
|
+
|
|
4
|
+
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
|
|
5
|
+
const handleTabClick = (item) => {
|
|
6
|
+
var _a;
|
|
7
|
+
if (item.disabled)
|
|
8
|
+
return;
|
|
9
|
+
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
10
|
+
onChange(item.id);
|
|
11
|
+
};
|
|
12
|
+
const themeStyles = {
|
|
13
|
+
light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
|
|
14
|
+
dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
|
|
15
|
+
primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
|
|
16
|
+
}[theme];
|
|
17
|
+
return (jsx("nav", { "aria-label": "Bottom Navigation", className: buildClassName('w-full flex items-center justify-around select-none shadow-lg transition-colors relative', fixed && 'fixed bottom-0 left-0 right-0 z-40', 'pb-[env(safe-area-inset-bottom,6px)] px-2', themeStyles, containerClass), "data-testid": "bottom-navigation", children: items.map((item) => {
|
|
18
|
+
const isActive = item.id === activeId;
|
|
19
|
+
const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
|
|
20
|
+
const activeItemColor = {
|
|
21
|
+
light: 'text-blue-600 dark:text-blue-400 font-bold',
|
|
22
|
+
dark: 'text-white font-bold',
|
|
23
|
+
primary: 'text-white font-bold',
|
|
24
|
+
}[theme];
|
|
25
|
+
const inactiveItemColor = {
|
|
26
|
+
light: 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',
|
|
27
|
+
dark: 'text-gray-400 hover:text-gray-200 font-medium',
|
|
28
|
+
primary: 'text-blue-200 hover:text-white font-medium',
|
|
29
|
+
}[theme];
|
|
30
|
+
const pillActiveStyles = {
|
|
31
|
+
light: 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',
|
|
32
|
+
dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',
|
|
33
|
+
primary: 'bg-white/25 text-white shadow-xs scale-105',
|
|
34
|
+
}[theme];
|
|
35
|
+
const badgeColor = {
|
|
36
|
+
danger: 'bg-red-500 text-white',
|
|
37
|
+
info: 'bg-blue-500 text-white',
|
|
38
|
+
success: 'bg-emerald-500 text-white',
|
|
39
|
+
}[item.badgeVariant || 'danger'];
|
|
40
|
+
return (jsxs("button", { type: "button", disabled: item.disabled, onClick: () => handleTabClick(item), className: buildClassName('flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive ? activeItemColor : inactiveItemColor, itemClass), "data-testid": `bottom-nav-item-${item.id}`, "aria-selected": isActive, children: [activeIndicatorStyle === 'line' && isActive && (jsx("span", { className: buildClassName('absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') })), jsxs("div", { className: buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
|
|
41
|
+
? buildClassName('px-4 py-1 rounded-full', isActive
|
|
42
|
+
? pillActiveStyles
|
|
43
|
+
: 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
|
|
44
|
+
: 'px-1 py-0.5'), children: [jsx("span", { className: "text-xl transition-transform duration-150 group-active:scale-95", children: isActive && item.activeIcon ? item.activeIcon : item.icon }), item.badge !== undefined && item.badge !== null && (jsx("span", { className: buildClassName('absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10', badgeColor), "data-testid": `bottom-nav-badge-${item.id}`, children: item.badge }))] }), showLabelText && (jsx("span", { className: buildClassName('text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150', isActive ? 'font-bold' : 'font-medium opacity-90'), children: item.label })), activeIndicatorStyle === 'dot' && isActive && (jsx("span", { className: buildClassName('size-1.5 rounded-full mt-1 transition-all duration-200', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') }))] }, item.id));
|
|
45
|
+
}) }));
|
|
46
|
+
}
|
|
47
|
+
BottomNavigation.displayName = 'BottomNavigation';
|
|
48
|
+
|
|
49
|
+
export { BottomNavigation };
|
|
50
|
+
//# sourceMappingURL=BottomNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BottomNavigation.js","sources":["../../../../../src/components/BottomNavigation/BottomNavigation.tsx"],"sourcesContent":["import React from 'react'\nimport type { BottomNavigationProps, BottomNavigationItem } from './BottomNavigation.types'\nimport { buildClassName } from '../../utils/build-classname'\n\nexport function BottomNavigation({\n items,\n activeId,\n onChange,\n fixed = true,\n showLabels = 'always',\n theme = 'light',\n activeIndicatorStyle = 'line',\n containerClass = '',\n itemClass = '',\n}: BottomNavigationProps) {\n const handleTabClick = (item: BottomNavigationItem) => {\n if (item.disabled) return\n item.onClick?.()\n onChange(item.id)\n }\n\n const themeStyles = {\n light:\n 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',\n dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',\n primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',\n }[theme]\n\n return (\n <nav\n aria-label=\"Bottom Navigation\"\n className={buildClassName(\n 'w-full flex items-center justify-around select-none shadow-lg transition-colors relative',\n fixed && 'fixed bottom-0 left-0 right-0 z-40',\n 'pb-[env(safe-area-inset-bottom,6px)] px-2',\n themeStyles,\n containerClass,\n )}\n data-testid=\"bottom-navigation\"\n >\n {items.map((item) => {\n const isActive = item.id === activeId\n const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive)\n\n const activeItemColor = {\n light: 'text-blue-600 dark:text-blue-400 font-bold',\n dark: 'text-white font-bold',\n primary: 'text-white font-bold',\n }[theme]\n\n const inactiveItemColor = {\n light:\n 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',\n dark: 'text-gray-400 hover:text-gray-200 font-medium',\n primary: 'text-blue-200 hover:text-white font-medium',\n }[theme]\n\n const pillActiveStyles = {\n light:\n 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',\n dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',\n primary: 'bg-white/25 text-white shadow-xs scale-105',\n }[theme]\n\n const badgeColor = {\n danger: 'bg-red-500 text-white',\n info: 'bg-blue-500 text-white',\n success: 'bg-emerald-500 text-white',\n }[item.badgeVariant || 'danger']\n\n return (\n <button\n key={item.id}\n type=\"button\"\n disabled={item.disabled}\n onClick={() => handleTabClick(item)}\n className={buildClassName(\n 'flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group',\n item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none',\n isActive ? activeItemColor : inactiveItemColor,\n itemClass,\n )}\n data-testid={`bottom-nav-item-${item.id}`}\n aria-selected={isActive}\n >\n {/* Active Indicator Bar on Top Border */}\n {activeIndicatorStyle === 'line' && isActive && (\n <span\n className={buildClassName(\n 'absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n\n {/* Icon & Badge Container */}\n <div\n className={buildClassName(\n 'relative inline-flex items-center justify-center transition-all duration-200',\n activeIndicatorStyle === 'pill'\n ? buildClassName(\n 'px-4 py-1 rounded-full',\n isActive\n ? pillActiveStyles\n : 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40',\n )\n : 'px-1 py-0.5',\n )}\n >\n <span className=\"text-xl transition-transform duration-150 group-active:scale-95\">\n {isActive && item.activeIcon ? item.activeIcon : item.icon}\n </span>\n\n {/* Notification Badge */}\n {item.badge !== undefined && item.badge !== null && (\n <span\n className={buildClassName(\n 'absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10',\n badgeColor,\n )}\n data-testid={`bottom-nav-badge-${item.id}`}\n >\n {item.badge}\n </span>\n )}\n </div>\n\n {/* Label */}\n {showLabelText && (\n <span\n className={buildClassName(\n 'text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150',\n isActive ? 'font-bold' : 'font-medium opacity-90',\n )}\n >\n {item.label}\n </span>\n )}\n\n {/* Active Dot Indicator */}\n {activeIndicatorStyle === 'dot' && isActive && (\n <span\n className={buildClassName(\n 'size-1.5 rounded-full mt-1 transition-all duration-200',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n </button>\n )\n })}\n </nav>\n )\n}\n\nBottomNavigation.displayName = 'BottomNavigation'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useState } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
import SvgSlash from '../Icons/Slash.svg.js';
|
|
5
|
+
|
|
6
|
+
const SIZE_CONTAINER_CLASS = {
|
|
7
|
+
sm: 'text-xs gap-1.5',
|
|
8
|
+
md: 'text-sm gap-2',
|
|
9
|
+
lg: 'text-base gap-2.5',
|
|
10
|
+
};
|
|
11
|
+
const SIZE_ICON_CLASS = {
|
|
12
|
+
sm: 'size-3',
|
|
13
|
+
md: 'size-3.5',
|
|
14
|
+
lg: 'size-4',
|
|
15
|
+
};
|
|
16
|
+
function RenderSeparator({ separator, size, index, className, }) {
|
|
17
|
+
const testId = `breadcrumb-divider-${index}`;
|
|
18
|
+
if (separator === 'slash' || !separator) {
|
|
19
|
+
return (jsx(SvgSlash, { "data-testid": testId, className: buildClassName(SIZE_ICON_CLASS[size] || 'size-3.5', 'text-gray-400 dark:text-gray-500 shrink-0 select-none', className) }));
|
|
20
|
+
}
|
|
21
|
+
if (separator === 'chevron') {
|
|
22
|
+
return (jsx("svg", { "data-testid": testId, className: buildClassName(SIZE_ICON_CLASS[size] || 'size-3.5', 'text-gray-400 dark:text-gray-500 shrink-0 select-none', className), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 5l7 7-7 7" }) }));
|
|
23
|
+
}
|
|
24
|
+
if (separator === 'dot') {
|
|
25
|
+
return (jsx("span", { "data-testid": testId, className: buildClassName('size-1 rounded-full bg-gray-400 dark:bg-gray-500 shrink-0 select-none mx-0.5', className) }));
|
|
26
|
+
}
|
|
27
|
+
return (jsx("span", { "data-testid": testId, className: buildClassName('shrink-0 select-none', className), children: separator }));
|
|
28
|
+
}
|
|
29
|
+
const Breadcrumb = forwardRef((props, ref) => {
|
|
30
|
+
const { items = [], render, separator = 'slash', size = 'md', maxItems, className, itemClass, activeItemClass, separatorClass, ...navProps } = props;
|
|
31
|
+
const [expanded, setExpanded] = useState(false);
|
|
32
|
+
const count = items.length;
|
|
33
|
+
const shouldTruncate = maxItems !== undefined && maxItems > 1 && count > maxItems && !expanded;
|
|
34
|
+
const getVisibleItems = () => {
|
|
35
|
+
if (!shouldTruncate)
|
|
36
|
+
return items;
|
|
37
|
+
// Always keep 1st item and last 1-2 items
|
|
38
|
+
const firstItem = items[0];
|
|
39
|
+
const lastItems = items.slice(count - (maxItems - 1));
|
|
40
|
+
return [firstItem, ...lastItems];
|
|
41
|
+
};
|
|
42
|
+
const hiddenItems = shouldTruncate ? items.slice(1, count - (maxItems - 1)) : [];
|
|
43
|
+
getVisibleItems();
|
|
44
|
+
return (jsx("nav", { ref: ref, "aria-label": "Breadcrumb", "data-testid": "breadcrumb-container", className: buildClassName('flex flex-wrap items-center text-gray-600 dark:text-gray-300 font-medium', SIZE_CONTAINER_CLASS[size] || SIZE_CONTAINER_CLASS.md, className), ...navProps, children: items.map((item, index) => {
|
|
45
|
+
const isLast = index === count - 1;
|
|
46
|
+
const isCollapsedMiddle = shouldTruncate && index > 0 && index < count - (maxItems - 1);
|
|
47
|
+
if (isCollapsedMiddle) {
|
|
48
|
+
if (index === 1) {
|
|
49
|
+
// Render the single '...' collapse pill
|
|
50
|
+
return (jsxs("span", { className: "inline-flex items-center gap-2 relative group/ellipsis", children: [jsx("button", { type: "button", onClick: () => setExpanded(true), className: "px-1.5 py-0.5 rounded-md text-xs font-semibold bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300 transition-colors cursor-pointer", "aria-label": `Expand ${hiddenItems.length} hidden breadcrumbs`, title: `Show ${hiddenItems.length} hidden levels`, children: "\u2022\u2022\u2022" }), jsx(RenderSeparator, { separator: separator, size: size, index: index, className: separatorClass })] }, "breadcrumb-collapsed"));
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const defaultContent = isLast ? (jsx("span", { className: buildClassName('text-gray-900 dark:text-white font-semibold', activeItemClass, item.className), children: item.text })) : item.to ? (jsx("a", { href: item.to, className: buildClassName('hover:text-blue-600 dark:hover:text-blue-400 transition-colors', itemClass, item.className), children: item.text })) : (jsx("span", { className: buildClassName(itemClass, item.className), children: item.text }));
|
|
55
|
+
return (jsxs("span", { className: "inline-flex items-center gap-2", "data-testid": `breadcrumb-item-${item.key}`, children: [jsxs("span", { className: "inline-flex items-center gap-1.5", ...(isLast ? { 'aria-current': 'page' } : {}), children: [item.icon && jsx("span", { className: "shrink-0 text-gray-400", children: item.icon }), isLast ? (defaultContent) : render ? (jsx("span", { className: buildClassName(itemClass, item.className), children: render(item) })) : (defaultContent)] }), !isLast && (jsx(RenderSeparator, { separator: separator, size: size, index: index, className: separatorClass }))] }, item.key));
|
|
56
|
+
}) }));
|
|
57
|
+
});
|
|
58
|
+
Breadcrumb.displayName = 'Breadcrumb';
|
|
59
|
+
|
|
60
|
+
export { Breadcrumb };
|
|
61
|
+
//# sourceMappingURL=Breadcrumb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumb.js","sources":["../../../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["import { forwardRef, useState, type ReactNode } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport SlashIcon from '../Icons/Slash.svg'\nimport type { BreadcrumbItem, BreadcrumbProps } from './Breadcrumb.types'\n\nconst SIZE_CONTAINER_CLASS: Record<string, string> = {\n sm: 'text-xs gap-1.5',\n md: 'text-sm gap-2',\n lg: 'text-base gap-2.5',\n}\n\nconst SIZE_ICON_CLASS: Record<string, string> = {\n sm: 'size-3',\n md: 'size-3.5',\n lg: 'size-4',\n}\n\nfunction RenderSeparator({\n separator,\n size,\n index,\n className,\n}: {\n separator: BreadcrumbProps['separator']\n size: 'sm' | 'md' | 'lg'\n index: number\n className?: string\n}) {\n const testId = `breadcrumb-divider-${index}`\n\n if (separator === 'slash' || !separator) {\n return (\n <SlashIcon\n data-testid={testId}\n className={buildClassName(\n SIZE_ICON_CLASS[size] || 'size-3.5',\n 'text-gray-400 dark:text-gray-500 shrink-0 select-none',\n className,\n )}\n />\n )\n }\n\n if (separator === 'chevron') {\n return (\n <svg\n data-testid={testId}\n className={buildClassName(\n SIZE_ICON_CLASS[size] || 'size-3.5',\n 'text-gray-400 dark:text-gray-500 shrink-0 select-none',\n className,\n )}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n )\n }\n\n if (separator === 'dot') {\n return (\n <span\n data-testid={testId}\n className={buildClassName(\n 'size-1 rounded-full bg-gray-400 dark:bg-gray-500 shrink-0 select-none mx-0.5',\n className,\n )}\n />\n )\n }\n\n return (\n <span data-testid={testId} className={buildClassName('shrink-0 select-none', className)}>\n {separator}\n </span>\n )\n}\n\nexport const Breadcrumb = forwardRef<HTMLElement, BreadcrumbProps>((props, ref) => {\n const {\n items = [],\n render,\n separator = 'slash',\n size = 'md',\n maxItems,\n className,\n itemClass,\n activeItemClass,\n separatorClass,\n ...navProps\n } = props\n\n const [expanded, setExpanded] = useState(false)\n const count = items.length\n const shouldTruncate = maxItems !== undefined && maxItems > 1 && count > maxItems && !expanded\n\n const getVisibleItems = () => {\n if (!shouldTruncate) return items\n // Always keep 1st item and last 1-2 items\n const firstItem = items[0]\n const lastItems = items.slice(count - (maxItems - 1))\n return [firstItem, ...lastItems]\n }\n\n const hiddenItems = shouldTruncate ? items.slice(1, count - (maxItems - 1)) : []\n const visibleItems = getVisibleItems()\n\n return (\n <nav\n ref={ref}\n aria-label=\"Breadcrumb\"\n data-testid=\"breadcrumb-container\"\n className={buildClassName(\n 'flex flex-wrap items-center text-gray-600 dark:text-gray-300 font-medium',\n SIZE_CONTAINER_CLASS[size] || SIZE_CONTAINER_CLASS.md,\n className,\n )}\n {...navProps}\n >\n {items.map((item, index) => {\n const isLast = index === count - 1\n const isCollapsedMiddle = shouldTruncate && index > 0 && index < count - (maxItems - 1)\n\n if (isCollapsedMiddle) {\n if (index === 1) {\n // Render the single '...' collapse pill\n return (\n <span\n key=\"breadcrumb-collapsed\"\n className=\"inline-flex items-center gap-2 relative group/ellipsis\"\n >\n <button\n type=\"button\"\n onClick={() => setExpanded(true)}\n className=\"px-1.5 py-0.5 rounded-md text-xs font-semibold bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300 transition-colors cursor-pointer\"\n aria-label={`Expand ${hiddenItems.length} hidden breadcrumbs`}\n title={`Show ${hiddenItems.length} hidden levels`}\n >\n •••\n </button>\n <RenderSeparator\n separator={separator}\n size={size}\n index={index}\n className={separatorClass}\n />\n </span>\n )\n }\n return null\n }\n\n const defaultContent = isLast ? (\n <span\n className={buildClassName(\n 'text-gray-900 dark:text-white font-semibold',\n activeItemClass,\n item.className,\n )}\n >\n {item.text}\n </span>\n ) : item.to ? (\n <a\n href={item.to}\n className={buildClassName(\n 'hover:text-blue-600 dark:hover:text-blue-400 transition-colors',\n itemClass,\n item.className,\n )}\n >\n {item.text}\n </a>\n ) : (\n <span className={buildClassName(itemClass, item.className)}>{item.text}</span>\n )\n\n return (\n <span\n key={item.key}\n className=\"inline-flex items-center gap-2\"\n data-testid={`breadcrumb-item-${item.key}`}\n >\n <span\n className=\"inline-flex items-center gap-1.5\"\n {...(isLast ? { 'aria-current': 'page' as const } : {})}\n >\n {item.icon && <span className=\"shrink-0 text-gray-400\">{item.icon}</span>}\n {isLast ? (\n defaultContent\n ) : render ? (\n <span className={buildClassName(itemClass, item.className)}>{render(item)}</span>\n ) : (\n defaultContent\n )}\n </span>\n {!isLast && (\n <RenderSeparator\n separator={separator}\n size={size}\n index={index}\n className={separatorClass}\n />\n )}\n </span>\n )\n })}\n </nav>\n )\n})\n\nBreadcrumb.displayName = 'Breadcrumb'\n"],"names":["_jsx","SlashIcon","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useMemo } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
import { Loader } from '../Loader/index.js';
|
|
5
|
+
import { TextContent } from '../TextContent/TextContent.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Tailwind CSS classes for theme + variant combinations.
|
|
9
|
+
*/
|
|
10
|
+
const THEMED_BTN_CLASS = {
|
|
11
|
+
primary: {
|
|
12
|
+
default: 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:bg-[var(--ui-primary-disabled)]',
|
|
13
|
+
outlined: 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)] disabled:border-[var(--ui-primary-disabled)]',
|
|
14
|
+
plain: 'text-[var(--ui-primary-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)]',
|
|
15
|
+
},
|
|
16
|
+
danger: {
|
|
17
|
+
default: 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:bg-[var(--ui-danger-disabled)]',
|
|
18
|
+
outlined: 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)] disabled:border-[var(--ui-danger-disabled)]',
|
|
19
|
+
plain: 'text-[var(--ui-danger-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)]',
|
|
20
|
+
},
|
|
21
|
+
secondary: {
|
|
22
|
+
default: 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:bg-gray-200 dark:disabled:bg-gray-700',
|
|
23
|
+
outlined: 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400 disabled:border-[var(--ui-border-muted)]',
|
|
24
|
+
plain: 'text-gray-700 hover:bg-black/5 dark:text-gray-200 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400',
|
|
25
|
+
},
|
|
26
|
+
success: {
|
|
27
|
+
default: 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:bg-emerald-300 dark:disabled:bg-emerald-900',
|
|
28
|
+
outlined: 'text-emerald-600 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',
|
|
29
|
+
plain: 'text-emerald-600 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',
|
|
30
|
+
},
|
|
31
|
+
warning: {
|
|
32
|
+
default: 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:bg-amber-300 dark:disabled:bg-amber-900',
|
|
33
|
+
outlined: 'text-amber-600 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',
|
|
34
|
+
plain: 'text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
const LOADER_TEXT_CLASS = {
|
|
38
|
+
primary: {
|
|
39
|
+
default: 'text-white',
|
|
40
|
+
outlined: 'text-[var(--ui-primary-text)]',
|
|
41
|
+
plain: 'text-[var(--ui-primary-text)]',
|
|
42
|
+
},
|
|
43
|
+
danger: {
|
|
44
|
+
default: 'text-white',
|
|
45
|
+
outlined: 'text-[var(--ui-danger-text)]',
|
|
46
|
+
plain: 'text-[var(--ui-danger-text)]',
|
|
47
|
+
},
|
|
48
|
+
secondary: {
|
|
49
|
+
default: 'text-gray-700 dark:text-white',
|
|
50
|
+
outlined: 'text-gray-700 dark:text-gray-200',
|
|
51
|
+
plain: 'text-gray-700 dark:text-gray-200',
|
|
52
|
+
},
|
|
53
|
+
success: {
|
|
54
|
+
default: 'text-white',
|
|
55
|
+
outlined: 'text-emerald-600 dark:text-emerald-400',
|
|
56
|
+
plain: 'text-emerald-600 dark:text-emerald-400',
|
|
57
|
+
},
|
|
58
|
+
warning: {
|
|
59
|
+
default: 'text-white',
|
|
60
|
+
outlined: 'text-amber-600 dark:text-amber-400',
|
|
61
|
+
plain: 'text-amber-600 dark:text-amber-400',
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Generate size classes.
|
|
66
|
+
*/
|
|
67
|
+
const getBtnSizeClasses = (size, iconOnly = false) => {
|
|
68
|
+
switch (size) {
|
|
69
|
+
case 'xs':
|
|
70
|
+
return iconOnly ? 'h-7 w-7 p-1 rounded-sm text-xs' : 'h-7 px-2.5 rounded-sm gap-1 text-xs';
|
|
71
|
+
case 'sm':
|
|
72
|
+
return iconOnly ? 'h-8 w-8 p-1.5 rounded text-sm' : 'h-8 px-3 rounded gap-1.5 text-sm';
|
|
73
|
+
case 'md':
|
|
74
|
+
return iconOnly ? 'h-9 w-9 p-2 rounded-md text-sm' : 'h-9 px-4 rounded-md gap-2 text-sm';
|
|
75
|
+
case 'lg':
|
|
76
|
+
return iconOnly
|
|
77
|
+
? 'h-10 w-10 p-2.5 rounded-lg text-base'
|
|
78
|
+
: 'h-10 px-5 rounded-lg gap-2 text-base';
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Base shared tailwind classes.
|
|
83
|
+
*/
|
|
84
|
+
const BASE_BTN_CLASS = 'font-medium flex items-center justify-center shrink-0 cursor-pointer ' +
|
|
85
|
+
'disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-75 ' +
|
|
86
|
+
'active:scale-[0.98] transition-all duration-150 ease-out focus:outline-none';
|
|
87
|
+
const Button = forwardRef(({ as, type, ...props }, ref) => {
|
|
88
|
+
const { className = '', children, theme = 'primary', variant = 'default', size = 'md', leftIcon, rightIcon, fullWidth = false, loading = false, loadingText = '', rounded = false, disabled, iconOnly = false, noOutlineOnFocus = false, ...restProps } = props;
|
|
89
|
+
const Component = as || 'button';
|
|
90
|
+
// Accessibility guard for icon-only buttons
|
|
91
|
+
if (iconOnly && !restProps['aria-label']) {
|
|
92
|
+
console.warn('[ui] <Button iconOnly> requires aria-label for accessibility.');
|
|
93
|
+
}
|
|
94
|
+
const resolvedDisabled = disabled || loading;
|
|
95
|
+
// Clean invalid props when not rendering a real button
|
|
96
|
+
const { type: _ignoreType, disabled: _ignoreDisabled, ...cleanRest } = restProps;
|
|
97
|
+
const buttonSpecificProps = Component === 'button'
|
|
98
|
+
? {
|
|
99
|
+
type: type !== null && type !== void 0 ? type : 'button',
|
|
100
|
+
disabled: resolvedDisabled,
|
|
101
|
+
}
|
|
102
|
+
: {};
|
|
103
|
+
const classes = useMemo(() => buildClassName(BASE_BTN_CLASS, THEMED_BTN_CLASS[theme][variant], getBtnSizeClasses(size, iconOnly), !noOutlineOnFocus && 'focus:outline focus:outline-2 focus:outline-offset-2', rounded && 'rounded-full', fullWidth && 'w-full', variant === 'default' && 'shadow-xs hover:shadow-none disabled:shadow-none', className), [theme, variant, size, iconOnly, rounded, fullWidth, noOutlineOnFocus, className]);
|
|
104
|
+
/**
|
|
105
|
+
* SPECIAL CASE: iconOnly + loading → show spinner only
|
|
106
|
+
*/
|
|
107
|
+
if (loading && iconOnly) {
|
|
108
|
+
return (jsx(Component, { ref: ref, className: classes, ...buttonSpecificProps, ...cleanRest, children: jsx(Loader, { "data-testid": "btn-loader-icon", size: "xs", className: buildClassName(LOADER_TEXT_CLASS[theme][variant]) }) }));
|
|
109
|
+
}
|
|
110
|
+
const loaderIcon = (jsx(Loader, { "data-testid": "btn-loader-icon", size: "xs", className: buildClassName(LOADER_TEXT_CLASS[theme][variant]) }));
|
|
111
|
+
return (jsx(Component, { ref: ref, className: classes, ...buttonSpecificProps, ...cleanRest, children: loading && !loadingText ? (jsxs("span", { className: "flex items-center gap-2", "aria-live": "polite", children: [loaderIcon, children] })) : loading && loadingText ? (jsxs("span", { className: "flex items-center gap-2", "aria-live": "polite", children: [loaderIcon, jsx(TextContent, { className: buildClassName(LOADER_TEXT_CLASS[theme][variant]), children: loadingText })] })) : (jsxs(Fragment, { children: [leftIcon && jsx("span", { className: "shrink-0 flex items-center", children: leftIcon }), children, rightIcon && jsx("span", { className: "shrink-0 flex items-center", children: rightIcon })] })) }));
|
|
112
|
+
});
|
|
113
|
+
Button.displayName = 'Button';
|
|
114
|
+
|
|
115
|
+
export { Button };
|
|
116
|
+
//# sourceMappingURL=Button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../../../../src/components/Button/Button.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport type { ButtonComponent, ButtonProps, ButtonSize, ThemedButtonClass } from './Button.types'\nimport type { PolymorphicRef } from '../common-type'\n\n/**\n * Tailwind CSS classes for theme + variant combinations.\n */\nconst THEMED_BTN_CLASS: ThemedButtonClass = {\n primary: {\n default:\n 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:bg-[var(--ui-primary-disabled)]',\n outlined:\n 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)] disabled:border-[var(--ui-primary-disabled)]',\n plain:\n 'text-[var(--ui-primary-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)]',\n },\n danger: {\n default:\n 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:bg-[var(--ui-danger-disabled)]',\n outlined:\n 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)] disabled:border-[var(--ui-danger-disabled)]',\n plain:\n 'text-[var(--ui-danger-text)] hover:bg-black/5 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)]',\n },\n secondary: {\n default:\n 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:bg-gray-200 dark:disabled:bg-gray-700',\n outlined:\n 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400 disabled:border-[var(--ui-border-muted)]',\n plain:\n 'text-gray-700 hover:bg-black/5 dark:text-gray-200 dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400',\n },\n success: {\n default:\n 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:bg-emerald-300 dark:disabled:bg-emerald-900',\n outlined:\n 'text-emerald-600 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',\n plain:\n 'text-emerald-600 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',\n },\n warning: {\n default:\n 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:bg-amber-300 dark:disabled:bg-amber-900',\n outlined:\n 'text-amber-600 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',\n plain:\n 'text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',\n },\n}\n\nconst LOADER_TEXT_CLASS: ThemedButtonClass = {\n primary: {\n default: 'text-white',\n outlined: 'text-[var(--ui-primary-text)]',\n plain: 'text-[var(--ui-primary-text)]',\n },\n danger: {\n default: 'text-white',\n outlined: 'text-[var(--ui-danger-text)]',\n plain: 'text-[var(--ui-danger-text)]',\n },\n secondary: {\n default: 'text-gray-700 dark:text-white',\n outlined: 'text-gray-700 dark:text-gray-200',\n plain: 'text-gray-700 dark:text-gray-200',\n },\n success: {\n default: 'text-white',\n outlined: 'text-emerald-600 dark:text-emerald-400',\n plain: 'text-emerald-600 dark:text-emerald-400',\n },\n warning: {\n default: 'text-white',\n outlined: 'text-amber-600 dark:text-amber-400',\n plain: 'text-amber-600 dark:text-amber-400',\n },\n}\n\n/**\n * Generate size classes.\n */\nconst getBtnSizeClasses = (size: ButtonSize, iconOnly = false) => {\n switch (size) {\n case 'xs':\n return iconOnly ? 'h-7 w-7 p-1 rounded-sm text-xs' : 'h-7 px-2.5 rounded-sm gap-1 text-xs'\n\n case 'sm':\n return iconOnly ? 'h-8 w-8 p-1.5 rounded text-sm' : 'h-8 px-3 rounded gap-1.5 text-sm'\n\n case 'md':\n return iconOnly ? 'h-9 w-9 p-2 rounded-md text-sm' : 'h-9 px-4 rounded-md gap-2 text-sm'\n\n case 'lg':\n return iconOnly\n ? 'h-10 w-10 p-2.5 rounded-lg text-base'\n : 'h-10 px-5 rounded-lg gap-2 text-base'\n }\n}\n\n/**\n * Base shared tailwind classes.\n */\nconst BASE_BTN_CLASS =\n 'font-medium flex items-center justify-center shrink-0 cursor-pointer ' +\n 'disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-75 ' +\n 'active:scale-[0.98] transition-all duration-150 ease-out focus:outline-none'\n\nexport const Button = forwardRef(\n <C extends ElementType = 'button'>(\n { as, type, ...props }: ButtonProps<C>,\n ref: PolymorphicRef<C>,\n ) => {\n const {\n className = '',\n children,\n theme = 'primary',\n variant = 'default',\n size = 'md',\n leftIcon,\n rightIcon,\n fullWidth = false,\n loading = false,\n loadingText = '',\n rounded = false,\n disabled,\n iconOnly = false,\n noOutlineOnFocus = false,\n ...restProps\n } = props\n\n const Component = as || 'button'\n\n // Accessibility guard for icon-only buttons\n if (iconOnly && !(restProps as Record<string, unknown>)['aria-label']) {\n console.warn('[ui] <Button iconOnly> requires aria-label for accessibility.')\n }\n\n const resolvedDisabled = disabled || loading\n\n // Clean invalid props when not rendering a real button\n const { type: _ignoreType, disabled: _ignoreDisabled, ...cleanRest } = restProps\n\n const buttonSpecificProps =\n Component === 'button'\n ? {\n type: type ?? 'button',\n disabled: resolvedDisabled,\n }\n : {}\n\n const classes = useMemo(\n () =>\n buildClassName(\n BASE_BTN_CLASS,\n THEMED_BTN_CLASS[theme][variant],\n getBtnSizeClasses(size, iconOnly),\n !noOutlineOnFocus && 'focus:outline focus:outline-2 focus:outline-offset-2',\n rounded && 'rounded-full',\n fullWidth && 'w-full',\n variant === 'default' && 'shadow-xs hover:shadow-none disabled:shadow-none',\n className,\n ),\n [theme, variant, size, iconOnly, rounded, fullWidth, noOutlineOnFocus, className],\n )\n\n /**\n * SPECIAL CASE: iconOnly + loading → show spinner only\n */\n if (loading && iconOnly) {\n return (\n <Component ref={ref} className={classes} {...buttonSpecificProps} {...cleanRest}>\n <Loader\n data-testid=\"btn-loader-icon\"\n size=\"xs\"\n className={buildClassName(LOADER_TEXT_CLASS[theme][variant])}\n />\n </Component>\n )\n }\n\n const loaderIcon = (\n <Loader\n data-testid=\"btn-loader-icon\"\n size=\"xs\"\n className={buildClassName(LOADER_TEXT_CLASS[theme][variant])}\n />\n )\n\n return (\n <Component ref={ref} className={classes} {...buttonSpecificProps} {...cleanRest}>\n {loading && !loadingText ? (\n <span className=\"flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n {children}\n </span>\n ) : loading && loadingText ? (\n <span className=\"flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n <TextContent className={buildClassName(LOADER_TEXT_CLASS[theme][variant])}>\n {loadingText}\n </TextContent>\n </span>\n ) : (\n <>\n {leftIcon && <span className=\"shrink-0 flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"shrink-0 flex items-center\">{rightIcon}</span>}\n </>\n )}\n </Component>\n )\n },\n) as ButtonComponent\n\nButton.displayName = 'Button'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo, Children, isValidElement, cloneElement } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
|
|
5
|
+
const EDGE_ROUNDING = {
|
|
6
|
+
horizontal: {
|
|
7
|
+
xs: { first: 'rounded-l-sm rounded-r-none', last: 'rounded-r-sm rounded-l-none' },
|
|
8
|
+
sm: { first: 'rounded-l rounded-r-none', last: 'rounded-r rounded-l-none' },
|
|
9
|
+
md: { first: 'rounded-l-md rounded-r-none', last: 'rounded-r-md rounded-l-none' },
|
|
10
|
+
lg: { first: 'rounded-l-lg rounded-r-none', last: 'rounded-r-lg rounded-l-none' },
|
|
11
|
+
},
|
|
12
|
+
vertical: {
|
|
13
|
+
xs: { first: 'rounded-t-sm rounded-b-none', last: 'rounded-b-sm rounded-t-none' },
|
|
14
|
+
sm: { first: 'rounded-t rounded-b-none', last: 'rounded-b rounded-t-none' },
|
|
15
|
+
md: { first: 'rounded-t-md rounded-b-none', last: 'rounded-b-md rounded-t-none' },
|
|
16
|
+
lg: { first: 'rounded-t-lg rounded-b-none', last: 'rounded-b-lg rounded-t-none' },
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
const PILL_EDGE_ROUNDING = {
|
|
20
|
+
horizontal: { first: 'rounded-l-full rounded-r-none', last: 'rounded-r-full rounded-l-none' },
|
|
21
|
+
vertical: { first: 'rounded-t-full rounded-b-none', last: 'rounded-b-full rounded-t-none' },
|
|
22
|
+
};
|
|
23
|
+
const getEdgeRoundingClass = ({ index, count, size, orientation, pill, }) => {
|
|
24
|
+
if (count <= 1)
|
|
25
|
+
return '';
|
|
26
|
+
if (index !== 0 && index !== count - 1)
|
|
27
|
+
return 'rounded-none';
|
|
28
|
+
const position = index === 0 ? 'first' : 'last';
|
|
29
|
+
return pill
|
|
30
|
+
? PILL_EDGE_ROUNDING[orientation][position]
|
|
31
|
+
: EDGE_ROUNDING[orientation][size][position];
|
|
32
|
+
};
|
|
33
|
+
const ButtonGroup = ({ children, orientation = 'horizontal', theme = 'secondary', variant = 'default', size = 'md', value, onChange, disabled: groupDisabled = false, rounded = false, fullWidth = false, label, className = '', }) => {
|
|
34
|
+
const isVertical = orientation === 'vertical';
|
|
35
|
+
const items = useMemo(() => Children.toArray(children).filter(isValidElement), [children]);
|
|
36
|
+
const count = items.length;
|
|
37
|
+
const isToggleMode = value !== undefined;
|
|
38
|
+
return (jsx("div", { role: "group", "aria-label": label, className: buildClassName('inline-flex items-stretch', isVertical ? 'flex-col' : 'flex-row', fullWidth && 'flex w-full', className), children: items.map((child, index) => {
|
|
39
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
40
|
+
const childProps = child.props;
|
|
41
|
+
const childSize = (_a = childProps.size) !== null && _a !== void 0 ? _a : size;
|
|
42
|
+
const childDisabled = (_b = childProps.disabled) !== null && _b !== void 0 ? _b : groupDisabled;
|
|
43
|
+
// Resolve item value for toggle mode
|
|
44
|
+
const itemVal = (_d = (_c = childProps.value) !== null && _c !== void 0 ? _c : childProps.id) !== null && _d !== void 0 ? _d : (typeof childProps.children === 'string' || typeof childProps.children === 'number'
|
|
45
|
+
? childProps.children
|
|
46
|
+
: index);
|
|
47
|
+
const isSelected = isToggleMode
|
|
48
|
+
? Array.isArray(value)
|
|
49
|
+
? value.includes(itemVal)
|
|
50
|
+
: value === itemVal
|
|
51
|
+
: false;
|
|
52
|
+
const resolvedTheme = isToggleMode
|
|
53
|
+
? isSelected
|
|
54
|
+
? ((_e = childProps.theme) !== null && _e !== void 0 ? _e : 'primary')
|
|
55
|
+
: ((_f = childProps.theme) !== null && _f !== void 0 ? _f : 'secondary')
|
|
56
|
+
: ((_g = childProps.theme) !== null && _g !== void 0 ? _g : theme);
|
|
57
|
+
const resolvedVariant = (_h = childProps.variant) !== null && _h !== void 0 ? _h : variant;
|
|
58
|
+
const handleClick = (e) => {
|
|
59
|
+
var _a;
|
|
60
|
+
(_a = childProps.onClick) === null || _a === void 0 ? void 0 : _a.call(childProps, e);
|
|
61
|
+
if (isToggleMode && !childDisabled) {
|
|
62
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(itemVal);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return cloneElement(child, {
|
|
66
|
+
theme: resolvedTheme,
|
|
67
|
+
variant: resolvedVariant,
|
|
68
|
+
size: childSize,
|
|
69
|
+
disabled: childDisabled,
|
|
70
|
+
...(isToggleMode ? { 'aria-pressed': isSelected } : {}),
|
|
71
|
+
onClick: handleClick,
|
|
72
|
+
className: buildClassName(childProps.className, getEdgeRoundingClass({
|
|
73
|
+
index,
|
|
74
|
+
count,
|
|
75
|
+
size: childSize,
|
|
76
|
+
orientation,
|
|
77
|
+
pill: rounded,
|
|
78
|
+
}), count > 1 && [
|
|
79
|
+
'relative shadow-none hover:z-10 focus:z-10 focus-visible:z-10',
|
|
80
|
+
isSelected && 'z-10',
|
|
81
|
+
index > 0 && (isVertical ? '-mt-px' : '-ml-px'),
|
|
82
|
+
index > 0 &&
|
|
83
|
+
resolvedVariant === 'default' &&
|
|
84
|
+
(isVertical
|
|
85
|
+
? resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
86
|
+
? 'border-t border-white/25 dark:border-white/20'
|
|
87
|
+
: 'border-t border-[var(--ui-border)]'
|
|
88
|
+
: resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
89
|
+
? 'border-l border-white/25 dark:border-white/20'
|
|
90
|
+
: 'border-l border-[var(--ui-border)]'),
|
|
91
|
+
], fullWidth && 'flex-1'),
|
|
92
|
+
});
|
|
93
|
+
}) }));
|
|
94
|
+
};
|
|
95
|
+
ButtonGroup.displayName = 'ButtonGroup';
|
|
96
|
+
|
|
97
|
+
export { ButtonGroup };
|
|
98
|
+
//# sourceMappingURL=ButtonGroup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonGroup.js","sources":["../../../../../src/components/ButtonGroup/ButtonGroup.tsx"],"sourcesContent":["import React, { Children, cloneElement, isValidElement, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport type { ButtonSize, ButtonTheme } from '../Button/Button.types'\nimport type { ButtonGroupOrientation, ButtonGroupProps } from './ButtonGroup.types'\n\nconst EDGE_ROUNDING: Record<\n ButtonGroupOrientation,\n Record<ButtonSize, { first: string; last: string }>\n> = {\n horizontal: {\n xs: { first: 'rounded-l-sm rounded-r-none', last: 'rounded-r-sm rounded-l-none' },\n sm: { first: 'rounded-l rounded-r-none', last: 'rounded-r rounded-l-none' },\n md: { first: 'rounded-l-md rounded-r-none', last: 'rounded-r-md rounded-l-none' },\n lg: { first: 'rounded-l-lg rounded-r-none', last: 'rounded-r-lg rounded-l-none' },\n },\n vertical: {\n xs: { first: 'rounded-t-sm rounded-b-none', last: 'rounded-b-sm rounded-t-none' },\n sm: { first: 'rounded-t rounded-b-none', last: 'rounded-b rounded-t-none' },\n md: { first: 'rounded-t-md rounded-b-none', last: 'rounded-b-md rounded-t-none' },\n lg: { first: 'rounded-t-lg rounded-b-none', last: 'rounded-b-lg rounded-t-none' },\n },\n}\n\nconst PILL_EDGE_ROUNDING: Record<ButtonGroupOrientation, { first: string; last: string }> = {\n horizontal: { first: 'rounded-l-full rounded-r-none', last: 'rounded-r-full rounded-l-none' },\n vertical: { first: 'rounded-t-full rounded-b-none', last: 'rounded-b-full rounded-t-none' },\n}\n\nconst getEdgeRoundingClass = ({\n index,\n count,\n size,\n orientation,\n pill,\n}: {\n index: number\n count: number\n size: ButtonSize\n orientation: ButtonGroupOrientation\n pill: boolean\n}) => {\n if (count <= 1) return ''\n if (index !== 0 && index !== count - 1) return 'rounded-none'\n\n const position = index === 0 ? 'first' : 'last'\n return pill\n ? PILL_EDGE_ROUNDING[orientation][position]\n : EDGE_ROUNDING[orientation][size][position]\n}\n\nexport const ButtonGroup: React.FC<ButtonGroupProps> = ({\n children,\n orientation = 'horizontal',\n theme = 'secondary',\n variant = 'default',\n size = 'md',\n value,\n onChange,\n disabled: groupDisabled = false,\n rounded = false,\n fullWidth = false,\n label,\n className = '',\n}) => {\n const isVertical = orientation === 'vertical'\n const items = useMemo(() => Children.toArray(children).filter(isValidElement), [children])\n const count = items.length\n const isToggleMode = value !== undefined\n\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={buildClassName(\n 'inline-flex items-stretch',\n isVertical ? 'flex-col' : 'flex-row',\n fullWidth && 'flex w-full',\n className,\n )}\n >\n {items.map((child, index) => {\n const childProps = child.props as Record<string, any>\n const childSize = (childProps.size as ButtonSize) ?? size\n const childDisabled = childProps.disabled ?? groupDisabled\n\n // Resolve item value for toggle mode\n const itemVal =\n childProps.value ??\n childProps.id ??\n (typeof childProps.children === 'string' || typeof childProps.children === 'number'\n ? childProps.children\n : index)\n\n const isSelected = isToggleMode\n ? Array.isArray(value)\n ? value.includes(itemVal)\n : value === itemVal\n : false\n\n const resolvedTheme: ButtonTheme = isToggleMode\n ? isSelected\n ? (childProps.theme ?? 'primary')\n : (childProps.theme ?? 'secondary')\n : (childProps.theme ?? theme)\n\n const resolvedVariant = childProps.variant ?? variant\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n childProps.onClick?.(e)\n if (isToggleMode && !childDisabled) {\n onChange?.(itemVal)\n }\n }\n\n return cloneElement(child as React.ReactElement<Record<string, unknown>>, {\n theme: resolvedTheme,\n variant: resolvedVariant,\n size: childSize,\n disabled: childDisabled,\n ...(isToggleMode ? { 'aria-pressed': isSelected } : {}),\n onClick: handleClick,\n className: buildClassName(\n childProps.className,\n getEdgeRoundingClass({\n index,\n count,\n size: childSize,\n orientation,\n pill: rounded,\n }),\n count > 1 && [\n 'relative shadow-none hover:z-10 focus:z-10 focus-visible:z-10',\n isSelected && 'z-10',\n index > 0 && (isVertical ? '-mt-px' : '-ml-px'),\n index > 0 &&\n resolvedVariant === 'default' &&\n (isVertical\n ? resolvedTheme === 'primary' || resolvedTheme === 'danger'\n ? 'border-t border-white/25 dark:border-white/20'\n : 'border-t border-[var(--ui-border)]'\n : resolvedTheme === 'primary' || resolvedTheme === 'danger'\n ? 'border-l border-white/25 dark:border-white/20'\n : 'border-l border-[var(--ui-border)]'),\n ],\n fullWidth && 'flex-1',\n ),\n })\n })}\n </div>\n )\n}\n\nButtonGroup.displayName = 'ButtonGroup'\n"],"names":["_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
|
|
5
|
+
const RADIUS_CLASS = {
|
|
6
|
+
none: 'rounded-none',
|
|
7
|
+
sm: 'rounded-sm',
|
|
8
|
+
md: 'rounded-md',
|
|
9
|
+
lg: 'rounded-lg',
|
|
10
|
+
xl: 'rounded-xl',
|
|
11
|
+
'2xl': 'rounded-2xl',
|
|
12
|
+
};
|
|
13
|
+
const ASPECT_RATIO_CLASS = {
|
|
14
|
+
auto: 'aspect-auto',
|
|
15
|
+
square: 'aspect-square',
|
|
16
|
+
video: 'aspect-video',
|
|
17
|
+
wide: 'aspect-[21/9]',
|
|
18
|
+
};
|
|
19
|
+
function ChevronRightIcon({ className = 'size-4' }) {
|
|
20
|
+
return (jsx("svg", { className: className, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }));
|
|
21
|
+
}
|
|
22
|
+
const Card = forwardRef(({ as, ...props }, ref) => {
|
|
23
|
+
const { variant = 'outlined', radius = 'xl', hoverable = false, clickable = false, selected = false, bordered = true, compact = false, zeroPadding = false, title, subtitle, leading, trailing, badge, showChevron = false, children, onClick, ...rest } = props;
|
|
24
|
+
const Component = as || 'div';
|
|
25
|
+
const { className, ...cleanRest } = rest;
|
|
26
|
+
const isClickable = clickable || Boolean(onClick);
|
|
27
|
+
const isOutlined = variant === 'outlined' && bordered;
|
|
28
|
+
const isElevated = variant === 'elevated';
|
|
29
|
+
const isFilled = variant === 'filled';
|
|
30
|
+
const isGhost = variant === 'ghost';
|
|
31
|
+
const classes = buildClassName('block transition-all duration-150 select-none', RADIUS_CLASS[radius] || RADIUS_CLASS.xl, zeroPadding ? '' : compact ? 'p-3 sm:p-4' : 'p-5 sm:p-6',
|
|
32
|
+
// Surface variants
|
|
33
|
+
isOutlined && 'bg-white dark:bg-gray-900 border border-[var(--ui-border)]', isElevated &&
|
|
34
|
+
'bg-white dark:bg-gray-900 border border-[var(--ui-border)] shadow-md shadow-gray-200/50 dark:shadow-none', isFilled && 'bg-gray-50/80 dark:bg-gray-800/60 border border-transparent', isGhost && 'bg-transparent border border-transparent',
|
|
35
|
+
// Hoverable & Clickable mobile/web touch states
|
|
36
|
+
hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80', isClickable &&
|
|
37
|
+
'cursor-pointer hover:-translate-y-0.5 hover:shadow-lg active:scale-[0.99] active:bg-gray-100 dark:active:bg-gray-800/90', selected && 'ring-2 ring-[var(--ui-primary)] border-[var(--ui-primary)]', className);
|
|
38
|
+
const hasHeaderRow = title || subtitle || leading || trailing || badge || showChevron;
|
|
39
|
+
return (jsxs(Component, { ref: ref, className: classes, onClick: onClick, ...cleanRest, children: [hasHeaderRow && (jsxs("div", { className: buildClassName('flex items-center gap-3 w-full min-w-0', children && 'mb-3'), children: [leading && jsx("div", { className: "shrink-0 flex items-center justify-center", children: leading }), jsxs("div", { className: "flex-1 min-w-0 text-left", children: [jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [title && (jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white truncate", children: title })), badge] }), subtitle && (jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate", children: subtitle }))] }), (trailing || showChevron) && (jsxs("div", { className: "shrink-0 flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400", children: [trailing, showChevron && jsx(ChevronRightIcon, { className: "size-4 text-gray-400" })] }))] })), children] }));
|
|
40
|
+
});
|
|
41
|
+
const CardHeader = ({ className, bordered = false, children, ...props }) => (jsx("div", { className: buildClassName('flex items-center justify-between gap-4 mb-4', bordered && 'pb-4 border-b border-[var(--ui-border)]', className), ...props, children: children }));
|
|
42
|
+
const CardTitle = ({ className, as: Component = 'h3', children, ...props }) => (jsx(Component, { className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white tracking-tight', className), ...props, children: children }));
|
|
43
|
+
const CardDescription = ({ className, children, ...props }) => (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal mt-1', className), ...props, children: children }));
|
|
44
|
+
const CardContent = ({ className, children, ...props }) => (jsx("div", { className: buildClassName('space-y-3', className), ...props, children: children }));
|
|
45
|
+
const CardFooter = ({ className, bordered = false, children, ...props }) => (jsx("div", { className: buildClassName('flex items-center justify-end gap-3 mt-4', bordered && 'pt-4 border-t border-[var(--ui-border)]', className), ...props, children: children }));
|
|
46
|
+
const CardMedia = ({ className, aspectRatio = 'video', alt = '', ...props }) => (jsx("div", { className: buildClassName('overflow-hidden -mx-5 -mt-5 mb-4 sm:-mx-6 sm:-mt-6', className), children: jsx("img", { alt: alt, className: buildClassName('w-full object-cover', ASPECT_RATIO_CLASS[aspectRatio] || ASPECT_RATIO_CLASS.video), ...props }) }));
|
|
47
|
+
Card.Header = CardHeader;
|
|
48
|
+
Card.Title = CardTitle;
|
|
49
|
+
Card.Description = CardDescription;
|
|
50
|
+
Card.Content = CardContent;
|
|
51
|
+
Card.Body = CardContent;
|
|
52
|
+
Card.Footer = CardFooter;
|
|
53
|
+
Card.Media = CardMedia;
|
|
54
|
+
Card.displayName = 'Card';
|
|
55
|
+
|
|
56
|
+
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle };
|
|
57
|
+
//# sourceMappingURL=Card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Card.js","sources":["../../../../../src/components/Card/Card.tsx"],"sourcesContent":["import { ElementType, forwardRef } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport type {\n CardComponent,\n CardContentProps,\n CardDescriptionProps,\n CardFooterProps,\n CardHeaderProps,\n CardMediaProps,\n CardProps,\n CardTitleProps,\n} from './Card.types'\nimport type { PolymorphicRef } from '../common-type'\n\nconst RADIUS_CLASS: Record<string, string> = {\n none: 'rounded-none',\n sm: 'rounded-sm',\n md: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n}\n\nconst ASPECT_RATIO_CLASS: Record<string, string> = {\n auto: 'aspect-auto',\n square: 'aspect-square',\n video: 'aspect-video',\n wide: 'aspect-[21/9]',\n}\n\nfunction ChevronRightIcon({ className = 'size-4' }: { className?: string }) {\n return (\n <svg className={className} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )\n}\n\nexport const Card = forwardRef(\n <C extends ElementType = 'div'>({ as, ...props }: CardProps<C>, ref: PolymorphicRef<C>) => {\n const {\n variant = 'outlined',\n radius = 'xl',\n hoverable = false,\n clickable = false,\n selected = false,\n bordered = true,\n compact = false,\n zeroPadding = false,\n title,\n subtitle,\n leading,\n trailing,\n badge,\n showChevron = false,\n children,\n onClick,\n ...rest\n } = props\n\n const Component = as || 'div'\n const { className, ...cleanRest } = rest as { className?: string }\n\n const isClickable = clickable || Boolean(onClick)\n const isOutlined = variant === 'outlined' && bordered\n const isElevated = variant === 'elevated'\n const isFilled = variant === 'filled'\n const isGhost = variant === 'ghost'\n\n const classes = buildClassName(\n 'block transition-all duration-150 select-none',\n RADIUS_CLASS[radius] || RADIUS_CLASS.xl,\n zeroPadding ? '' : compact ? 'p-3 sm:p-4' : 'p-5 sm:p-6',\n\n // Surface variants\n isOutlined && 'bg-white dark:bg-gray-900 border border-[var(--ui-border)]',\n isElevated &&\n 'bg-white dark:bg-gray-900 border border-[var(--ui-border)] shadow-md shadow-gray-200/50 dark:shadow-none',\n isFilled && 'bg-gray-50/80 dark:bg-gray-800/60 border border-transparent',\n isGhost && 'bg-transparent border border-transparent',\n\n // Hoverable & Clickable mobile/web touch states\n hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80',\n isClickable &&\n 'cursor-pointer hover:-translate-y-0.5 hover:shadow-lg active:scale-[0.99] active:bg-gray-100 dark:active:bg-gray-800/90',\n selected && 'ring-2 ring-[var(--ui-primary)] border-[var(--ui-primary)]',\n\n className,\n )\n\n const hasHeaderRow = title || subtitle || leading || trailing || badge || showChevron\n\n return (\n <Component ref={ref} className={classes} onClick={onClick} {...cleanRest}>\n {hasHeaderRow && (\n <div\n className={buildClassName('flex items-center gap-3 w-full min-w-0', children && 'mb-3')}\n >\n {leading && <div className=\"shrink-0 flex items-center justify-center\">{leading}</div>}\n <div className=\"flex-1 min-w-0 text-left\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n {title && (\n <span className=\"text-sm font-semibold text-gray-900 dark:text-white truncate\">\n {title}\n </span>\n )}\n {badge}\n </div>\n {subtitle && (\n <div className=\"text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate\">\n {subtitle}\n </div>\n )}\n </div>\n {(trailing || showChevron) && (\n <div className=\"shrink-0 flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400\">\n {trailing}\n {showChevron && <ChevronRightIcon className=\"size-4 text-gray-400\" />}\n </div>\n )}\n </div>\n )}\n {children}\n </Component>\n )\n },\n) as unknown as CardComponent\n\nexport const CardHeader = ({\n className,\n bordered = false,\n children,\n ...props\n}: CardHeaderProps) => (\n <div\n className={buildClassName(\n 'flex items-center justify-between gap-4 mb-4',\n bordered && 'pb-4 border-b border-[var(--ui-border)]',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n)\n\nexport const CardTitle = ({\n className,\n as: Component = 'h3',\n children,\n ...props\n}: CardTitleProps) => (\n <Component\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white tracking-tight',\n className,\n )}\n {...props}\n >\n {children}\n </Component>\n)\n\nexport const CardDescription = ({ className, children, ...props }: CardDescriptionProps) => (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal mt-1',\n className,\n )}\n {...props}\n >\n {children}\n </p>\n)\n\nexport const CardContent = ({ className, children, ...props }: CardContentProps) => (\n <div className={buildClassName('space-y-3', className)} {...props}>\n {children}\n </div>\n)\n\nexport const CardFooter = ({\n className,\n bordered = false,\n children,\n ...props\n}: CardFooterProps) => (\n <div\n className={buildClassName(\n 'flex items-center justify-end gap-3 mt-4',\n bordered && 'pt-4 border-t border-[var(--ui-border)]',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n)\n\nexport const CardMedia = ({\n className,\n aspectRatio = 'video',\n alt = '',\n ...props\n}: CardMediaProps) => (\n <div className={buildClassName('overflow-hidden -mx-5 -mt-5 mb-4 sm:-mx-6 sm:-mt-6', className)}>\n <img\n alt={alt}\n className={buildClassName(\n 'w-full object-cover',\n ASPECT_RATIO_CLASS[aspectRatio] || ASPECT_RATIO_CLASS.video,\n )}\n {...props}\n />\n </div>\n)\n\nCard.Header = CardHeader\nCard.Title = CardTitle\nCard.Description = CardDescription\nCard.Content = CardContent\nCard.Body = CardContent\nCard.Footer = CardFooter\nCard.Media = CardMedia\n\nCard.displayName = 'Card'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|