@pk-design/react-tailwind 1.6.0 → 1.7.1
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
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default, { useId, useMemo, useState, forwardRef, Children, isValidElement, cloneElement, useRef, useImperativeHandle, useEffect, useCallback, Fragment as Fragment$1,
|
|
3
|
+
import React__default, { useId, useMemo, useState, forwardRef, Children, isValidElement, cloneElement, useRef, useImperativeHandle, useEffect, useCallback, Fragment as Fragment$1, createContext, useContext, useLayoutEffect } from 'react';
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle, Menu, MenuButton, MenuItems, MenuItem, Combobox, ComboboxInput, ComboboxButton, ComboboxOptions, ComboboxOption, TabGroup, TabList, Tab, TabPanels, TabPanel, Transition } from '@headlessui/react';
|
|
6
6
|
import { FixedSizeList } from 'react-window';
|
|
7
7
|
|
|
8
8
|
const buildClassName = (...classes) => twMerge(classes.filter(Boolean));
|
|
9
9
|
|
|
10
|
-
var _path$
|
|
11
|
-
function _extends$
|
|
10
|
+
var _path$j;
|
|
11
|
+
function _extends$j() { return _extends$j = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$j.apply(null, arguments); }
|
|
12
12
|
var SvgChevronDown = function SvgChevronDown(props) {
|
|
13
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
13
|
+
return /*#__PURE__*/React.createElement("svg", _extends$j({
|
|
14
14
|
xmlns: "http://www.w3.org/2000/svg",
|
|
15
15
|
width: 24,
|
|
16
16
|
height: 24,
|
|
@@ -21,19 +21,19 @@ var SvgChevronDown = function SvgChevronDown(props) {
|
|
|
21
21
|
strokeWidth: 2,
|
|
22
22
|
className: "lucide lucide-chevron-down-icon lucide-chevron-down",
|
|
23
23
|
viewBox: "0 0 24 24"
|
|
24
|
-
}, props), _path$
|
|
24
|
+
}, props), _path$j || (_path$j = /*#__PURE__*/React.createElement("path", {
|
|
25
25
|
d: "m6 9 6 6 6-6"
|
|
26
26
|
})));
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const CONTAINER_CLASS = {
|
|
30
|
-
bordered: 'rounded-lg border border-
|
|
30
|
+
bordered: 'rounded-lg border border-[var(--ui-border)] divide-y divide-[var(--ui-border)] bg-white dark:bg-gray-800 overflow-hidden',
|
|
31
31
|
separated: 'space-y-2',
|
|
32
|
-
plain: 'divide-y divide-
|
|
32
|
+
plain: 'divide-y divide-[var(--ui-border)]',
|
|
33
33
|
};
|
|
34
34
|
const ITEM_CLASS = {
|
|
35
35
|
bordered: '',
|
|
36
|
-
separated: 'rounded-lg border border-
|
|
36
|
+
separated: 'rounded-lg border border-[var(--ui-border)] bg-white dark:bg-gray-800 overflow-hidden',
|
|
37
37
|
plain: '',
|
|
38
38
|
};
|
|
39
39
|
const HEADER_CLASS = 'flex w-full items-center justify-between gap-2 py-3 px-4 text-left text-sm font-medium ' +
|
|
@@ -78,115 +78,6 @@ const Accordion = ({ items, type = 'single', variant = 'bordered', collapsible =
|
|
|
78
78
|
};
|
|
79
79
|
Accordion.displayName = 'Accordion';
|
|
80
80
|
|
|
81
|
-
var _path$h, _path2;
|
|
82
|
-
function _extends$h() { return _extends$h = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$h.apply(null, arguments); }
|
|
83
|
-
var SvgBadgeCheck = function SvgBadgeCheck(props) {
|
|
84
|
-
return /*#__PURE__*/React.createElement("svg", _extends$h({
|
|
85
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
86
|
-
width: 24,
|
|
87
|
-
height: 24,
|
|
88
|
-
fill: "none",
|
|
89
|
-
stroke: "currentColor",
|
|
90
|
-
strokeLinecap: "round",
|
|
91
|
-
strokeLinejoin: "round",
|
|
92
|
-
strokeWidth: 2,
|
|
93
|
-
className: "lucide lucide-badge-check-icon lucide-badge-check",
|
|
94
|
-
viewBox: "0 0 24 24"
|
|
95
|
-
}, props), _path$h || (_path$h = /*#__PURE__*/React.createElement("path", {
|
|
96
|
-
d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76"
|
|
97
|
-
})), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
|
|
98
|
-
d: "m9 12 2 2 4-4"
|
|
99
|
-
})));
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
var _circle$4, _path$g;
|
|
103
|
-
function _extends$g() { return _extends$g = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$g.apply(null, arguments); }
|
|
104
|
-
var SvgCircleX = function SvgCircleX(props) {
|
|
105
|
-
return /*#__PURE__*/React.createElement("svg", _extends$g({
|
|
106
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
107
|
-
width: 24,
|
|
108
|
-
height: 24,
|
|
109
|
-
fill: "none",
|
|
110
|
-
stroke: "currentColor",
|
|
111
|
-
strokeLinecap: "round",
|
|
112
|
-
strokeLinejoin: "round",
|
|
113
|
-
strokeWidth: 2,
|
|
114
|
-
className: "lucide lucide-circle-x-icon lucide-circle-x",
|
|
115
|
-
viewBox: "0 0 24 24"
|
|
116
|
-
}, props), _circle$4 || (_circle$4 = /*#__PURE__*/React.createElement("circle", {
|
|
117
|
-
cx: 12,
|
|
118
|
-
cy: 12,
|
|
119
|
-
r: 10
|
|
120
|
-
})), _path$g || (_path$g = /*#__PURE__*/React.createElement("path", {
|
|
121
|
-
d: "m15 9-6 6M9 9l6 6"
|
|
122
|
-
})));
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
var _circle$3, _path$f;
|
|
126
|
-
function _extends$f() { return _extends$f = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$f.apply(null, arguments); }
|
|
127
|
-
var SvgCircleAlert = function SvgCircleAlert(props) {
|
|
128
|
-
return /*#__PURE__*/React.createElement("svg", _extends$f({
|
|
129
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
130
|
-
width: 24,
|
|
131
|
-
height: 24,
|
|
132
|
-
fill: "none",
|
|
133
|
-
stroke: "currentColor",
|
|
134
|
-
strokeLinecap: "round",
|
|
135
|
-
strokeLinejoin: "round",
|
|
136
|
-
strokeWidth: 2,
|
|
137
|
-
className: "lucide lucide-circle-alert-icon lucide-circle-alert",
|
|
138
|
-
viewBox: "0 0 24 24"
|
|
139
|
-
}, props), _circle$3 || (_circle$3 = /*#__PURE__*/React.createElement("circle", {
|
|
140
|
-
cx: 12,
|
|
141
|
-
cy: 12,
|
|
142
|
-
r: 10
|
|
143
|
-
})), _path$f || (_path$f = /*#__PURE__*/React.createElement("path", {
|
|
144
|
-
d: "M12 8v4M12 16h.01"
|
|
145
|
-
})));
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
var _circle$2, _path$e;
|
|
149
|
-
function _extends$e() { return _extends$e = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$e.apply(null, arguments); }
|
|
150
|
-
var SvgInfo = function SvgInfo(props) {
|
|
151
|
-
return /*#__PURE__*/React.createElement("svg", _extends$e({
|
|
152
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
153
|
-
width: 24,
|
|
154
|
-
height: 24,
|
|
155
|
-
fill: "none",
|
|
156
|
-
stroke: "currentColor",
|
|
157
|
-
strokeLinecap: "round",
|
|
158
|
-
strokeLinejoin: "round",
|
|
159
|
-
strokeWidth: 2,
|
|
160
|
-
className: "lucide lucide-info-icon lucide-info",
|
|
161
|
-
viewBox: "0 0 24 24"
|
|
162
|
-
}, props), _circle$2 || (_circle$2 = /*#__PURE__*/React.createElement("circle", {
|
|
163
|
-
cx: 12,
|
|
164
|
-
cy: 12,
|
|
165
|
-
r: 10
|
|
166
|
-
})), _path$e || (_path$e = /*#__PURE__*/React.createElement("path", {
|
|
167
|
-
d: "M12 16v-4M12 8h.01"
|
|
168
|
-
})));
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
var _path$d;
|
|
172
|
-
function _extends$d() { return _extends$d = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$d.apply(null, arguments); }
|
|
173
|
-
var SvgX = function SvgX(props) {
|
|
174
|
-
return /*#__PURE__*/React.createElement("svg", _extends$d({
|
|
175
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
176
|
-
width: 24,
|
|
177
|
-
height: 24,
|
|
178
|
-
fill: "none",
|
|
179
|
-
stroke: "currentColor",
|
|
180
|
-
strokeLinecap: "round",
|
|
181
|
-
strokeLinejoin: "round",
|
|
182
|
-
strokeWidth: 2,
|
|
183
|
-
className: "lucide lucide-x-icon lucide-x",
|
|
184
|
-
viewBox: "0 0 24 24"
|
|
185
|
-
}, props), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
|
|
186
|
-
d: "M18 6 6 18M6 6l12 12"
|
|
187
|
-
})));
|
|
188
|
-
};
|
|
189
|
-
|
|
190
81
|
const loaderSizeMap = {
|
|
191
82
|
xs: 'size-4',
|
|
192
83
|
sm: 'size-6',
|
|
@@ -253,8 +144,8 @@ const THEMED_BTN_CLASS = {
|
|
|
253
144
|
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)]',
|
|
254
145
|
},
|
|
255
146
|
secondary: {
|
|
256
|
-
default: 'text-gray-700 bg-white border border-
|
|
257
|
-
outlined: 'text-gray-700 hover:text-white border border-
|
|
147
|
+
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',
|
|
148
|
+
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)]',
|
|
258
149
|
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',
|
|
259
150
|
},
|
|
260
151
|
success: {
|
|
@@ -346,52 +237,132 @@ const Button = forwardRef(({ as, type, ...props }, ref) => {
|
|
|
346
237
|
});
|
|
347
238
|
Button.displayName = 'Button';
|
|
348
239
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
240
|
+
var _path$i;
|
|
241
|
+
function _extends$i() { return _extends$i = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$i.apply(null, arguments); }
|
|
242
|
+
var SvgChevronLeft = function SvgChevronLeft(props) {
|
|
243
|
+
return /*#__PURE__*/React.createElement("svg", _extends$i({
|
|
244
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
245
|
+
width: 24,
|
|
246
|
+
height: 24,
|
|
247
|
+
fill: "none",
|
|
248
|
+
stroke: "currentColor",
|
|
249
|
+
strokeLinecap: "round",
|
|
250
|
+
strokeLinejoin: "round",
|
|
251
|
+
strokeWidth: 2,
|
|
252
|
+
className: "lucide lucide-chevron-left-icon lucide-chevron-left",
|
|
253
|
+
viewBox: "0 0 24 24"
|
|
254
|
+
}, props), _path$i || (_path$i = /*#__PURE__*/React.createElement("path", {
|
|
255
|
+
d: "m15 18-6-6 6-6"
|
|
256
|
+
})));
|
|
354
257
|
};
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
258
|
+
|
|
259
|
+
var _path$h;
|
|
260
|
+
function _extends$h() { return _extends$h = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$h.apply(null, arguments); }
|
|
261
|
+
var SvgX = function SvgX(props) {
|
|
262
|
+
return /*#__PURE__*/React.createElement("svg", _extends$h({
|
|
263
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
264
|
+
width: 24,
|
|
265
|
+
height: 24,
|
|
266
|
+
fill: "none",
|
|
267
|
+
stroke: "currentColor",
|
|
268
|
+
strokeLinecap: "round",
|
|
269
|
+
strokeLinejoin: "round",
|
|
270
|
+
strokeWidth: 2,
|
|
271
|
+
className: "lucide lucide-x-icon lucide-x",
|
|
272
|
+
viewBox: "0 0 24 24"
|
|
273
|
+
}, props), _path$h || (_path$h = /*#__PURE__*/React.createElement("path", {
|
|
274
|
+
d: "M18 6 6 18M6 6l12 12"
|
|
275
|
+
})));
|
|
360
276
|
};
|
|
361
|
-
const Alert = forwardRef((props, ref) => {
|
|
362
|
-
const { type = 'info', className, message, children, removable = false, onRemove, icon, title, ...restProps } = props;
|
|
363
|
-
const DefaultIcon = AlertTypeIconMap[type] || SvgInfo;
|
|
364
|
-
const iconNode = icon !== undefined ? (icon) : (jsx(DefaultIcon, { className: "size-5 shrink-0", "data-testid": `alert-${type}-icon` }));
|
|
365
|
-
return (jsxs("div", { ref: ref, className: buildClassName('flex items-center justify-between rounded-md p-3 text-sm ring-1 ring-inset gap-2', TypeClassMap$1[type], className), ...restProps, children: [jsxs("span", { className: "inline-flex items-start gap-2 min-w-0", children: [iconNode && jsx("span", { className: "shrink-0 inline-flex mt-0.5", children: iconNode }), jsxs("span", { className: "inline-flex flex-col gap-0.5 min-w-0", children: [title && jsx("span", { className: "font-semibold", children: title }), jsx("span", { className: "inline-flex items-center", children: message !== null && message !== void 0 ? message : children })] })] }), removable && (jsx(Button, { iconOnly: true, "aria-label": "Dismiss alert", size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/10 dark:hover:bg-white/10 shrink-0", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), "data-testid": "alert-remove-btn", children: jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
366
|
-
});
|
|
367
|
-
Alert.displayName = 'Alert';
|
|
368
277
|
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
278
|
+
const alignmentMap = {
|
|
279
|
+
center: 'items-center justify-center h-full',
|
|
280
|
+
start: 'justify-start h-full',
|
|
281
|
+
end: 'justify-end h-full',
|
|
282
|
+
top: 'items-start justify-center w-full',
|
|
283
|
+
bottom: 'items-end justify-center h-full',
|
|
375
284
|
};
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
285
|
+
const panelAlignmentMap = {
|
|
286
|
+
center: 'data-[closed]:scale-95 rounded-2xl',
|
|
287
|
+
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
288
|
+
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
289
|
+
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
290
|
+
bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh]',
|
|
379
291
|
};
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
|
|
292
|
+
const panelSizeMap = {
|
|
293
|
+
xs: 'max-w-xs',
|
|
294
|
+
sm: 'max-w-sm',
|
|
295
|
+
md: 'max-w-md',
|
|
296
|
+
lg: 'max-w-lg',
|
|
297
|
+
xl: 'max-w-xl',
|
|
298
|
+
'2xl': 'max-w-2xl',
|
|
299
|
+
full: 'w-full',
|
|
300
|
+
};
|
|
301
|
+
const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align = 'end', size = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
|
|
302
|
+
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
303
|
+
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
304
|
+
const [viewportHeight, setViewportHeight] = React__default.useState(null);
|
|
305
|
+
React__default.useEffect(() => {
|
|
306
|
+
if (!isOpen) {
|
|
307
|
+
setViewportHeight(null);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const updateHeight = () => {
|
|
311
|
+
if (typeof window !== 'undefined' && window.visualViewport) {
|
|
312
|
+
setViewportHeight(window.visualViewport.height);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
updateHeight();
|
|
316
|
+
const vv = typeof window !== 'undefined' ? window.visualViewport : null;
|
|
317
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('resize', updateHeight);
|
|
318
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('scroll', updateHeight);
|
|
319
|
+
return () => {
|
|
320
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('resize', updateHeight);
|
|
321
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('scroll', updateHeight);
|
|
322
|
+
};
|
|
323
|
+
}, [isOpen]);
|
|
324
|
+
const handleDialogClose = () => {
|
|
325
|
+
if (closeOnOutsideClick) {
|
|
326
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
return (jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsx("div", { className: "fixed left-0 top-0 w-full", style: { height: viewportHeight ? `${viewportHeight}px` : '100dvh' }, children: jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0', 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0', panelAlignmentMap[align], panelSizeMap[size], panelClass), children: [shouldShowDragHandle && (jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), showTitleSection && (jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsx(DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) }))] }), description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsx("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass), children: children }), footer && (jsx("div", { className: buildClassName('p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
|
|
330
|
+
};
|
|
331
|
+
Drawer.displayName = 'Drawer';
|
|
390
332
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
var
|
|
394
|
-
|
|
333
|
+
function ActionSheet({ isOpen, onClose, title, description, actions, showCancelButton = true, cancelLabel = 'Cancel', onCancel, closeOnBackdropClick = true, dragHandle = true, panelClass = '', containerClass = '', }) {
|
|
334
|
+
const handleItemClick = (action) => {
|
|
335
|
+
var _a;
|
|
336
|
+
if (action.disabled)
|
|
337
|
+
return;
|
|
338
|
+
(_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action);
|
|
339
|
+
onClose();
|
|
340
|
+
};
|
|
341
|
+
const handleCancelClick = () => {
|
|
342
|
+
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
343
|
+
onClose();
|
|
344
|
+
};
|
|
345
|
+
return (jsx(Drawer, { isOpen: isOpen, onClose: onClose, align: "bottom", closeOnOutsideClick: closeOnBackdropClick, showCloseButton: false, dragHandle: dragHandle, panelClass: buildClassName('rounded-t-2xl max-h-[85vh] overflow-hidden', panelClass), "data-testid": "action-sheet-drawer", children: jsxs("div", { className: buildClassName('space-y-4 py-1', containerClass), "data-testid": "action-sheet", children: [(title || description) && (jsxs("div", { className: "text-center px-4 pb-2 border-b border-[var(--ui-border-muted)]", children: [title && (jsx("h3", { className: "text-sm font-bold text-gray-900 dark:text-white truncate", children: title })), description && (jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate", children: description }))] })), jsx("div", { className: "space-y-1 bg-gray-50 dark:bg-gray-800/60 p-1.5 rounded-2xl border border-[var(--ui-border-muted)]", children: actions.map((action) => {
|
|
346
|
+
const isDanger = action.theme === 'danger';
|
|
347
|
+
const isPrimary = action.theme === 'primary';
|
|
348
|
+
return (jsxs("button", { type: "button", disabled: action.disabled, onClick: () => handleItemClick(action), className: buildClassName('w-full flex items-center gap-3.5 p-3 rounded-xl text-left transition-all duration-150 group cursor-pointer', action.disabled && 'opacity-50 cursor-not-allowed pointer-events-none', !action.disabled &&
|
|
349
|
+
(isDanger
|
|
350
|
+
? 'hover:bg-red-50 dark:hover:bg-red-950/40 text-red-600 dark:text-red-400 font-semibold'
|
|
351
|
+
: isPrimary
|
|
352
|
+
? 'hover:bg-blue-50 dark:hover:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
353
|
+
: 'hover:bg-white dark:hover:bg-gray-800 text-gray-800 dark:text-gray-200 font-medium')), "data-testid": `action-sheet-item-${action.id}`, children: [action.icon && (jsx("span", { className: buildClassName('shrink-0 text-base transition-colors', isDanger
|
|
354
|
+
? 'text-red-500 dark:text-red-400'
|
|
355
|
+
: isPrimary
|
|
356
|
+
? 'text-blue-500 dark:text-blue-400'
|
|
357
|
+
: 'text-gray-500 dark:text-gray-400 group-hover:text-gray-700 dark:group-hover:text-gray-200'), children: action.icon })), jsxs("div", { className: "min-w-0 flex-1", children: [jsx("div", { className: "text-sm truncate", children: action.label }), action.description && (jsx("div", { className: "text-xs text-gray-400 dark:text-gray-500 truncate font-normal mt-0.5", children: action.description }))] })] }, action.id));
|
|
358
|
+
}) }), showCancelButton && (jsx("div", { className: "pt-1", children: jsx(Button, { theme: "secondary", size: "lg", fullWidth: true, onClick: handleCancelClick, className: "font-semibold text-sm rounded-xl py-3", "data-testid": "action-sheet-cancel-btn", children: cancelLabel }) }))] }) }));
|
|
359
|
+
}
|
|
360
|
+
ActionSheet.displayName = 'ActionSheet';
|
|
361
|
+
|
|
362
|
+
var _path$g, _path2;
|
|
363
|
+
function _extends$g() { return _extends$g = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$g.apply(null, arguments); }
|
|
364
|
+
var SvgBadgeCheck = function SvgBadgeCheck(props) {
|
|
365
|
+
return /*#__PURE__*/React.createElement("svg", _extends$g({
|
|
395
366
|
xmlns: "http://www.w3.org/2000/svg",
|
|
396
367
|
width: 24,
|
|
397
368
|
height: 24,
|
|
@@ -400,17 +371,19 @@ var SvgTriangleAlert = function SvgTriangleAlert(props) {
|
|
|
400
371
|
strokeLinecap: "round",
|
|
401
372
|
strokeLinejoin: "round",
|
|
402
373
|
strokeWidth: 2,
|
|
403
|
-
className: "lucide lucide-
|
|
374
|
+
className: "lucide lucide-badge-check-icon lucide-badge-check",
|
|
404
375
|
viewBox: "0 0 24 24"
|
|
405
|
-
}, props), _path$
|
|
406
|
-
d: "
|
|
376
|
+
}, props), _path$g || (_path$g = /*#__PURE__*/React.createElement("path", {
|
|
377
|
+
d: "M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76"
|
|
378
|
+
})), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
|
|
379
|
+
d: "m9 12 2 2 4-4"
|
|
407
380
|
})));
|
|
408
381
|
};
|
|
409
382
|
|
|
410
|
-
var _circle$
|
|
411
|
-
function _extends$
|
|
412
|
-
var
|
|
413
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
383
|
+
var _circle$5, _path$f;
|
|
384
|
+
function _extends$f() { return _extends$f = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$f.apply(null, arguments); }
|
|
385
|
+
var SvgCircleX = function SvgCircleX(props) {
|
|
386
|
+
return /*#__PURE__*/React.createElement("svg", _extends$f({
|
|
414
387
|
xmlns: "http://www.w3.org/2000/svg",
|
|
415
388
|
width: 24,
|
|
416
389
|
height: 24,
|
|
@@ -419,29 +392,160 @@ var SvgCircleCheck = function SvgCircleCheck(props) {
|
|
|
419
392
|
strokeLinecap: "round",
|
|
420
393
|
strokeLinejoin: "round",
|
|
421
394
|
strokeWidth: 2,
|
|
422
|
-
className: "lucide lucide-circle-
|
|
395
|
+
className: "lucide lucide-circle-x-icon lucide-circle-x",
|
|
423
396
|
viewBox: "0 0 24 24"
|
|
424
|
-
}, props), _circle$
|
|
397
|
+
}, props), _circle$5 || (_circle$5 = /*#__PURE__*/React.createElement("circle", {
|
|
425
398
|
cx: 12,
|
|
426
399
|
cy: 12,
|
|
427
400
|
r: 10
|
|
428
|
-
})), _path$
|
|
429
|
-
d: "
|
|
401
|
+
})), _path$f || (_path$f = /*#__PURE__*/React.createElement("path", {
|
|
402
|
+
d: "m15 9-6 6M9 9l6 6"
|
|
430
403
|
})));
|
|
431
404
|
};
|
|
432
405
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
406
|
+
var _circle$4, _path$e;
|
|
407
|
+
function _extends$e() { return _extends$e = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$e.apply(null, arguments); }
|
|
408
|
+
var SvgCircleAlert = function SvgCircleAlert(props) {
|
|
409
|
+
return /*#__PURE__*/React.createElement("svg", _extends$e({
|
|
410
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
411
|
+
width: 24,
|
|
412
|
+
height: 24,
|
|
413
|
+
fill: "none",
|
|
414
|
+
stroke: "currentColor",
|
|
415
|
+
strokeLinecap: "round",
|
|
416
|
+
strokeLinejoin: "round",
|
|
417
|
+
strokeWidth: 2,
|
|
418
|
+
className: "lucide lucide-circle-alert-icon lucide-circle-alert",
|
|
419
|
+
viewBox: "0 0 24 24"
|
|
420
|
+
}, props), _circle$4 || (_circle$4 = /*#__PURE__*/React.createElement("circle", {
|
|
421
|
+
cx: 12,
|
|
422
|
+
cy: 12,
|
|
423
|
+
r: 10
|
|
424
|
+
})), _path$e || (_path$e = /*#__PURE__*/React.createElement("path", {
|
|
425
|
+
d: "M12 8v4M12 16h.01"
|
|
426
|
+
})));
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
var _circle$3, _path$d;
|
|
430
|
+
function _extends$d() { return _extends$d = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$d.apply(null, arguments); }
|
|
431
|
+
var SvgInfo = function SvgInfo(props) {
|
|
432
|
+
return /*#__PURE__*/React.createElement("svg", _extends$d({
|
|
433
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
434
|
+
width: 24,
|
|
435
|
+
height: 24,
|
|
436
|
+
fill: "none",
|
|
437
|
+
stroke: "currentColor",
|
|
438
|
+
strokeLinecap: "round",
|
|
439
|
+
strokeLinejoin: "round",
|
|
440
|
+
strokeWidth: 2,
|
|
441
|
+
className: "lucide lucide-info-icon lucide-info",
|
|
442
|
+
viewBox: "0 0 24 24"
|
|
443
|
+
}, props), _circle$3 || (_circle$3 = /*#__PURE__*/React.createElement("circle", {
|
|
444
|
+
cx: 12,
|
|
445
|
+
cy: 12,
|
|
446
|
+
r: 10
|
|
447
|
+
})), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
|
|
448
|
+
d: "M12 16v-4M12 8h.01"
|
|
449
|
+
})));
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
const AlertTypeIconMap = {
|
|
453
|
+
success: SvgBadgeCheck,
|
|
454
|
+
danger: SvgCircleX,
|
|
455
|
+
warning: SvgCircleAlert,
|
|
456
|
+
info: SvgInfo,
|
|
457
|
+
};
|
|
458
|
+
const TypeClassMap$1 = {
|
|
459
|
+
success: 'bg-[var(--ui-success-light)] ring-[var(--ui-success-ring-subtle)] text-[var(--ui-success-text)]',
|
|
460
|
+
danger: 'bg-[var(--ui-danger-light)] ring-[var(--ui-danger-ring-subtle)] text-[var(--ui-danger-text)]',
|
|
461
|
+
warning: 'bg-[var(--ui-warning-light)] ring-[var(--ui-warning-ring-subtle)] text-[var(--ui-warning-text)]',
|
|
462
|
+
info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',
|
|
463
|
+
};
|
|
464
|
+
const Alert = forwardRef((props, ref) => {
|
|
465
|
+
const { type = 'info', className, message, children, removable = false, onRemove, icon, title, ...restProps } = props;
|
|
466
|
+
const DefaultIcon = AlertTypeIconMap[type] || SvgInfo;
|
|
467
|
+
const iconNode = icon !== undefined ? (icon) : (jsx(DefaultIcon, { className: "size-5 shrink-0", "data-testid": `alert-${type}-icon` }));
|
|
468
|
+
return (jsxs("div", { ref: ref, className: buildClassName('flex items-center justify-between rounded-md p-3 text-sm ring-1 ring-inset gap-2', TypeClassMap$1[type], className), ...restProps, children: [jsxs("span", { className: "inline-flex items-start gap-2 min-w-0", children: [iconNode && jsx("span", { className: "shrink-0 inline-flex mt-0.5", children: iconNode }), jsxs("span", { className: "inline-flex flex-col gap-0.5 min-w-0", children: [title && jsx("span", { className: "font-semibold", children: title }), jsx("span", { className: "inline-flex items-center", children: message !== null && message !== void 0 ? message : children })] })] }), removable && (jsx(Button, { iconOnly: true, "aria-label": "Dismiss alert", size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/10 dark:hover:bg-white/10 shrink-0", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), "data-testid": "alert-remove-btn", children: jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
469
|
+
});
|
|
470
|
+
Alert.displayName = 'Alert';
|
|
471
|
+
|
|
472
|
+
const ThemeClassMap = {
|
|
473
|
+
success: 'bg-[var(--ui-success-light)] text-[var(--ui-success-text)] ring-[var(--ui-success-ring-subtle)]',
|
|
474
|
+
danger: 'bg-[var(--ui-danger-light)] text-[var(--ui-danger-text)] ring-[var(--ui-danger-ring-subtle)]',
|
|
475
|
+
warning: 'bg-[var(--ui-warning-light)] text-[var(--ui-warning-text)] ring-[var(--ui-warning-ring-subtle)]',
|
|
476
|
+
info: 'bg-[var(--ui-info-light)] text-[var(--ui-info-text)] ring-[var(--ui-info-ring-subtle)]',
|
|
477
|
+
primary: 'bg-[var(--ui-info-light)] text-[var(--ui-info-text)] ring-[var(--ui-info-ring-subtle)]',
|
|
478
|
+
secondary: 'bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 ring-[var(--ui-secondary-ring-subtle)]',
|
|
479
|
+
};
|
|
480
|
+
const SIZE_CLASS$1 = {
|
|
481
|
+
sm: 'text-xs py-0.5 px-2',
|
|
482
|
+
md: 'text-xs py-1 px-3',
|
|
483
|
+
};
|
|
484
|
+
const Badge = forwardRef((props, ref) => {
|
|
485
|
+
const { theme = 'info', className, children, removable = false, rounded = false, onRemove, size = 'md', icon, ...restProps } = props;
|
|
486
|
+
return (jsxs(TextContent, { ref: ref, className: buildClassName('inline-flex items-center gap-1 font-medium ring-1 ring-inset', SIZE_CLASS$1[size], ThemeClassMap[theme] || ThemeClassMap.info, rounded ? 'rounded-full' : 'rounded-md', icon ? 'pl-2' : '', removable ? 'pr-1' : '', className), "data-testid": `badge-${theme}`, ...restProps, children: [icon && jsx("span", { className: "shrink-0 inline-flex", children: icon }), children, removable && (jsx(SvgX, { className: "size-4 shrink-0 hover:bg-black/10 dark:hover:bg-white/10 rounded-sm cursor-pointer", role: "button", tabIndex: 0, "aria-label": "Remove", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), onKeyDown: (e) => {
|
|
487
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
488
|
+
e.preventDefault();
|
|
489
|
+
onRemove === null || onRemove === void 0 ? void 0 : onRemove();
|
|
490
|
+
}
|
|
491
|
+
} }))] }));
|
|
492
|
+
});
|
|
493
|
+
Badge.displayName = 'Badge';
|
|
494
|
+
|
|
495
|
+
var _path$c;
|
|
496
|
+
function _extends$c() { return _extends$c = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$c.apply(null, arguments); }
|
|
497
|
+
var SvgTriangleAlert = function SvgTriangleAlert(props) {
|
|
498
|
+
return /*#__PURE__*/React.createElement("svg", _extends$c({
|
|
499
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
500
|
+
width: 24,
|
|
501
|
+
height: 24,
|
|
502
|
+
fill: "none",
|
|
503
|
+
stroke: "currentColor",
|
|
504
|
+
strokeLinecap: "round",
|
|
505
|
+
strokeLinejoin: "round",
|
|
506
|
+
strokeWidth: 2,
|
|
507
|
+
className: "lucide lucide-triangle-alert-icon lucide-triangle-alert",
|
|
508
|
+
viewBox: "0 0 24 24"
|
|
509
|
+
}, props), _path$c || (_path$c = /*#__PURE__*/React.createElement("path", {
|
|
510
|
+
d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01"
|
|
511
|
+
})));
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
var _circle$2, _path$b;
|
|
515
|
+
function _extends$b() { return _extends$b = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$b.apply(null, arguments); }
|
|
516
|
+
var SvgCircleCheck = function SvgCircleCheck(props) {
|
|
517
|
+
return /*#__PURE__*/React.createElement("svg", _extends$b({
|
|
518
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
519
|
+
width: 24,
|
|
520
|
+
height: 24,
|
|
521
|
+
fill: "none",
|
|
522
|
+
stroke: "currentColor",
|
|
523
|
+
strokeLinecap: "round",
|
|
524
|
+
strokeLinejoin: "round",
|
|
525
|
+
strokeWidth: 2,
|
|
526
|
+
className: "lucide lucide-circle-check-icon lucide-circle-check",
|
|
527
|
+
viewBox: "0 0 24 24"
|
|
528
|
+
}, props), _circle$2 || (_circle$2 = /*#__PURE__*/React.createElement("circle", {
|
|
529
|
+
cx: 12,
|
|
530
|
+
cy: 12,
|
|
531
|
+
r: 10
|
|
532
|
+
})), _path$b || (_path$b = /*#__PURE__*/React.createElement("path", {
|
|
533
|
+
d: "m9 12 2 2 4-4"
|
|
534
|
+
})));
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const sizeMap = {
|
|
538
|
+
xs: 'size-4',
|
|
539
|
+
sm: 'size-5',
|
|
540
|
+
md: 'size-6',
|
|
541
|
+
lg: 'size-8',
|
|
542
|
+
xl: 'size-10',
|
|
543
|
+
};
|
|
544
|
+
const IconMap = {
|
|
545
|
+
info: SvgInfo,
|
|
546
|
+
error: SvgCircleX,
|
|
547
|
+
success: SvgCircleCheck,
|
|
548
|
+
warning: SvgTriangleAlert,
|
|
445
549
|
};
|
|
446
550
|
const TypeClassMap = {
|
|
447
551
|
info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',
|
|
@@ -509,6 +613,51 @@ const BodyText = forwardRef((props, ref) => {
|
|
|
509
613
|
});
|
|
510
614
|
BodyText.displayName = 'BodyText';
|
|
511
615
|
|
|
616
|
+
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
|
|
617
|
+
const handleTabClick = (item) => {
|
|
618
|
+
var _a;
|
|
619
|
+
if (item.disabled)
|
|
620
|
+
return;
|
|
621
|
+
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
622
|
+
onChange(item.id);
|
|
623
|
+
};
|
|
624
|
+
const themeStyles = {
|
|
625
|
+
light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
|
|
626
|
+
dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
|
|
627
|
+
primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
|
|
628
|
+
}[theme];
|
|
629
|
+
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) => {
|
|
630
|
+
const isActive = item.id === activeId;
|
|
631
|
+
const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
|
|
632
|
+
const activeItemColor = {
|
|
633
|
+
light: 'text-blue-600 dark:text-blue-400 font-bold',
|
|
634
|
+
dark: 'text-white font-bold',
|
|
635
|
+
primary: 'text-white font-bold',
|
|
636
|
+
}[theme];
|
|
637
|
+
const inactiveItemColor = {
|
|
638
|
+
light: 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',
|
|
639
|
+
dark: 'text-gray-400 hover:text-gray-200 font-medium',
|
|
640
|
+
primary: 'text-blue-200 hover:text-white font-medium',
|
|
641
|
+
}[theme];
|
|
642
|
+
const pillActiveStyles = {
|
|
643
|
+
light: 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',
|
|
644
|
+
dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',
|
|
645
|
+
primary: 'bg-white/25 text-white shadow-xs scale-105',
|
|
646
|
+
}[theme];
|
|
647
|
+
const badgeColor = {
|
|
648
|
+
danger: 'bg-red-500 text-white',
|
|
649
|
+
info: 'bg-blue-500 text-white',
|
|
650
|
+
success: 'bg-emerald-500 text-white',
|
|
651
|
+
}[item.badgeVariant || 'danger'];
|
|
652
|
+
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'
|
|
653
|
+
? buildClassName('px-4 py-1 rounded-full', isActive
|
|
654
|
+
? pillActiveStyles
|
|
655
|
+
: 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
|
|
656
|
+
: '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));
|
|
657
|
+
}) }));
|
|
658
|
+
}
|
|
659
|
+
BottomNavigation.displayName = 'BottomNavigation';
|
|
660
|
+
|
|
512
661
|
var _path$a;
|
|
513
662
|
function _extends$a() { return _extends$a = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$a.apply(null, arguments); }
|
|
514
663
|
var SvgSlash = function SvgSlash(props) {
|
|
@@ -664,10 +813,10 @@ const ButtonGroup = ({ children, orientation = 'horizontal', theme = 'secondary'
|
|
|
664
813
|
(isVertical
|
|
665
814
|
? resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
666
815
|
? 'border-t border-white/25 dark:border-white/20'
|
|
667
|
-
: 'border-t border-
|
|
816
|
+
: 'border-t border-[var(--ui-border)]'
|
|
668
817
|
: resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
669
818
|
? 'border-l border-white/25 dark:border-white/20'
|
|
670
|
-
: 'border-l border-
|
|
819
|
+
: 'border-l border-[var(--ui-border)]'),
|
|
671
820
|
], fullWidth && 'flex-1'),
|
|
672
821
|
});
|
|
673
822
|
}) }));
|
|
@@ -688,27 +837,33 @@ const ASPECT_RATIO_CLASS = {
|
|
|
688
837
|
video: 'aspect-video',
|
|
689
838
|
wide: 'aspect-[21/9]',
|
|
690
839
|
};
|
|
840
|
+
function ChevronRightIcon$1({ className = 'size-4' }) {
|
|
841
|
+
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" }) }));
|
|
842
|
+
}
|
|
691
843
|
const Card = forwardRef(({ as, ...props }, ref) => {
|
|
692
|
-
const { variant = 'outlined', radius = 'xl', hoverable = false, clickable = false, selected = false, bordered = true, compact = false, zeroPadding = false, ...rest } = props;
|
|
844
|
+
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;
|
|
693
845
|
const Component = as || 'div';
|
|
694
846
|
const { className, ...cleanRest } = rest;
|
|
847
|
+
const isClickable = clickable || Boolean(onClick);
|
|
695
848
|
const isOutlined = variant === 'outlined' && bordered;
|
|
696
849
|
const isElevated = variant === 'elevated';
|
|
697
850
|
const isFilled = variant === 'filled';
|
|
698
851
|
const isGhost = variant === 'ghost';
|
|
699
|
-
const classes = buildClassName('block transition-all duration-
|
|
852
|
+
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',
|
|
700
853
|
// Surface variants
|
|
701
854
|
isOutlined && 'bg-white dark:bg-gray-900 border border-[var(--ui-border)]', isElevated &&
|
|
702
|
-
'bg-white dark:bg-gray-900 border border-
|
|
703
|
-
// Hoverable & Clickable states
|
|
704
|
-
hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80',
|
|
705
|
-
|
|
855
|
+
'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',
|
|
856
|
+
// Hoverable & Clickable mobile/web touch states
|
|
857
|
+
hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80', isClickable &&
|
|
858
|
+
'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);
|
|
859
|
+
const hasHeaderRow = title || subtitle || leading || trailing || badge || showChevron;
|
|
860
|
+
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$1, { className: "size-4 text-gray-400" })] }))] })), children] }));
|
|
706
861
|
});
|
|
707
|
-
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-
|
|
862
|
+
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 }));
|
|
708
863
|
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 }));
|
|
709
864
|
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 }));
|
|
710
865
|
const CardContent = ({ className, children, ...props }) => (jsx("div", { className: buildClassName('space-y-3', className), ...props, children: children }));
|
|
711
|
-
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-
|
|
866
|
+
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 }));
|
|
712
867
|
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 }) }));
|
|
713
868
|
Card.Header = CardHeader;
|
|
714
869
|
Card.Title = CardTitle;
|
|
@@ -728,19 +883,19 @@ Label.displayName = 'Label';
|
|
|
728
883
|
const sizeStyles = {
|
|
729
884
|
sm: {
|
|
730
885
|
box: 'size-3.5',
|
|
731
|
-
svg: '
|
|
886
|
+
svg: 'size-2.75',
|
|
732
887
|
text: 'text-xs',
|
|
733
888
|
subtext: 'text-[11px]',
|
|
734
889
|
},
|
|
735
890
|
md: {
|
|
736
891
|
box: 'size-4.5',
|
|
737
|
-
svg: '
|
|
892
|
+
svg: 'size-3.5',
|
|
738
893
|
text: 'text-sm',
|
|
739
894
|
subtext: 'text-xs',
|
|
740
895
|
},
|
|
741
896
|
lg: {
|
|
742
897
|
box: 'size-5.5',
|
|
743
|
-
svg: '
|
|
898
|
+
svg: 'size-4.25',
|
|
744
899
|
text: 'text-base',
|
|
745
900
|
subtext: 'text-sm',
|
|
746
901
|
},
|
|
@@ -761,19 +916,19 @@ const Checkbox = forwardRef((props, ref) => {
|
|
|
761
916
|
const isCard = variant === 'card';
|
|
762
917
|
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsx("div", { className: buildClassName(isCard
|
|
763
918
|
? 'rounded-xl border p-3.5 transition-all duration-150 relative'
|
|
764
|
-
: 'flex items-
|
|
919
|
+
: 'flex items-center', isCard &&
|
|
765
920
|
(disabled
|
|
766
|
-
? 'border-
|
|
921
|
+
? 'border-[var(--ui-border-muted)] bg-gray-50/50 dark:bg-gray-900/40 opacity-70'
|
|
767
922
|
: checked || indeterminate
|
|
768
923
|
? 'border-blue-500/80 bg-blue-50/30 dark:bg-blue-950/20 dark:border-blue-500/60 shadow-xs'
|
|
769
|
-
: 'border-
|
|
770
|
-
? 'border-
|
|
771
|
-
: 'bg-white dark:bg-gray-700 border-
|
|
772
|
-
'!bg-blue-600 !border-blue-600 dark:!bg-blue-600 dark:!border-blue-600', className) }), !indeterminate && (jsx("span", { className: buildClassName('absolute text-white pointer-events-none transition-opacity
|
|
924
|
+
: 'border-[var(--ui-border)] bg-white dark:bg-gray-900 hover:border-gray-300 dark:hover:border-gray-700 shadow-2xs'), containerClass), children: jsxs("label", { htmlFor: checkboxId, className: buildClassName('inline-flex relative select-none w-full', description ? 'items-start' : 'items-center', disabled ? 'cursor-not-allowed opacity-70' : 'cursor-pointer'), children: [jsxs("div", { className: "relative inline-flex items-center justify-center shrink-0", children: [jsx("input", { ref: innerRef, ...rest, id: checkboxId, name: name, type: "checkbox", disabled: disabled, checked: checked, onChange: onChange, "aria-checked": indeterminate ? 'mixed' : checked, className: buildClassName('peer cursor-pointer transition-all appearance-none rounded', currentSize.box, 'border focus:ring-2 focus:ring-offset-2', 'checked:bg-blue-600 checked:border-blue-600 dark:checked:bg-blue-600 dark:checked:border-blue-600', 'focus:ring-[var(--ui-focus-ring)] dark:focus:ring-offset-gray-900', disabled
|
|
925
|
+
? 'border-[var(--ui-border-muted)] bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
926
|
+
: 'bg-white dark:bg-gray-700 border-[var(--ui-border)] hover:border-gray-400 dark:hover:border-gray-500', indeterminate &&
|
|
927
|
+
'!bg-blue-600 !border-blue-600 dark:!bg-blue-600 dark:!border-blue-600', className) }), !indeterminate && (jsx("span", { className: buildClassName('absolute inset-0 flex items-center justify-center text-white pointer-events-none transition-opacity', checked !== undefined
|
|
773
928
|
? checked
|
|
774
929
|
? 'opacity-100'
|
|
775
930
|
: 'opacity-0'
|
|
776
|
-
: 'opacity-0 peer-checked:opacity-100'), children: jsx("svg", {
|
|
931
|
+
: 'opacity-0 peer-checked:opacity-100'), children: jsx("svg", { className: currentSize.svg, viewBox: "0 0 20 20", fill: "currentColor", children: jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }) })), indeterminate && (jsx("span", { className: "absolute inset-0 flex items-center justify-center text-white pointer-events-none opacity-100 z-10", children: jsx("svg", { className: currentSize.svg, viewBox: "0 0 20 20", fill: "currentColor", children: jsx("path", { fillRule: "evenodd", d: "M4 10a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1z", clipRule: "evenodd" }) }) }))] }), (label || description) && (jsxs("div", { className: "ml-2.5 flex flex-col justify-center min-w-0 flex-1", children: [label && (jsx(Label, { htmlFor: checkboxId, className: buildClassName(disabled
|
|
777
932
|
? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
|
|
778
933
|
: 'cursor-pointer text-gray-800 dark:text-gray-200 font-medium', currentSize.text, labelClass), children: label })), description && (jsx("span", { className: buildClassName('mt-0.5 text-gray-500 dark:text-gray-400 font-normal leading-normal', currentSize.subtext), children: description }))] }))] }) }), (error || helperText) && (jsx("div", { className: "mt-1.5 ml-0.5", children: error ? (jsx(TextContent, { error: true, small: true, children: error })) : (jsx(TextContent, { muted: true, small: true, children: helperText })) }))] }));
|
|
779
934
|
});
|
|
@@ -842,7 +997,7 @@ const CheckboxGroup = (props) => {
|
|
|
842
997
|
: inline
|
|
843
998
|
? 'flex flex-wrap gap-3'
|
|
844
999
|
: 'flex flex-col gap-3';
|
|
845
|
-
return (jsxs("div", { className: buildClassName('mb-3 space-y-3', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, children: label }), labelHint && (jsx(BodyText, { muted: true, small: true, children: labelHint }))] })), showSelectAll && items.length > 0 && (jsx("div", { className: "pb-1 border-b border-
|
|
1000
|
+
return (jsxs("div", { className: buildClassName('mb-3 space-y-3', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, children: label }), labelHint && (jsx(BodyText, { muted: true, small: true, children: labelHint }))] })), showSelectAll && items.length > 0 && (jsx("div", { className: "pb-1 border-b border-[var(--ui-border)]", children: jsx(Checkbox, { id: `${groupId}-select-all`, label: selectAllLabel, size: size, variant: variant, checked: allSelected, indeterminate: isIndeterminate, disabled: disabled || enabledItems.length === 0, onChange: handleSelectAllChange }) })), jsx("div", { className: layoutClass, children: items.map((item, index) => {
|
|
846
1001
|
const key = typeof item.value === 'string' || typeof item.value === 'number' ? item.value : index;
|
|
847
1002
|
return (jsx(Checkbox, { name: name, id: `${groupId}-${String(item.value)}`, label: item.label, description: item.description, value: String(item.value), size: size, variant: variant, disabled: disabled || item.disabled, checked: currentValue.includes(item.value), onChange: handleGroupChange }, key));
|
|
848
1003
|
}) }), (error || helperText) && (jsx("div", { className: "mt-1.5 ml-0.5", children: error ? (jsx(TextContent, { error: true, small: true, children: error })) : (jsx(TextContent, { muted: true, small: true, children: helperText })) }))] }));
|
|
@@ -922,27 +1077,8 @@ const usePagination = ({ totalPages, currentPage, siblingCount = 1, // number of
|
|
|
922
1077
|
|
|
923
1078
|
var _path$9;
|
|
924
1079
|
function _extends$9() { return _extends$9 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$9.apply(null, arguments); }
|
|
925
|
-
var SvgChevronLeft = function SvgChevronLeft(props) {
|
|
926
|
-
return /*#__PURE__*/React.createElement("svg", _extends$9({
|
|
927
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
928
|
-
width: 24,
|
|
929
|
-
height: 24,
|
|
930
|
-
fill: "none",
|
|
931
|
-
stroke: "currentColor",
|
|
932
|
-
strokeLinecap: "round",
|
|
933
|
-
strokeLinejoin: "round",
|
|
934
|
-
strokeWidth: 2,
|
|
935
|
-
className: "lucide lucide-chevron-left-icon lucide-chevron-left",
|
|
936
|
-
viewBox: "0 0 24 24"
|
|
937
|
-
}, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
|
|
938
|
-
d: "m15 18-6-6 6-6"
|
|
939
|
-
})));
|
|
940
|
-
};
|
|
941
|
-
|
|
942
|
-
var _path$8;
|
|
943
|
-
function _extends$8() { return _extends$8 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$8.apply(null, arguments); }
|
|
944
1080
|
var SvgChevronRight = function SvgChevronRight(props) {
|
|
945
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1081
|
+
return /*#__PURE__*/React.createElement("svg", _extends$9({
|
|
946
1082
|
xmlns: "http://www.w3.org/2000/svg",
|
|
947
1083
|
width: 24,
|
|
948
1084
|
height: 24,
|
|
@@ -953,7 +1089,7 @@ var SvgChevronRight = function SvgChevronRight(props) {
|
|
|
953
1089
|
strokeWidth: 2,
|
|
954
1090
|
className: "lucide lucide-chevron-right-icon lucide-chevron-right",
|
|
955
1091
|
viewBox: "0 0 24 24"
|
|
956
|
-
}, props), _path$
|
|
1092
|
+
}, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
|
|
957
1093
|
d: "m9 18 6-6-6-6"
|
|
958
1094
|
})));
|
|
959
1095
|
};
|
|
@@ -1075,10 +1211,10 @@ const useRowSelection = ({ items, getKey, selectedRowKeys, defaultSelectedRowKey
|
|
|
1075
1211
|
};
|
|
1076
1212
|
};
|
|
1077
1213
|
|
|
1078
|
-
var _path$
|
|
1079
|
-
function _extends$
|
|
1214
|
+
var _path$8;
|
|
1215
|
+
function _extends$8() { return _extends$8 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$8.apply(null, arguments); }
|
|
1080
1216
|
var SvgArrowDownWideNarrow = function SvgArrowDownWideNarrow(props) {
|
|
1081
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1217
|
+
return /*#__PURE__*/React.createElement("svg", _extends$8({
|
|
1082
1218
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1083
1219
|
width: 24,
|
|
1084
1220
|
height: 24,
|
|
@@ -1089,15 +1225,15 @@ var SvgArrowDownWideNarrow = function SvgArrowDownWideNarrow(props) {
|
|
|
1089
1225
|
strokeWidth: 2,
|
|
1090
1226
|
className: "lucide lucide-arrow-down-wide-narrow-icon lucide-arrow-down-wide-narrow",
|
|
1091
1227
|
viewBox: "0 0 24 24"
|
|
1092
|
-
}, props), _path$
|
|
1228
|
+
}, props), _path$8 || (_path$8 = /*#__PURE__*/React.createElement("path", {
|
|
1093
1229
|
d: "m3 16 4 4 4-4M7 20V4M11 4h10M11 8h7M11 12h4"
|
|
1094
1230
|
})));
|
|
1095
1231
|
};
|
|
1096
1232
|
|
|
1097
|
-
var _path$
|
|
1098
|
-
function _extends$
|
|
1233
|
+
var _path$7;
|
|
1234
|
+
function _extends$7() { return _extends$7 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$7.apply(null, arguments); }
|
|
1099
1235
|
var SvgArrowDownNarrowWide = function SvgArrowDownNarrowWide(props) {
|
|
1100
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1236
|
+
return /*#__PURE__*/React.createElement("svg", _extends$7({
|
|
1101
1237
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1102
1238
|
width: 24,
|
|
1103
1239
|
height: 24,
|
|
@@ -1108,15 +1244,15 @@ var SvgArrowDownNarrowWide = function SvgArrowDownNarrowWide(props) {
|
|
|
1108
1244
|
strokeWidth: 2,
|
|
1109
1245
|
className: "lucide lucide-arrow-down-narrow-wide-icon lucide-arrow-down-narrow-wide",
|
|
1110
1246
|
viewBox: "0 0 24 24"
|
|
1111
|
-
}, props), _path$
|
|
1247
|
+
}, props), _path$7 || (_path$7 = /*#__PURE__*/React.createElement("path", {
|
|
1112
1248
|
d: "m3 16 4 4 4-4M7 20V4M11 4h4M11 8h7M11 12h10"
|
|
1113
1249
|
})));
|
|
1114
1250
|
};
|
|
1115
1251
|
|
|
1116
|
-
var _path$
|
|
1117
|
-
function _extends$
|
|
1252
|
+
var _path$6;
|
|
1253
|
+
function _extends$6() { return _extends$6 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$6.apply(null, arguments); }
|
|
1118
1254
|
var SvgArrowDownAz = function SvgArrowDownAz(props) {
|
|
1119
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1255
|
+
return /*#__PURE__*/React.createElement("svg", _extends$6({
|
|
1120
1256
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1121
1257
|
width: 24,
|
|
1122
1258
|
height: 24,
|
|
@@ -1127,15 +1263,15 @@ var SvgArrowDownAz = function SvgArrowDownAz(props) {
|
|
|
1127
1263
|
strokeWidth: 2,
|
|
1128
1264
|
className: "lucide lucide-arrow-down-az-icon lucide-arrow-down-a-z",
|
|
1129
1265
|
viewBox: "0 0 24 24"
|
|
1130
|
-
}, props), _path$
|
|
1266
|
+
}, props), _path$6 || (_path$6 = /*#__PURE__*/React.createElement("path", {
|
|
1131
1267
|
d: "m3 16 4 4 4-4M7 20V4M20 8h-5M15 10V6.5a2.5 2.5 0 0 1 5 0V10M15 14h5l-5 6h5"
|
|
1132
1268
|
})));
|
|
1133
1269
|
};
|
|
1134
1270
|
|
|
1135
|
-
var _path$
|
|
1136
|
-
function _extends$
|
|
1271
|
+
var _path$5;
|
|
1272
|
+
function _extends$5() { return _extends$5 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$5.apply(null, arguments); }
|
|
1137
1273
|
var SvgArrowDownZa = function SvgArrowDownZa(props) {
|
|
1138
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1274
|
+
return /*#__PURE__*/React.createElement("svg", _extends$5({
|
|
1139
1275
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1140
1276
|
width: 24,
|
|
1141
1277
|
height: 24,
|
|
@@ -1146,15 +1282,15 @@ var SvgArrowDownZa = function SvgArrowDownZa(props) {
|
|
|
1146
1282
|
strokeWidth: 2,
|
|
1147
1283
|
className: "lucide lucide-arrow-down-za-icon lucide-arrow-down-z-a",
|
|
1148
1284
|
viewBox: "0 0 24 24"
|
|
1149
|
-
}, props), _path$
|
|
1285
|
+
}, props), _path$5 || (_path$5 = /*#__PURE__*/React.createElement("path", {
|
|
1150
1286
|
d: "m3 16 4 4 4-4M7 4v16M15 4h5l-5 6h5M15 20v-3.5a2.5 2.5 0 0 1 5 0V20M20 18h-5"
|
|
1151
1287
|
})));
|
|
1152
1288
|
};
|
|
1153
1289
|
|
|
1154
|
-
var _path$
|
|
1155
|
-
function _extends$
|
|
1290
|
+
var _path$4;
|
|
1291
|
+
function _extends$4() { return _extends$4 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$4.apply(null, arguments); }
|
|
1156
1292
|
var SvgArrowUpDown = function SvgArrowUpDown(props) {
|
|
1157
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1293
|
+
return /*#__PURE__*/React.createElement("svg", _extends$4({
|
|
1158
1294
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1159
1295
|
width: 24,
|
|
1160
1296
|
height: 24,
|
|
@@ -1165,7 +1301,7 @@ var SvgArrowUpDown = function SvgArrowUpDown(props) {
|
|
|
1165
1301
|
strokeWidth: 2,
|
|
1166
1302
|
className: "lucide lucide-arrow-up-down-icon lucide-arrow-up-down",
|
|
1167
1303
|
viewBox: "0 0 24 24"
|
|
1168
|
-
}, props), _path$
|
|
1304
|
+
}, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
|
|
1169
1305
|
d: "m21 16-4 4-4-4M17 20V4M3 8l4-4 4 4M7 4v16"
|
|
1170
1306
|
})));
|
|
1171
1307
|
};
|
|
@@ -1207,7 +1343,7 @@ const autoSortItems = (items, column, sort) => {
|
|
|
1207
1343
|
return 0;
|
|
1208
1344
|
});
|
|
1209
1345
|
};
|
|
1210
|
-
function DataTable({ items, columns, sorting = {}, onSort, loading, pagination, setPagination = () => { }, emptyMessage = 'No data found', containerClass = '', wrapperClass = '', tableClass = '', headClass = '', footerRow, rowKey = 'id', onRowClick, rowClass, density = 'default', striped = false, layout = 'auto', selectable = false, selectedRowKeys, defaultSelectedRowKeys, onSelectionChange, isRowSelectable, paginationContainerClass, }) {
|
|
1346
|
+
function DataTable({ items, columns, sorting = {}, onSort, loading, pagination, setPagination = () => { }, emptyMessage = 'No data found', containerClass = '', wrapperClass = '', tableClass = '', headClass = '', footerRow, rowKey = 'id', onRowClick, rowClass, density = 'default', striped = false, layout = 'auto', selectable = false, selectedRowKeys, defaultSelectedRowKeys, onSelectionChange, isRowSelectable, stickyHeader = true, stickyPagination = true, paginationContainerClass, }) {
|
|
1211
1347
|
const internalSorting = useRef({});
|
|
1212
1348
|
const [sortedItems, setSortedItems] = useState(items);
|
|
1213
1349
|
useEffect(() => {
|
|
@@ -1252,12 +1388,13 @@ function DataTable({ items, columns, sorting = {}, onSort, loading, pagination,
|
|
|
1252
1388
|
});
|
|
1253
1389
|
const densityCellClass = DENSITY_CELL_CLASS$2[density];
|
|
1254
1390
|
const colSize = columns.length + (selectable ? 1 : 0);
|
|
1255
|
-
|
|
1391
|
+
const wrapperHasOverflow = /\boverflow-(x-|y-)?(auto|hidden|scroll|visible|clip)\b/.test(wrapperClass);
|
|
1392
|
+
return (jsxs("div", { className: buildClassName('w-full rounded-lg relative', containerClass), children: [jsx("div", { className: buildClassName(!wrapperHasOverflow && 'overflow-x-auto', 'rounded-lg border border-[var(--ui-border)]', wrapperClass, pagination && 'rounded-b-none border-b-0'), children: jsxs(Table, { className: buildClassName('relative w-full max-w-full h-fit', tableClass), layout: layout, children: [jsxs(TableHead, { className: headClass, children: [selectable && (jsx(TableHeaderCell, { className: buildClassName('bg-gray-50 dark:bg-gray-800 w-px', densityCellClass, stickyHeader && 'sticky top-0 z-20 shadow-[0_1px_2px_rgba(0,0,0,0.06)]'), children: jsx(Checkbox, { "aria-label": "Select all rows", checked: allSelected, ref: (el) => {
|
|
1256
1393
|
if (el)
|
|
1257
1394
|
el.indeterminate = someSelected;
|
|
1258
|
-
}, onChange: toggleAll }) })), columns.map((column) => (jsx(TableHeaderCell, { align: column.headerAlign, style: { width: column.width || 'auto' }, className: buildClassName('bg-gray-50 dark:bg-gray-800', densityCellClass, column.sticky === 'left' &&
|
|
1259
|
-
'sticky left-0 z-
|
|
1260
|
-
'sticky right-0 z-
|
|
1395
|
+
}, onChange: toggleAll }) })), columns.map((column) => (jsx(TableHeaderCell, { align: column.headerAlign, style: { width: column.width || 'auto' }, className: buildClassName('bg-gray-50 dark:bg-gray-800', densityCellClass, stickyHeader && 'sticky top-0 z-20 shadow-[0_1px_2px_rgba(0,0,0,0.06)]', column.sticky === 'left' &&
|
|
1396
|
+
'sticky left-0 z-30 shadow-[2px_0_6px_rgba(0,0,0,0.06)]', column.sticky === 'right' &&
|
|
1397
|
+
'sticky right-0 z-30 shadow-[-2px_0_6px_rgba(0,0,0,0.06)]', column.headerClass), children: jsxs(TextContent, { role: column.sortable ? 'button' : undefined, className: buildClassName('group', column.sortable && 'inline-flex items-center gap-2 cursor-pointer select-none'), onClick: () => handleSort(column), children: [jsx(TextContent, { className: "shrink-0", children: column.label }), column.sortable ? getSortIcon(sorting[column.name]) : null] }) }, column.name)))] }), jsx(TableBody, { loading: loading, colSize: colSize, rowSize: (pagination === null || pagination === void 0 ? void 0 : pagination.limit) || 5, children: !loading && sortedItems.length === 0 ? (jsx(EmptyTableRow, { colSpan: colSize, children: emptyMessage })) : (sortedItems.map((item, idx) => {
|
|
1261
1398
|
const key = getKey(item, idx);
|
|
1262
1399
|
const rowSelectable = !isRowSelectable || isRowSelectable(item);
|
|
1263
1400
|
return (jsxs(TableRow, { className: buildClassName('group', onRowClick && 'cursor-pointer', striped && idx % 2 === 1 && 'bg-gray-50 dark:bg-gray-800/40', getRowClass(item, idx)), onClick: onRowClick ? () => onRowClick(item, idx) : undefined, children: [selectable && (jsx(TableCell, { className: buildClassName(densityCellClass, striped && idx % 2 === 1 && 'bg-gray-50 dark:bg-gray-800/40'), children: jsx("span", { onClick: (e) => e.stopPropagation(), children: jsx(Checkbox, { "aria-label": "Select row", checked: isSelected(key), disabled: !rowSelectable, onChange: () => toggleRow(key) }) }) })), columns.map((column) => {
|
|
@@ -1268,7 +1405,7 @@ function DataTable({ items, columns, sorting = {}, onSort, loading, pagination,
|
|
|
1268
1405
|
? column.render(item)
|
|
1269
1406
|
: ((_a = get(item, column.name)) !== null && _a !== void 0 ? _a : 'Not set') }, column.name));
|
|
1270
1407
|
})] }, key));
|
|
1271
|
-
})) }), footerRow && jsx(TableFoot, { children: footerRow })] }) }), pagination && (jsx(Pagination, { ...pagination, className: buildClassName('rounded-b-lg border
|
|
1408
|
+
})) }), footerRow && jsx(TableFoot, { children: footerRow })] }) }), pagination && (jsx(Pagination, { ...pagination, className: buildClassName('rounded-b-lg border border-[var(--ui-border)]', stickyPagination && 'sticky bottom-0 z-20 bg-white dark:bg-gray-800', paginationContainerClass), onChange: setPagination }))] }));
|
|
1272
1409
|
}
|
|
1273
1410
|
DataTable.displayName = 'DataTable';
|
|
1274
1411
|
|
|
@@ -1383,8 +1520,8 @@ const DetailedInformation = forwardRef((props, ref) => {
|
|
|
1383
1520
|
const isMultiColumn = columns > 1;
|
|
1384
1521
|
return (jsxs("div", { ref: ref, className: buildClassName(isCard
|
|
1385
1522
|
? compact
|
|
1386
|
-
? 'p-3 sm:p-4 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-
|
|
1387
|
-
: 'p-4 sm:p-6 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-
|
|
1523
|
+
? 'p-3 sm:p-4 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-[var(--ui-border)]'
|
|
1524
|
+
: 'p-4 sm:p-6 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-[var(--ui-border)]'
|
|
1388
1525
|
: isBordered
|
|
1389
1526
|
? compact
|
|
1390
1527
|
? 'p-3 sm:p-4 border border-[var(--ui-border)] rounded-2xl'
|
|
@@ -1402,8 +1539,8 @@ const DetailedInformation = forwardRef((props, ref) => {
|
|
|
1402
1539
|
const isVertical = layout === 'vertical' || isMultiColumn;
|
|
1403
1540
|
return (jsxs("div", { className: buildClassName(isMultiColumn && isCard
|
|
1404
1541
|
? compact
|
|
1405
|
-
? 'p-3 bg-white dark:bg-gray-900 rounded-xl border border-
|
|
1406
|
-
: 'p-4 bg-white dark:bg-gray-900 rounded-xl border border-
|
|
1542
|
+
? 'p-3 bg-white dark:bg-gray-900 rounded-xl border border-[var(--ui-border)] shadow-2xs flex flex-col gap-1'
|
|
1543
|
+
: 'p-4 bg-white dark:bg-gray-900 rounded-xl border border-[var(--ui-border)] shadow-2xs flex flex-col gap-1'
|
|
1407
1544
|
: isVertical
|
|
1408
1545
|
? 'flex flex-col gap-1 py-2 px-1'
|
|
1409
1546
|
: 'grid grid-cols-3 gap-4 items-center py-2.5 px-1', compact && !isMultiColumn ? 'py-1.5' : ''), children: [jsxs("dt", { className: buildClassName('text-sm/6 font-medium text-gray-900 dark:text-gray-100 flex items-center gap-1.5', labelClass, detail.labelClass), children: [detail.icon && jsx("span", { className: "shrink-0 text-gray-400", children: detail.icon }), jsx("span", { children: detail.label }), detail.helpText && (jsx("span", { className: "text-xs text-gray-400 font-normal cursor-help", title: detail.helpText, children: "(?)" }))] }), jsx("dd", { className: buildClassName('text-sm/6 text-gray-700 dark:text-gray-300', !isVertical && 'sm:col-span-2 sm:mt-0', detail.contentClass), children: detail.copyable && copyText ? (jsx(CopyableValue, { text: copyText, children: displayValue })) : (displayValue) })] }, detail.label || index));
|
|
@@ -1416,41 +1553,6 @@ const Dot = ({ as = 'span', className, ...props }) => React__default.createEleme
|
|
|
1416
1553
|
...props,
|
|
1417
1554
|
});
|
|
1418
1555
|
|
|
1419
|
-
const alignmentMap = {
|
|
1420
|
-
center: 'items-center justify-center h-full',
|
|
1421
|
-
start: 'justify-start h-full',
|
|
1422
|
-
end: 'justify-end h-full',
|
|
1423
|
-
top: 'items-start justify-center w-full',
|
|
1424
|
-
bottom: 'items-end justify-center h-full',
|
|
1425
|
-
};
|
|
1426
|
-
const panelAlignmentMap = {
|
|
1427
|
-
center: 'data-[closed]:scale-95 rounded-2xl',
|
|
1428
|
-
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
1429
|
-
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
1430
|
-
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
1431
|
-
bottom: 'data-[closed]:translate-y-1/2 rounded-t-2xl md:rounded-t-3xl max-h-[92svh]',
|
|
1432
|
-
};
|
|
1433
|
-
const panelSizeMap = {
|
|
1434
|
-
xs: 'max-w-xs',
|
|
1435
|
-
sm: 'max-w-sm',
|
|
1436
|
-
md: 'max-w-md',
|
|
1437
|
-
lg: 'max-w-lg',
|
|
1438
|
-
xl: 'max-w-xl',
|
|
1439
|
-
'2xl': 'max-w-2xl',
|
|
1440
|
-
full: 'w-full',
|
|
1441
|
-
};
|
|
1442
|
-
const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align = 'end', size = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
|
|
1443
|
-
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
1444
|
-
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
1445
|
-
const handleDialogClose = () => {
|
|
1446
|
-
if (closeOnOutsideClick) {
|
|
1447
|
-
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
1448
|
-
}
|
|
1449
|
-
};
|
|
1450
|
-
return (jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsx("div", { className: "fixed inset-0 w-screen h-[100svh]", children: jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0', 'overflow-y-auto overflow-x-hidden duration-200 ease-out data-[closed]:opacity-0', panelAlignmentMap[align], panelSizeMap[size], panelClass), children: [shouldShowDragHandle && (jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), showTitleSection && (jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-gray-100 dark:border-gray-700/60 shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsx(DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) }))] }), description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsx("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass), children: children }), footer && (jsx("div", { className: buildClassName('p-4 border-t border-gray-100 dark:border-gray-700/60 bg-gray-50/50 dark:bg-gray-800/80 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
|
|
1451
|
-
};
|
|
1452
|
-
Drawer.displayName = 'Drawer';
|
|
1453
|
-
|
|
1454
1556
|
const WIDTH_CLASS = {
|
|
1455
1557
|
auto: 'w-auto min-w-[120px]',
|
|
1456
1558
|
sm: 'w-44',
|
|
@@ -1476,7 +1578,7 @@ const Dropdown = ({ triggerButton, renderTriggerButton, className, items, render
|
|
|
1476
1578
|
variant: (_b = triggerButton.props.variant) !== null && _b !== void 0 ? _b : variant,
|
|
1477
1579
|
size: (_c = triggerButton.props.size) !== null && _c !== void 0 ? _c : size,
|
|
1478
1580
|
disabled: (_d = triggerButton.props.disabled) !== null && _d !== void 0 ? _d : disabled,
|
|
1479
|
-
}) })) : (jsx(MenuButton, { as: Fragment$1, children: triggerButton })), jsx(MenuItems, { transition: transition, anchor: anchor, className: buildClassName('origin-top-right rounded-xl shadow-lg p-1.5 text-sm transition duration-100 ease-out z-50', 'border border-
|
|
1581
|
+
}) })) : (jsx(MenuButton, { as: Fragment$1, children: triggerButton })), jsx(MenuItems, { transition: transition, anchor: anchor, className: buildClassName('origin-top-right rounded-xl shadow-lg p-1.5 text-sm transition duration-100 ease-out z-50', 'border border-[var(--ui-border)] bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200', 'focus:outline-none data-[closed]:scale-95 data-[closed]:opacity-0', '[--anchor-gap:--spacing(1)]', widthClass, itemsContainerClass), "data-testid": "dropdown-items", as: "ul", children: items.map((item, idx) => (jsxs(Fragment$1, { children: [item.groupTitle && (jsx("li", { className: "px-2.5 pt-2 pb-1 text-[11px] font-semibold text-gray-400 dark:text-gray-500 uppercase tracking-wider select-none", "data-testid": `dropdown-group-${item.id}`, children: item.groupTitle }, `group-${item.id}`)), !item.divider && (jsx(MenuItem, { as: "li", disabled: item.disabled, children: ({ disabled, active }) => (jsx("div", { onClick: () => {
|
|
1480
1582
|
var _a;
|
|
1481
1583
|
if (!disabled) {
|
|
1482
1584
|
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, item);
|
|
@@ -1488,14 +1590,14 @@ const Dropdown = ({ triggerButton, renderTriggerButton, className, items, render
|
|
|
1488
1590
|
: 'hover:bg-rose-50 dark:hover:bg-rose-950/40')
|
|
1489
1591
|
: buildClassName('text-gray-700 dark:text-gray-200', active
|
|
1490
1592
|
? 'bg-gray-100 dark:bg-gray-700/80'
|
|
1491
|
-
: 'hover:bg-gray-100/80 dark:hover:bg-gray-700/80'), disabled && 'opacity-40 cursor-not-allowed pointer-events-none', menuItemClass), "data-testid": `dropdown-item-${item.id}`, children: renderItem ? (renderItem(item)) : (jsxs(Fragment, { children: [jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [item.icon && (jsx("span", { className: buildClassName('shrink-0', item.danger ? 'text-rose-500' : 'text-gray-400 dark:text-gray-500'), children: item.icon })), jsxs("div", { className: "flex flex-col min-w-0", children: [item.label && jsx("span", { className: "font-medium truncate", children: item.label }), item.description && (jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500 font-normal truncate", children: item.description }))] })] }), item.shortcut && (jsx("kbd", { className: "shrink-0 text-[10px] font-medium font-mono px-1.5 py-0.5 rounded bg-gray-100 dark:bg-gray-700/80 border border-
|
|
1593
|
+
: 'hover:bg-gray-100/80 dark:hover:bg-gray-700/80'), disabled && 'opacity-40 cursor-not-allowed pointer-events-none', menuItemClass), "data-testid": `dropdown-item-${item.id}`, children: renderItem ? (renderItem(item)) : (jsxs(Fragment, { children: [jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [item.icon && (jsx("span", { className: buildClassName('shrink-0', item.danger ? 'text-rose-500' : 'text-gray-400 dark:text-gray-500'), children: item.icon })), jsxs("div", { className: "flex flex-col min-w-0", children: [item.label && (jsx("span", { className: "font-medium truncate", children: item.label })), item.description && (jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500 font-normal truncate", children: item.description }))] })] }), item.shortcut && (jsx("kbd", { className: "shrink-0 text-[10px] font-medium font-mono px-1.5 py-0.5 rounded bg-gray-100 dark:bg-gray-700/80 border border-[var(--ui-border-muted)] text-gray-400 dark:text-gray-400", children: item.shortcut }))] })) })) })), item.divider && idx < items.length - 1 && (jsx("li", { className: "my-1 h-px bg-gray-200/80 dark:bg-gray-700/80", "data-testid": "dropdown-divider" }, `divider-${item.id}`))] }, item.id))) })] }));
|
|
1492
1594
|
};
|
|
1493
1595
|
Dropdown.displayName = 'Dropdown';
|
|
1494
1596
|
|
|
1495
|
-
var _path$
|
|
1496
|
-
function _extends$
|
|
1597
|
+
var _path$3;
|
|
1598
|
+
function _extends$3() { return _extends$3 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$3.apply(null, arguments); }
|
|
1497
1599
|
var SvgFolderPlus = function SvgFolderPlus(props) {
|
|
1498
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
1600
|
+
return /*#__PURE__*/React.createElement("svg", _extends$3({
|
|
1499
1601
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1500
1602
|
width: 24,
|
|
1501
1603
|
height: 24,
|
|
@@ -1506,7 +1608,7 @@ var SvgFolderPlus = function SvgFolderPlus(props) {
|
|
|
1506
1608
|
strokeWidth: 2,
|
|
1507
1609
|
className: "lucide lucide-folder-plus-icon lucide-folder-plus",
|
|
1508
1610
|
viewBox: "0 0 24 24"
|
|
1509
|
-
}, props), _path$
|
|
1611
|
+
}, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
|
|
1510
1612
|
d: "M12 10v6M9 13h6M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
|
|
1511
1613
|
})));
|
|
1512
1614
|
};
|
|
@@ -1515,15 +1617,401 @@ const EmptyState = ({ title, description, className, action = null, }) => {
|
|
|
1515
1617
|
return (jsx("div", { className: buildClassName('w-full flex justify-center px-4 pt-16', className), children: jsxs("div", { className: "max-w-md flex flex-col items-center gap-4", children: [jsx(SvgFolderPlus, { className: "size-8 text-[var(--ui-text)]" }), jsx(HeadingText.SubTitle, { children: title }), description && (jsx(BodyText, { as: "p", className: "text-center", muted: true, small: true, children: description })), action] }) }));
|
|
1516
1618
|
};
|
|
1517
1619
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1620
|
+
function FloatingActionButton({ icon, activeIcon, label, variant = 'primary', size = 'md', position = 'bottom-right', speedDialActions, isOpen: externalIsOpen, onToggle, disabled = false, onClick, 'aria-label': ariaLabel, containerClass = '', className = '', }) {
|
|
1621
|
+
const [internalIsOpen, setInternalIsOpen] = useState(false);
|
|
1622
|
+
const isSpeedDial = Array.isArray(speedDialActions) && speedDialActions.length > 0;
|
|
1623
|
+
const isOpen = externalIsOpen !== undefined ? externalIsOpen : internalIsOpen;
|
|
1624
|
+
const toggleOpen = () => {
|
|
1625
|
+
const nextState = !isOpen;
|
|
1626
|
+
setInternalIsOpen(nextState);
|
|
1627
|
+
onToggle === null || onToggle === void 0 ? void 0 : onToggle(nextState);
|
|
1628
|
+
};
|
|
1629
|
+
const handleMainClick = () => {
|
|
1630
|
+
if (disabled)
|
|
1631
|
+
return;
|
|
1632
|
+
if (isSpeedDial) {
|
|
1633
|
+
toggleOpen();
|
|
1634
|
+
}
|
|
1635
|
+
else {
|
|
1636
|
+
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
1637
|
+
}
|
|
1638
|
+
};
|
|
1639
|
+
const handleSubActionClick = (action) => {
|
|
1640
|
+
var _a;
|
|
1641
|
+
if (action.disabled)
|
|
1642
|
+
return;
|
|
1643
|
+
(_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action);
|
|
1644
|
+
setInternalIsOpen(false);
|
|
1645
|
+
onToggle === null || onToggle === void 0 ? void 0 : onToggle(false);
|
|
1646
|
+
};
|
|
1647
|
+
const positionClasses = {
|
|
1648
|
+
'bottom-right': 'fixed bottom-6 right-6 z-40',
|
|
1649
|
+
'bottom-left': 'fixed bottom-6 left-6 z-40',
|
|
1650
|
+
'bottom-center': 'fixed bottom-6 left-1/2 -translate-x-1/2 z-40',
|
|
1651
|
+
inline: 'relative inline-flex z-10',
|
|
1652
|
+
}[position];
|
|
1653
|
+
const variantClasses = {
|
|
1654
|
+
primary: 'bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-lg shadow-blue-600/30',
|
|
1655
|
+
secondary: 'bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-800 dark:text-gray-100 border border-[var(--ui-border)] shadow-lg',
|
|
1656
|
+
danger: 'bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-lg shadow-red-600/30',
|
|
1657
|
+
dark: 'bg-gray-900 hover:bg-black active:bg-black text-white shadow-lg shadow-gray-900/40',
|
|
1658
|
+
}[variant];
|
|
1659
|
+
const sizeClasses = {
|
|
1660
|
+
sm: label ? 'px-3.5 py-2 text-xs gap-2 rounded-full' : 'p-2.5 rounded-full',
|
|
1661
|
+
md: label ? 'px-5 py-3 text-sm gap-2.5 rounded-full' : 'p-3.5 rounded-full',
|
|
1662
|
+
lg: label ? 'px-6 py-4 text-base gap-3 rounded-full' : 'p-4 rounded-full',
|
|
1663
|
+
}[size];
|
|
1664
|
+
return (jsxs("div", { className: buildClassName(positionClasses, containerClass), "data-testid": "fab-container", children: [isSpeedDial && isOpen && (jsx("div", { className: "fixed inset-0 bg-black/25 backdrop-blur-xs z-30 transition-opacity duration-200", onClick: () => toggleOpen(), "data-testid": "fab-backdrop" })), isSpeedDial && (jsx("div", { className: buildClassName('absolute bottom-full mb-3 flex flex-col gap-2.5 z-40 transition-all duration-200 origin-bottom', position === 'bottom-left'
|
|
1665
|
+
? 'items-start left-0'
|
|
1666
|
+
: position === 'bottom-center'
|
|
1667
|
+
? 'items-center left-1/2 -translate-x-1/2'
|
|
1668
|
+
: 'items-end right-0', isOpen
|
|
1669
|
+
? 'scale-100 opacity-100 pointer-events-auto'
|
|
1670
|
+
: 'scale-90 opacity-0 pointer-events-none'), "data-testid": "fab-speed-dial-menu", children: speedDialActions.map((action) => {
|
|
1671
|
+
const isDanger = action.theme === 'danger';
|
|
1672
|
+
const isPrimary = action.theme === 'primary';
|
|
1673
|
+
return (jsxs("button", { type: "button", disabled: action.disabled, onClick: () => handleSubActionClick(action), className: buildClassName('flex items-center gap-2.5 py-2 px-3.5 rounded-full text-xs font-semibold shadow-md transition-all duration-150 cursor-pointer group', action.disabled && 'opacity-50 cursor-not-allowed pointer-events-none', !action.disabled &&
|
|
1674
|
+
(isDanger
|
|
1675
|
+
? 'bg-red-600 text-white hover:bg-red-700'
|
|
1676
|
+
: isPrimary
|
|
1677
|
+
? 'bg-blue-600 text-white hover:bg-blue-700'
|
|
1678
|
+
: 'bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700 border border-[var(--ui-border)]')), "data-testid": `fab-action-${action.id}`, children: [jsx("span", { className: "text-sm", children: action.icon }), jsx("span", { className: "whitespace-nowrap", children: action.label })] }, action.id));
|
|
1679
|
+
}) })), jsxs("button", { type: "button", disabled: disabled, onClick: handleMainClick, "aria-label": ariaLabel || (typeof label === 'string' ? label : 'Floating action'), "aria-expanded": isSpeedDial ? isOpen : undefined, className: buildClassName('inline-flex items-center justify-center font-semibold transition-all duration-200 cursor-pointer select-none z-40 active:scale-95', disabled && 'opacity-50 cursor-not-allowed pointer-events-none shadow-none', variantClasses, sizeClasses, className), "data-testid": "fab-button", children: [jsx("span", { className: buildClassName('transition-transform duration-200', isOpen && 'rotate-45'), children: isOpen && activeIcon ? activeIcon : icon }), label && jsx("span", { className: "whitespace-nowrap", children: label })] })] }));
|
|
1680
|
+
}
|
|
1681
|
+
FloatingActionButton.displayName = 'FloatingActionButton';
|
|
1682
|
+
|
|
1683
|
+
const GAP_MAP = {
|
|
1684
|
+
none: 'gap-0',
|
|
1685
|
+
xs: 'gap-1',
|
|
1686
|
+
sm: 'gap-2',
|
|
1687
|
+
md: 'gap-4',
|
|
1688
|
+
lg: 'gap-6',
|
|
1689
|
+
xl: 'gap-8',
|
|
1690
|
+
'2xl': 'gap-12',
|
|
1691
|
+
};
|
|
1692
|
+
const GAP_X_MAP = {
|
|
1693
|
+
none: 'gap-x-0',
|
|
1694
|
+
xs: 'gap-x-1',
|
|
1695
|
+
sm: 'gap-x-2',
|
|
1696
|
+
md: 'gap-x-4',
|
|
1697
|
+
lg: 'gap-x-6',
|
|
1698
|
+
xl: 'gap-x-8',
|
|
1699
|
+
'2xl': 'gap-x-12',
|
|
1700
|
+
};
|
|
1701
|
+
const GAP_Y_MAP = {
|
|
1702
|
+
none: 'gap-y-0',
|
|
1703
|
+
xs: 'gap-y-1',
|
|
1704
|
+
sm: 'gap-y-2',
|
|
1705
|
+
md: 'gap-y-4',
|
|
1706
|
+
lg: 'gap-y-6',
|
|
1707
|
+
xl: 'gap-y-8',
|
|
1708
|
+
'2xl': 'gap-y-12',
|
|
1709
|
+
};
|
|
1710
|
+
const ALIGN_MAP = {
|
|
1711
|
+
start: 'items-start',
|
|
1712
|
+
center: 'items-center',
|
|
1713
|
+
end: 'items-end',
|
|
1714
|
+
baseline: 'items-baseline',
|
|
1715
|
+
stretch: 'items-stretch',
|
|
1716
|
+
};
|
|
1717
|
+
const JUSTIFY_MAP = {
|
|
1718
|
+
start: 'justify-start',
|
|
1719
|
+
center: 'justify-center',
|
|
1720
|
+
end: 'justify-end',
|
|
1721
|
+
between: 'justify-between',
|
|
1722
|
+
around: 'justify-around',
|
|
1723
|
+
evenly: 'justify-evenly',
|
|
1724
|
+
};
|
|
1725
|
+
const DIRECTION_MAP = {
|
|
1726
|
+
row: 'flex-row',
|
|
1727
|
+
'row-reverse': 'flex-row-reverse',
|
|
1728
|
+
col: 'flex-col',
|
|
1729
|
+
'col-reverse': 'flex-col-reverse',
|
|
1730
|
+
};
|
|
1731
|
+
const WRAP_MAP = {
|
|
1732
|
+
wrap: 'flex-wrap',
|
|
1733
|
+
nowrap: 'flex-nowrap',
|
|
1734
|
+
'wrap-reverse': 'flex-wrap-reverse',
|
|
1735
|
+
};
|
|
1736
|
+
/**
|
|
1737
|
+
* Resolves the `order` prop to inline styles when it's a raw number.
|
|
1738
|
+
*
|
|
1739
|
+
* `'first'` / `'last'` map to the static `order-first`/`order-last` Tailwind
|
|
1740
|
+
* utilities (safe, since those exact class names are literal elsewhere).
|
|
1741
|
+
* Arbitrary numeric orders can't be expressed as a safe literal class (the
|
|
1742
|
+
* value is unbounded), so they're applied as an inline `order` style instead
|
|
1743
|
+
* — that works regardless of what the consuming app's Tailwind build scans.
|
|
1744
|
+
*/
|
|
1745
|
+
const resolveOrderStyle = (order) => typeof order === 'number' ? { order } : undefined;
|
|
1746
|
+
const resolveOrderClassName = (order) => {
|
|
1747
|
+
if (order === 'first')
|
|
1748
|
+
return '-order-1';
|
|
1749
|
+
if (order === 'last')
|
|
1750
|
+
return 'order-last';
|
|
1751
|
+
return undefined;
|
|
1752
|
+
};
|
|
1753
|
+
/** Width-fraction span classes used by `Flex.Item` (unprefixed / base breakpoint). */
|
|
1754
|
+
const FLEX_SPAN_MAP = {
|
|
1755
|
+
1: 'w-1/12 flex-none',
|
|
1756
|
+
2: 'w-2/12 flex-none',
|
|
1757
|
+
3: 'w-3/12 flex-none',
|
|
1758
|
+
4: 'w-4/12 flex-none',
|
|
1759
|
+
5: 'w-5/12 flex-none',
|
|
1760
|
+
6: 'w-6/12 flex-none',
|
|
1761
|
+
7: 'w-7/12 flex-none',
|
|
1762
|
+
8: 'w-8/12 flex-none',
|
|
1763
|
+
9: 'w-9/12 flex-none',
|
|
1764
|
+
10: 'w-10/12 flex-none',
|
|
1765
|
+
11: 'w-11/12 flex-none',
|
|
1766
|
+
12: 'w-full flex-none',
|
|
1767
|
+
auto: 'w-auto flex-none',
|
|
1768
|
+
full: 'w-full flex-none',
|
|
1769
|
+
};
|
|
1770
|
+
const FLEX_SM_SPAN_MAP = {
|
|
1771
|
+
1: 'sm:w-1/12',
|
|
1772
|
+
2: 'sm:w-2/12',
|
|
1773
|
+
3: 'sm:w-3/12',
|
|
1774
|
+
4: 'sm:w-4/12',
|
|
1775
|
+
5: 'sm:w-5/12',
|
|
1776
|
+
6: 'sm:w-6/12',
|
|
1777
|
+
7: 'sm:w-7/12',
|
|
1778
|
+
8: 'sm:w-8/12',
|
|
1779
|
+
9: 'sm:w-9/12',
|
|
1780
|
+
10: 'sm:w-10/12',
|
|
1781
|
+
11: 'sm:w-11/12',
|
|
1782
|
+
12: 'sm:w-full',
|
|
1783
|
+
auto: 'sm:w-auto',
|
|
1784
|
+
full: 'sm:w-full',
|
|
1785
|
+
};
|
|
1786
|
+
const FLEX_MD_SPAN_MAP = {
|
|
1787
|
+
1: 'md:w-1/12',
|
|
1788
|
+
2: 'md:w-2/12',
|
|
1789
|
+
3: 'md:w-3/12',
|
|
1790
|
+
4: 'md:w-4/12',
|
|
1791
|
+
5: 'md:w-5/12',
|
|
1792
|
+
6: 'md:w-6/12',
|
|
1793
|
+
7: 'md:w-7/12',
|
|
1794
|
+
8: 'md:w-8/12',
|
|
1795
|
+
9: 'md:w-9/12',
|
|
1796
|
+
10: 'md:w-10/12',
|
|
1797
|
+
11: 'md:w-11/12',
|
|
1798
|
+
12: 'md:w-full',
|
|
1799
|
+
auto: 'md:w-auto',
|
|
1800
|
+
full: 'md:w-full',
|
|
1801
|
+
};
|
|
1802
|
+
const FLEX_LG_SPAN_MAP = {
|
|
1803
|
+
1: 'lg:w-1/12',
|
|
1804
|
+
2: 'lg:w-2/12',
|
|
1805
|
+
3: 'lg:w-3/12',
|
|
1806
|
+
4: 'lg:w-4/12',
|
|
1807
|
+
5: 'lg:w-5/12',
|
|
1808
|
+
6: 'lg:w-6/12',
|
|
1809
|
+
7: 'lg:w-7/12',
|
|
1810
|
+
8: 'lg:w-8/12',
|
|
1811
|
+
9: 'lg:w-9/12',
|
|
1812
|
+
10: 'lg:w-10/12',
|
|
1813
|
+
11: 'lg:w-11/12',
|
|
1814
|
+
12: 'lg:w-full',
|
|
1815
|
+
auto: 'lg:w-auto',
|
|
1816
|
+
full: 'lg:w-full',
|
|
1817
|
+
};
|
|
1818
|
+
const FLEX_XL_SPAN_MAP = {
|
|
1819
|
+
1: 'xl:w-1/12',
|
|
1820
|
+
2: 'xl:w-2/12',
|
|
1821
|
+
3: 'xl:w-3/12',
|
|
1822
|
+
4: 'xl:w-4/12',
|
|
1823
|
+
5: 'xl:w-5/12',
|
|
1824
|
+
6: 'xl:w-6/12',
|
|
1825
|
+
7: 'xl:w-7/12',
|
|
1826
|
+
8: 'xl:w-8/12',
|
|
1827
|
+
9: 'xl:w-9/12',
|
|
1828
|
+
10: 'xl:w-10/12',
|
|
1829
|
+
11: 'xl:w-11/12',
|
|
1830
|
+
12: 'xl:w-full',
|
|
1831
|
+
auto: 'xl:w-auto',
|
|
1832
|
+
full: 'xl:w-full',
|
|
1833
|
+
};
|
|
1834
|
+
const FLEX_XXL_SPAN_MAP = {
|
|
1835
|
+
1: '2xl:w-1/12',
|
|
1836
|
+
2: '2xl:w-2/12',
|
|
1837
|
+
3: '2xl:w-3/12',
|
|
1838
|
+
4: '2xl:w-4/12',
|
|
1839
|
+
5: '2xl:w-5/12',
|
|
1840
|
+
6: '2xl:w-6/12',
|
|
1841
|
+
7: '2xl:w-7/12',
|
|
1842
|
+
8: '2xl:w-8/12',
|
|
1843
|
+
9: '2xl:w-9/12',
|
|
1844
|
+
10: '2xl:w-10/12',
|
|
1845
|
+
11: '2xl:w-11/12',
|
|
1846
|
+
12: '2xl:w-full',
|
|
1847
|
+
auto: '2xl:w-auto',
|
|
1848
|
+
full: '2xl:w-full',
|
|
1849
|
+
};
|
|
1850
|
+
/** `col-span-*` classes used by `Grid.Col` (unprefixed / base breakpoint). */
|
|
1851
|
+
const GRID_SPAN_MAP = {
|
|
1852
|
+
1: 'col-span-1',
|
|
1853
|
+
2: 'col-span-2',
|
|
1854
|
+
3: 'col-span-3',
|
|
1855
|
+
4: 'col-span-4',
|
|
1856
|
+
5: 'col-span-5',
|
|
1857
|
+
6: 'col-span-6',
|
|
1858
|
+
7: 'col-span-7',
|
|
1859
|
+
8: 'col-span-8',
|
|
1860
|
+
9: 'col-span-9',
|
|
1861
|
+
10: 'col-span-10',
|
|
1862
|
+
11: 'col-span-11',
|
|
1863
|
+
12: 'col-span-12',
|
|
1864
|
+
auto: 'col-auto',
|
|
1865
|
+
full: 'col-span-full',
|
|
1866
|
+
};
|
|
1867
|
+
const GRID_SM_SPAN_MAP = {
|
|
1868
|
+
1: 'sm:col-span-1',
|
|
1869
|
+
2: 'sm:col-span-2',
|
|
1870
|
+
3: 'sm:col-span-3',
|
|
1871
|
+
4: 'sm:col-span-4',
|
|
1872
|
+
5: 'sm:col-span-5',
|
|
1873
|
+
6: 'sm:col-span-6',
|
|
1874
|
+
7: 'sm:col-span-7',
|
|
1875
|
+
8: 'sm:col-span-8',
|
|
1876
|
+
9: 'sm:col-span-9',
|
|
1877
|
+
10: 'sm:col-span-10',
|
|
1878
|
+
11: 'sm:col-span-11',
|
|
1879
|
+
12: 'sm:col-span-12',
|
|
1880
|
+
auto: 'sm:col-auto',
|
|
1881
|
+
full: 'sm:col-span-full',
|
|
1882
|
+
};
|
|
1883
|
+
const GRID_MD_SPAN_MAP = {
|
|
1884
|
+
1: 'md:col-span-1',
|
|
1885
|
+
2: 'md:col-span-2',
|
|
1886
|
+
3: 'md:col-span-3',
|
|
1887
|
+
4: 'md:col-span-4',
|
|
1888
|
+
5: 'md:col-span-5',
|
|
1889
|
+
6: 'md:col-span-6',
|
|
1890
|
+
7: 'md:col-span-7',
|
|
1891
|
+
8: 'md:col-span-8',
|
|
1892
|
+
9: 'md:col-span-9',
|
|
1893
|
+
10: 'md:col-span-10',
|
|
1894
|
+
11: 'md:col-span-11',
|
|
1895
|
+
12: 'md:col-span-12',
|
|
1896
|
+
auto: 'md:col-auto',
|
|
1897
|
+
full: 'md:col-span-full',
|
|
1898
|
+
};
|
|
1899
|
+
const GRID_LG_SPAN_MAP = {
|
|
1900
|
+
1: 'lg:col-span-1',
|
|
1901
|
+
2: 'lg:col-span-2',
|
|
1902
|
+
3: 'lg:col-span-3',
|
|
1903
|
+
4: 'lg:col-span-4',
|
|
1904
|
+
5: 'lg:col-span-5',
|
|
1905
|
+
6: 'lg:col-span-6',
|
|
1906
|
+
7: 'lg:col-span-7',
|
|
1907
|
+
8: 'lg:col-span-8',
|
|
1908
|
+
9: 'lg:col-span-9',
|
|
1909
|
+
10: 'lg:col-span-10',
|
|
1910
|
+
11: 'lg:col-span-11',
|
|
1911
|
+
12: 'lg:col-span-12',
|
|
1912
|
+
auto: 'lg:col-auto',
|
|
1913
|
+
full: 'lg:col-span-full',
|
|
1914
|
+
};
|
|
1915
|
+
const GRID_XL_SPAN_MAP = {
|
|
1916
|
+
1: 'xl:col-span-1',
|
|
1917
|
+
2: 'xl:col-span-2',
|
|
1918
|
+
3: 'xl:col-span-3',
|
|
1919
|
+
4: 'xl:col-span-4',
|
|
1920
|
+
5: 'xl:col-span-5',
|
|
1921
|
+
6: 'xl:col-span-6',
|
|
1922
|
+
7: 'xl:col-span-7',
|
|
1923
|
+
8: 'xl:col-span-8',
|
|
1924
|
+
9: 'xl:col-span-9',
|
|
1925
|
+
10: 'xl:col-span-10',
|
|
1926
|
+
11: 'xl:col-span-11',
|
|
1927
|
+
12: 'xl:col-span-12',
|
|
1928
|
+
auto: 'xl:col-auto',
|
|
1929
|
+
full: 'xl:col-span-full',
|
|
1930
|
+
};
|
|
1931
|
+
const GRID_XXL_SPAN_MAP = {
|
|
1932
|
+
1: '2xl:col-span-1',
|
|
1933
|
+
2: '2xl:col-span-2',
|
|
1934
|
+
3: '2xl:col-span-3',
|
|
1935
|
+
4: '2xl:col-span-4',
|
|
1936
|
+
5: '2xl:col-span-5',
|
|
1937
|
+
6: '2xl:col-span-6',
|
|
1938
|
+
7: '2xl:col-span-7',
|
|
1939
|
+
8: '2xl:col-span-8',
|
|
1940
|
+
9: '2xl:col-span-9',
|
|
1941
|
+
10: '2xl:col-span-10',
|
|
1942
|
+
11: '2xl:col-span-11',
|
|
1943
|
+
12: '2xl:col-span-12',
|
|
1944
|
+
auto: '2xl:col-auto',
|
|
1945
|
+
full: '2xl:col-span-full',
|
|
1946
|
+
};
|
|
1947
|
+
/**
|
|
1948
|
+
* Preset track-count classes for `Grid`'s `cols` prop. Each preset
|
|
1949
|
+
* progressively reveals more columns at wider breakpoints so a grid is
|
|
1950
|
+
* responsive out of the box without the caller specifying per-item spans.
|
|
1951
|
+
*/
|
|
1952
|
+
const GRID_COLS_MAP = {
|
|
1953
|
+
1: 'grid-cols-1',
|
|
1954
|
+
2: 'grid-cols-1 sm:grid-cols-2',
|
|
1955
|
+
3: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3',
|
|
1956
|
+
4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
|
|
1957
|
+
5: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5',
|
|
1958
|
+
6: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6',
|
|
1959
|
+
7: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-7',
|
|
1960
|
+
8: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-8',
|
|
1961
|
+
9: 'grid-cols-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-9',
|
|
1962
|
+
10: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-5 lg:grid-cols-10',
|
|
1963
|
+
11: 'grid-cols-1 sm:grid-cols-3 md:grid-cols-6 lg:grid-cols-11',
|
|
1964
|
+
12: 'grid-cols-12',
|
|
1965
|
+
auto: 'grid-cols-none auto-cols-auto',
|
|
1966
|
+
};
|
|
1967
|
+
|
|
1968
|
+
const FlexItem = forwardRef((props, ref) => {
|
|
1969
|
+
const { as: Component = 'div', span, sm, md, lg, xl, xxl, grow, shrink, order, className, style, children, ...restProps } = props;
|
|
1970
|
+
const classes = buildClassName('min-w-0 box-border', span && FLEX_SPAN_MAP[String(span)], sm && FLEX_SM_SPAN_MAP[String(sm)], md && FLEX_MD_SPAN_MAP[String(md)], lg && FLEX_LG_SPAN_MAP[String(lg)], xl && FLEX_XL_SPAN_MAP[String(xl)], xxl && FLEX_XXL_SPAN_MAP[String(xxl)], resolveOrderClassName(order), grow === true && 'grow', grow === false && 'grow-0', shrink === true && 'shrink', shrink === false && 'shrink-0', className);
|
|
1971
|
+
return (jsx(Component, { ref: ref, className: classes, style: { ...resolveOrderStyle(order), ...style }, ...restProps, children: children }));
|
|
1972
|
+
});
|
|
1973
|
+
FlexItem.displayName = 'Flex.Item';
|
|
1974
|
+
const Flex = forwardRef((props, ref) => {
|
|
1975
|
+
const { as: Component = 'div', gap, gapX, gapY, align = 'stretch', justify = 'start', direction = 'row', wrap = 'wrap', inline = false, className, children, ...restProps } = props;
|
|
1976
|
+
const classes = buildClassName(inline ? 'inline-flex' : 'flex', DIRECTION_MAP[direction] || 'flex-row', WRAP_MAP[wrap] || 'flex-wrap', 'w-full', !gapX && !gapY && gap && GAP_MAP[gap], gapX && GAP_X_MAP[gapX], gapY && GAP_Y_MAP[gapY], ALIGN_MAP[align] || 'items-stretch', JUSTIFY_MAP[justify] || 'justify-start', className);
|
|
1977
|
+
return (jsx(Component, { ref: ref, className: classes, ...restProps, children: children }));
|
|
1978
|
+
});
|
|
1979
|
+
Flex.Item = FlexItem;
|
|
1980
|
+
Flex.Col = FlexItem;
|
|
1981
|
+
Flex.displayName = 'Flex';
|
|
1982
|
+
|
|
1983
|
+
const GridContext = createContext({ isAutoFit: false });
|
|
1984
|
+
const GridCol = forwardRef((props, ref) => {
|
|
1985
|
+
const { as: Component = 'div', span, sm, md, lg, xl, xxl, grow, shrink, order, className, style, children, ...restProps } = props;
|
|
1986
|
+
const { isAutoFit } = useContext(GridContext);
|
|
1987
|
+
const classes = buildClassName('min-w-0 box-border', span ? GRID_SPAN_MAP[String(span)] : isAutoFit ? undefined : 'col-span-12 sm:col-span-4', sm && GRID_SM_SPAN_MAP[String(sm)], md && GRID_MD_SPAN_MAP[String(md)], lg && GRID_LG_SPAN_MAP[String(lg)], xl && GRID_XL_SPAN_MAP[String(xl)], xxl && GRID_XXL_SPAN_MAP[String(xxl)], resolveOrderClassName(order), grow === true && 'grow', grow === false && 'grow-0', shrink === true && 'shrink', shrink === false && 'shrink-0', className);
|
|
1988
|
+
return (jsx(Component, { ref: ref, className: classes, style: { ...resolveOrderStyle(order), ...style }, ...restProps, children: children }));
|
|
1989
|
+
});
|
|
1990
|
+
GridCol.displayName = 'Grid.Col';
|
|
1991
|
+
const Grid = forwardRef((props, ref) => {
|
|
1992
|
+
const { as: Component = 'div', cols, minColWidth, autoFit = true, gap = 'md', gapX, gapY, align = 'stretch', justify, direction = 'row', wrap = 'wrap', flex = false, inline = false, className, style, children, ...restProps } = props;
|
|
1993
|
+
const isAutoFit = Boolean(!flex && minColWidth);
|
|
1994
|
+
const classes = buildClassName(flex ? (inline ? 'inline-flex' : 'flex') : inline ? 'inline-grid' : 'grid', flex && (DIRECTION_MAP[direction] || 'flex-row'), flex && (WRAP_MAP[wrap] || 'flex-wrap'), !flex &&
|
|
1995
|
+
!minColWidth &&
|
|
1996
|
+
(cols ? GRID_COLS_MAP[String(cols)] || 'grid-cols-12' : 'grid-cols-12'), !flex && 'justify-items-stretch', 'w-full', !gapX && !gapY && GAP_MAP[gap], gapX && GAP_X_MAP[gapX], gapY && GAP_Y_MAP[gapY], ALIGN_MAP[align] || 'items-stretch', justify && (JUSTIFY_MAP[justify] || 'justify-start'), className);
|
|
1997
|
+
const gridTemplateColumns = !flex && minColWidth
|
|
1998
|
+
? `repeat(${autoFit ? 'auto-fit' : 'auto-fill'}, minmax(${minColWidth}, 1fr))`
|
|
1999
|
+
: undefined;
|
|
2000
|
+
return (jsx(GridContext.Provider, { value: { isAutoFit }, children: jsx(Component, { ref: ref, className: classes, style: gridTemplateColumns ? { gridTemplateColumns, ...style } : style, ...restProps, children: children }) }));
|
|
2001
|
+
});
|
|
2002
|
+
Grid.Col = GridCol;
|
|
2003
|
+
Grid.Item = GridCol;
|
|
2004
|
+
Grid.displayName = 'Grid';
|
|
2005
|
+
|
|
2006
|
+
const sizeClasses$4 = {
|
|
2007
|
+
sm: {
|
|
2008
|
+
input: 'px-2.5 py-1.5 text-xs leading-5',
|
|
2009
|
+
group: 'w-8 text-xs',
|
|
2010
|
+
icon: 'size-3.5',
|
|
2011
|
+
text: 'text-xs',
|
|
2012
|
+
},
|
|
2013
|
+
md: {
|
|
2014
|
+
input: 'px-3.5 py-2 text-sm leading-6',
|
|
1527
2015
|
group: 'w-10 text-sm',
|
|
1528
2016
|
icon: 'size-4',
|
|
1529
2017
|
text: 'text-sm',
|
|
@@ -1539,9 +2027,9 @@ function buildInputClass(className, { isFocusWithin = false, disabled = false, h
|
|
|
1539
2027
|
const currentSize = sizeClasses$4[size] || sizeClasses$4.md;
|
|
1540
2028
|
return buildClassName('transition-all duration-150', 'block w-full rounded-lg bg-white', currentSize.input, 'text-gray-900 outline outline-1 -outline-offset-1', hasError
|
|
1541
2029
|
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
1542
|
-
: 'outline-
|
|
1543
|
-
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 dark:text-gray-600 dark:placeholder-gray-600 placeholder-gray-400 outline-
|
|
1544
|
-
: 'bg-white dark:bg-gray-700 dark:text-white outline-
|
|
2030
|
+
: 'outline-[var(--ui-border)]', disabled
|
|
2031
|
+
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 dark:text-gray-600 dark:placeholder-gray-600 placeholder-gray-400 outline-[var(--ui-border-muted)]'
|
|
2032
|
+
: 'bg-white dark:bg-gray-700 dark:text-white outline-[var(--ui-border)] dark:placeholder-gray-400 placeholder-gray-400', isFocusWithin
|
|
1545
2033
|
? 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2'
|
|
1546
2034
|
: 'focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2', className);
|
|
1547
2035
|
}
|
|
@@ -1579,11 +2067,11 @@ const Input = forwardRef((props, ref) => {
|
|
|
1579
2067
|
const actualRightGroup = rightGroup !== null && rightGroup !== void 0 ? rightGroup : (showClearButton ? (jsx("button", { type: "button", onClick: handleClear, className: "p-1 rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors cursor-pointer", title: "Clear text", tabIndex: -1, children: jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: currentSize.icon, children: jsx("path", { d: "M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" }) }) })) : null);
|
|
1580
2068
|
const hasRightGroup = actualRightGroup !== null && actualRightGroup !== undefined;
|
|
1581
2069
|
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
1582
|
-
return (jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: "flex rounded-lg shadow-2xs", children: [prefix && (jsx("span", { className: "inline-flex items-center px-3 rounded-l-lg border border-r-0 border-
|
|
2070
|
+
return (jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: "flex rounded-lg shadow-2xs", children: [prefix && (jsx("span", { className: "inline-flex items-center px-3 rounded-l-lg border border-r-0 border-[var(--ui-border)] bg-gray-50 dark:bg-gray-800 text-gray-500 dark:text-gray-400 text-xs font-medium shrink-0", children: prefix })), jsxs("div", { className: "relative flex-1 min-w-0", children: [hasLeftGroup && (jsx("span", { className: buildClassName('absolute top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500', currentSize.group), children: leftGroup })), jsx("input", { ref: innerRef, autoComplete: "off", ...inputProps, value: value, defaultValue: defaultValue, onChange: handleInputChange, maxLength: maxLength, name: name, id: id, type: type, className: buildClassName(buildInputClass(className, {
|
|
1583
2071
|
disabled: inputProps.disabled,
|
|
1584
2072
|
hasError,
|
|
1585
2073
|
size,
|
|
1586
|
-
}), prefix ? '!rounded-l-none' : '', suffix ? '!rounded-r-none' : '', hasRightGroup ? (size === 'lg' ? 'pe-12' : size === 'sm' ? 'pe-8' : 'pe-10') : '', hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '') }), hasRightGroup && (jsx("span", { className: buildClassName('absolute end-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500', currentSize.group), children: actualRightGroup }))] }), suffix && (jsx("span", { className: "inline-flex items-center px-3 rounded-r-lg border border-l-0 border-
|
|
2074
|
+
}), prefix ? '!rounded-l-none' : '', suffix ? '!rounded-r-none' : '', hasRightGroup ? (size === 'lg' ? 'pe-12' : size === 'sm' ? 'pe-8' : 'pe-10') : '', hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : '') }), hasRightGroup && (jsx("span", { className: buildClassName('absolute end-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500', currentSize.group), children: actualRightGroup }))] }), suffix && (jsx("span", { className: "inline-flex items-center px-3 rounded-r-lg border border-l-0 border-[var(--ui-border)] bg-gray-50 dark:bg-gray-800 text-gray-500 dark:text-gray-400 text-xs font-medium shrink-0", children: suffix }))] }), (showErrorMessage && error) || helperText || showCount ? (jsxs("div", { className: "mt-1.5 flex items-center justify-between gap-2 text-xs", children: [jsx("div", { className: "min-w-0 flex-1", children: showErrorMessage && error ? (jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsx(TextContent, { muted: true, small: true, children: helperText })) : null }), showCount && (jsxs("span", { className: buildClassName('text-[11px] font-medium shrink-0 ml-auto', maxLength && charLength >= maxLength
|
|
1587
2075
|
? 'text-red-500 font-semibold'
|
|
1588
2076
|
: 'text-gray-400 dark:text-gray-500'), children: [charLength, maxLength ? ` / ${maxLength}` : ''] }))] })) : null] }));
|
|
1589
2077
|
});
|
|
@@ -1633,6 +2121,170 @@ const PasswordInput = forwardRef((props, ref) => {
|
|
|
1633
2121
|
});
|
|
1634
2122
|
PasswordInput.displayName = 'PasswordInput';
|
|
1635
2123
|
|
|
2124
|
+
function PinInput({ length = 4, value: externalValue, onChange, onComplete, mask = false, size = 'md', type = 'numeric', error, disabled = false, autoFocus = false, containerClass = '', inputClass = '', }) {
|
|
2125
|
+
const [internalValue, setInternalValue] = useState('');
|
|
2126
|
+
const inputRefs = useRef([]);
|
|
2127
|
+
const pinValue = externalValue !== undefined ? externalValue : internalValue;
|
|
2128
|
+
const digits = Array.from({ length }, (_, i) => pinValue[i] || '');
|
|
2129
|
+
useEffect(() => {
|
|
2130
|
+
if (autoFocus && inputRefs.current[0] && !disabled) {
|
|
2131
|
+
inputRefs.current[0].focus();
|
|
2132
|
+
}
|
|
2133
|
+
}, [autoFocus, disabled]);
|
|
2134
|
+
const updatePin = (newDigits) => {
|
|
2135
|
+
const newPin = newDigits.join('').slice(0, length);
|
|
2136
|
+
setInternalValue(newPin);
|
|
2137
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newPin);
|
|
2138
|
+
if (newPin.length === length) {
|
|
2139
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(newPin);
|
|
2140
|
+
}
|
|
2141
|
+
};
|
|
2142
|
+
const handleInputChange = (e, index) => {
|
|
2143
|
+
var _a;
|
|
2144
|
+
const char = e.target.value.slice(-1);
|
|
2145
|
+
if (!char)
|
|
2146
|
+
return;
|
|
2147
|
+
const isValid = type === 'numeric' ? /^[0-9]$/.test(char) : /^[a-zA-Z0-9]$/.test(char);
|
|
2148
|
+
if (!isValid)
|
|
2149
|
+
return;
|
|
2150
|
+
const nextDigits = [...digits];
|
|
2151
|
+
nextDigits[index] = char;
|
|
2152
|
+
updatePin(nextDigits);
|
|
2153
|
+
if (index < length - 1 && inputRefs.current[index + 1]) {
|
|
2154
|
+
(_a = inputRefs.current[index + 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2157
|
+
const handleKeyDown = (e, index) => {
|
|
2158
|
+
var _a, _b, _c;
|
|
2159
|
+
if (e.key === 'Backspace') {
|
|
2160
|
+
if (!digits[index] && index > 0 && inputRefs.current[index - 1]) {
|
|
2161
|
+
const nextDigits = [...digits];
|
|
2162
|
+
nextDigits[index - 1] = '';
|
|
2163
|
+
updatePin(nextDigits);
|
|
2164
|
+
(_a = inputRefs.current[index - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
2165
|
+
}
|
|
2166
|
+
else if (digits[index]) {
|
|
2167
|
+
const nextDigits = [...digits];
|
|
2168
|
+
nextDigits[index] = '';
|
|
2169
|
+
updatePin(nextDigits);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
else if (e.key === 'ArrowLeft' && index > 0) {
|
|
2173
|
+
(_b = inputRefs.current[index - 1]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
2174
|
+
}
|
|
2175
|
+
else if (e.key === 'ArrowRight' && index < length - 1) {
|
|
2176
|
+
(_c = inputRefs.current[index + 1]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
2177
|
+
}
|
|
2178
|
+
};
|
|
2179
|
+
const handlePaste = (e) => {
|
|
2180
|
+
e.preventDefault();
|
|
2181
|
+
if (disabled)
|
|
2182
|
+
return;
|
|
2183
|
+
const pastedData = e.clipboardData.getData('text').trim();
|
|
2184
|
+
const regex = type === 'numeric' ? /[0-9]/g : /[a-zA-Z0-9]/g;
|
|
2185
|
+
const matchedChars = pastedData.match(regex) || [];
|
|
2186
|
+
if (matchedChars.length === 0)
|
|
2187
|
+
return;
|
|
2188
|
+
const nextDigits = Array.from({ length }, (_, i) => matchedChars[i] || '');
|
|
2189
|
+
updatePin(nextDigits);
|
|
2190
|
+
const focusIndex = Math.min(matchedChars.length, length) - 1;
|
|
2191
|
+
const targetRef = inputRefs.current[focusIndex >= 0 ? focusIndex : 0];
|
|
2192
|
+
targetRef === null || targetRef === void 0 ? void 0 : targetRef.focus();
|
|
2193
|
+
};
|
|
2194
|
+
const sizeClasses = {
|
|
2195
|
+
sm: 'size-9 text-sm rounded-lg',
|
|
2196
|
+
md: 'size-11 text-base rounded-xl',
|
|
2197
|
+
lg: 'size-14 text-lg rounded-2xl',
|
|
2198
|
+
}[size];
|
|
2199
|
+
return (jsxs("div", { className: buildClassName('space-y-1.5', containerClass), "data-testid": "pin-input-container", children: [jsx("div", { className: "flex items-center gap-2.5 sm:gap-3", children: digits.map((digit, index) => {
|
|
2200
|
+
const isFilled = Boolean(digit);
|
|
2201
|
+
return (jsx("input", { ref: (el) => {
|
|
2202
|
+
inputRefs.current[index] = el;
|
|
2203
|
+
}, type: mask ? 'password' : 'text', inputMode: type === 'numeric' ? 'numeric' : 'text', pattern: type === 'numeric' ? '[0-9]*' : undefined, maxLength: 1, value: digit, disabled: disabled, onChange: (e) => handleInputChange(e, index), onKeyDown: (e) => handleKeyDown(e, index), onPaste: handlePaste, className: buildClassName('text-center font-bold transition-all duration-150 outline outline-1 -outline-offset-1 select-none', sizeClasses, disabled
|
|
2204
|
+
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 text-gray-400 dark:text-gray-600 outline-[var(--ui-border-muted)]'
|
|
2205
|
+
: error
|
|
2206
|
+
? 'bg-red-50/50 dark:bg-red-950/20 text-red-600 dark:text-red-400 outline-red-500 focus:outline-red-500 focus:outline-2 focus:-outline-offset-2'
|
|
2207
|
+
: isFilled
|
|
2208
|
+
? 'bg-blue-50/30 dark:bg-blue-950/30 text-gray-900 dark:text-white outline-blue-500 dark:outline-blue-400 focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2'
|
|
2209
|
+
: 'bg-white dark:bg-gray-800 text-gray-900 dark:text-white outline-[var(--ui-border)] focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2', inputClass), "data-testid": `pin-input-box-${index}` }, index));
|
|
2210
|
+
}) }), typeof error === 'string' && (jsx("div", { className: "text-xs text-red-500 dark:text-red-400 font-medium pt-0.5", "data-testid": "pin-input-error", children: error }))] }));
|
|
2211
|
+
}
|
|
2212
|
+
PinInput.displayName = 'PinInput';
|
|
2213
|
+
|
|
2214
|
+
function PullArrowIcon({ progress }) {
|
|
2215
|
+
const rotation = Math.min(180, progress * 180);
|
|
2216
|
+
return (jsx("svg", { className: "size-4 text-blue-600 dark:text-blue-400 transition-transform duration-150", style: { transform: `rotate(${rotation}deg)` }, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M19 14l-7 7m0 0l-7-7m7 7V3" }) }));
|
|
2217
|
+
}
|
|
2218
|
+
function PullToRefresh({ onRefresh, pullThreshold = 70, maxPullDistance = 120, disabled = false, refreshing: externalRefreshing, pullingContent, refreshingContent, children, className = '', contentClass = '', }) {
|
|
2219
|
+
const containerRef = useRef(null);
|
|
2220
|
+
const startYRef = useRef(0);
|
|
2221
|
+
const isPullingRef = useRef(false);
|
|
2222
|
+
const [pullDistance, setPullDistance] = useState(0);
|
|
2223
|
+
const [internalRefreshing, setInternalRefreshing] = useState(false);
|
|
2224
|
+
const isRefreshing = externalRefreshing !== undefined ? externalRefreshing : internalRefreshing;
|
|
2225
|
+
const handleTouchStart = useCallback((e) => {
|
|
2226
|
+
if (disabled || isRefreshing)
|
|
2227
|
+
return;
|
|
2228
|
+
const container = containerRef.current;
|
|
2229
|
+
if (container && container.scrollTop === 0) {
|
|
2230
|
+
startYRef.current = e.touches[0].clientY;
|
|
2231
|
+
isPullingRef.current = true;
|
|
2232
|
+
}
|
|
2233
|
+
}, [disabled, isRefreshing]);
|
|
2234
|
+
const handleTouchMove = useCallback((e) => {
|
|
2235
|
+
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2236
|
+
return;
|
|
2237
|
+
const container = containerRef.current;
|
|
2238
|
+
if (!container || container.scrollTop > 0)
|
|
2239
|
+
return;
|
|
2240
|
+
const currentY = e.touches[0].clientY;
|
|
2241
|
+
const rawDistance = currentY - startYRef.current;
|
|
2242
|
+
if (rawDistance > 0) {
|
|
2243
|
+
// Rubber-band resistance formula
|
|
2244
|
+
const dampened = Math.min(maxPullDistance, rawDistance * 0.45);
|
|
2245
|
+
setPullDistance(dampened);
|
|
2246
|
+
if (e.cancelable) {
|
|
2247
|
+
e.preventDefault();
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
else {
|
|
2251
|
+
setPullDistance(0);
|
|
2252
|
+
}
|
|
2253
|
+
}, [disabled, isRefreshing, maxPullDistance]);
|
|
2254
|
+
const handleTouchEnd = useCallback(async () => {
|
|
2255
|
+
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2256
|
+
return;
|
|
2257
|
+
isPullingRef.current = false;
|
|
2258
|
+
if (pullDistance >= pullThreshold) {
|
|
2259
|
+
setPullDistance(pullThreshold);
|
|
2260
|
+
setInternalRefreshing(true);
|
|
2261
|
+
try {
|
|
2262
|
+
await onRefresh();
|
|
2263
|
+
}
|
|
2264
|
+
finally {
|
|
2265
|
+
setInternalRefreshing(false);
|
|
2266
|
+
setPullDistance(0);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
else {
|
|
2270
|
+
setPullDistance(0);
|
|
2271
|
+
}
|
|
2272
|
+
}, [disabled, isRefreshing, onRefresh, pullDistance, pullThreshold]);
|
|
2273
|
+
const progress = Math.min(1, pullDistance / pullThreshold);
|
|
2274
|
+
const isReady = pullDistance >= pullThreshold;
|
|
2275
|
+
return (jsxs("div", { ref: containerRef, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, className: buildClassName('relative overflow-y-auto overscroll-none', className), "data-testid": "pull-to-refresh-container", children: [jsx("div", { className: "left-0 right-0 top-0 flex items-center justify-center pointer-events-none transition-all duration-150 z-20", style: {
|
|
2276
|
+
height: isRefreshing ? `${pullThreshold}px` : `${pullDistance}px`,
|
|
2277
|
+
opacity: pullDistance > 0 || isRefreshing ? 1 : 0,
|
|
2278
|
+
}, "data-testid": "pull-to-refresh-indicator", children: jsx("div", { className: "flex items-center gap-2 px-3.5 py-1.5 rounded-full bg-white dark:bg-gray-800 border border-[var(--ui-border)] shadow-md text-xs font-semibold text-gray-700 dark:text-gray-200", children: isRefreshing ? (refreshingContent || (jsxs(Fragment, { children: [jsx(Loader, { size: "sm" }), jsx("span", { children: "Refreshing..." })] }))) : pullingContent ? (pullingContent) : (jsxs(Fragment, { children: [jsx(PullArrowIcon, { progress: progress }), jsx("span", { children: isReady ? 'Release to refresh' : 'Pull down to refresh' })] })) }) }), jsx("div", { className: buildClassName('transition-transform duration-150', contentClass), style: {
|
|
2279
|
+
transform: isRefreshing
|
|
2280
|
+
? `translateY(${pullThreshold}px)`
|
|
2281
|
+
: pullDistance > 0
|
|
2282
|
+
? `translateY(${pullDistance}px)`
|
|
2283
|
+
: 'translateY(0px)',
|
|
2284
|
+
}, "data-testid": "pull-to-refresh-content", children: children })] }));
|
|
2285
|
+
}
|
|
2286
|
+
PullToRefresh.displayName = 'PullToRefresh';
|
|
2287
|
+
|
|
1636
2288
|
const SIZE_MAP = {
|
|
1637
2289
|
sm: 'size-4',
|
|
1638
2290
|
md: 'size-4.5',
|
|
@@ -1648,8 +2300,8 @@ const Radio = forwardRef((props, ref) => {
|
|
|
1648
2300
|
const generatedId = useId();
|
|
1649
2301
|
const radioId = id !== null && id !== void 0 ? id : (name && rest.value ? `${name}-${rest.value}` : generatedId);
|
|
1650
2302
|
return (jsxs("div", { className: buildClassName(wrapperClass), children: [jsxs("div", { className: buildClassName('flex items-start gap-2.5', containerClass), children: [jsx("div", { className: "grid place-items-center shrink-0 pt-0.5", children: jsx("input", { ref: ref, ...rest, id: radioId, name: name, type: "radio", disabled: disabled, "aria-checked": rest.checked, className: buildClassName('peer transition-all col-start-1 row-start-1 appearance-none shrink-0 rounded-full', 'border focus:ring-2 focus:ring-offset-2', 'checked:border-5 checked:bg-white', 'dark:focus:ring-offset-gray-800', SIZE_MAP[size], THEME_MAP[theme], disabled
|
|
1651
|
-
? 'border-
|
|
1652
|
-
: 'bg-white dark:bg-gray-700 border-
|
|
2303
|
+
? 'border-[var(--ui-border-muted)] bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
2304
|
+
: 'bg-white dark:bg-gray-700 border-[var(--ui-border)] hover:border-gray-400 dark:hover:border-gray-500 cursor-pointer', className) }) }), (label || description) && (jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [label && (jsx(Label, { htmlFor: radioId, className: buildClassName(disabled
|
|
1653
2305
|
? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
|
|
1654
2306
|
: 'cursor-pointer text-gray-700 dark:text-gray-200 font-medium', labelClass), children: label })), description && (jsx("p", { className: buildClassName('text-xs leading-normal', disabled
|
|
1655
2307
|
? 'text-gray-300 dark:text-gray-600'
|
|
@@ -1688,7 +2340,7 @@ const RadioGroup = (props) => {
|
|
|
1688
2340
|
if (isCards) {
|
|
1689
2341
|
return (jsxs("label", { htmlFor: `${name}-${item.value}`, className: buildClassName('relative flex items-start gap-3 p-4 rounded-xl border transition-all cursor-pointer select-none min-w-[200px] flex-1', isSelected
|
|
1690
2342
|
? 'border-[var(--ui-primary)] bg-blue-50/40 dark:bg-blue-950/30 ring-2 ring-[var(--ui-primary-ring)]/30'
|
|
1691
|
-
: 'border-
|
|
2343
|
+
: 'border-[var(--ui-border)] bg-white dark:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600', isItemDisabled &&
|
|
1692
2344
|
'opacity-50 cursor-not-allowed pointer-events-none bg-gray-50 dark:bg-gray-800/50'), children: [jsx(Radio, { name: name, id: `${name}-${item.value}`, value: item.value, "aria-label": item.label, size: size, theme: theme, checked: isSelected, disabled: isItemDisabled, onChange: onChange, containerClass: "pt-0.5" }), jsxs("div", { className: "flex-1 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2", children: [item.icon && (jsx("span", { className: "shrink-0 text-gray-500 dark:text-gray-400", children: item.icon })), jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white truncate", children: item.label })] }), item.description && (jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400 font-normal leading-relaxed", children: item.description }))] })] }, item.value));
|
|
1693
2345
|
}
|
|
1694
2346
|
return (jsx(Radio, { name: name, id: `${name}-${item.value}`, label: item.label, description: item.description, value: item.value, size: size, theme: theme, checked: isSelected, disabled: isItemDisabled, onChange: onChange }, item.value));
|
|
@@ -1783,7 +2435,7 @@ const RadioSwitch = ({ label, items, selected, size = 'md', theme = 'primary', d
|
|
|
1783
2435
|
onChange(getValue(nextItem));
|
|
1784
2436
|
}
|
|
1785
2437
|
};
|
|
1786
|
-
return (jsxs("div", { ref: containerRef, role: "radiogroup", tabIndex: 0, "aria-label": label, onKeyDown: handleGroupKeyDown, className: buildClassName('relative inline-grid grid-flow-col auto-cols-fr items-stretch bg-gray-100 dark:bg-gray-800/80 border border-
|
|
2438
|
+
return (jsxs("div", { ref: containerRef, role: "radiogroup", tabIndex: 0, "aria-label": label, onKeyDown: handleGroupKeyDown, className: buildClassName('relative inline-grid grid-flow-col auto-cols-fr items-stretch bg-gray-100 dark:bg-gray-800/80 border border-[var(--ui-border)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]', SIZE_CONTAINER_CLASS$1[size], disabled && 'opacity-60 pointer-events-none', wrapperClass), children: [jsx("div", { className: buildClassName('absolute transition-all duration-200 ease-[cubic-bezier(.25,.8,.25,1)] pointer-events-none', THEME_SWITCH_CLASS[theme], size === 'sm' ? 'rounded-md' : 'rounded-lg', style.ready ? 'opacity-100' : 'opacity-0', switchClass), style: {
|
|
1787
2439
|
transform: `translate(${style.left}px, ${style.top}px)`,
|
|
1788
2440
|
width: style.width,
|
|
1789
2441
|
height: style.height,
|
|
@@ -1963,155 +2615,1112 @@ const RangeSlider = ({ label, labelHint, labelClass = '', containerClass = '', c
|
|
|
1963
2615
|
window.addEventListener('pointermove', stablePointerMoveRef.current);
|
|
1964
2616
|
window.addEventListener('pointerup', stablePointerUpRef.current);
|
|
1965
2617
|
};
|
|
1966
|
-
const handleTrackClick = (e) => {
|
|
1967
|
-
if (!trackRef.current)
|
|
2618
|
+
const handleTrackClick = (e) => {
|
|
2619
|
+
if (!trackRef.current)
|
|
2620
|
+
return;
|
|
2621
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
2622
|
+
const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width);
|
|
2623
|
+
const rawVal = min + (x / rect.width) * (max - min);
|
|
2624
|
+
const snappedVal = snapToStep(rawVal);
|
|
2625
|
+
const pxMin = (percent(valueMin) / 100) * rect.width;
|
|
2626
|
+
const pxMax = (percent(valueMax) / 100) * rect.width;
|
|
2627
|
+
if (x <= pxMin) {
|
|
2628
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2631
|
+
if (x >= pxMax) {
|
|
2632
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
2633
|
+
return;
|
|
2634
|
+
}
|
|
2635
|
+
const distMin = Math.abs(snappedVal - valueMin);
|
|
2636
|
+
const distMax = Math.abs(snappedVal - valueMax);
|
|
2637
|
+
if (distMin < distMax) {
|
|
2638
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
2639
|
+
}
|
|
2640
|
+
else {
|
|
2641
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
// Keyboard accessibility handler for thumbs
|
|
2645
|
+
const handleKeyDown = (thumb) => (e) => {
|
|
2646
|
+
let delta = 0;
|
|
2647
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown')
|
|
2648
|
+
delta = -step;
|
|
2649
|
+
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp')
|
|
2650
|
+
delta = step;
|
|
2651
|
+
else if (e.key === 'Home') {
|
|
2652
|
+
if (thumb === 'min')
|
|
2653
|
+
onChange(min, valueMax);
|
|
2654
|
+
else
|
|
2655
|
+
onChange(valueMin, valueMin + step);
|
|
2656
|
+
return;
|
|
2657
|
+
}
|
|
2658
|
+
else if (e.key === 'End') {
|
|
2659
|
+
if (thumb === 'min')
|
|
2660
|
+
onChange(valueMax - step, valueMax);
|
|
2661
|
+
else
|
|
2662
|
+
onChange(valueMin, max);
|
|
2663
|
+
return;
|
|
2664
|
+
}
|
|
2665
|
+
if (delta !== 0) {
|
|
2666
|
+
e.preventDefault();
|
|
2667
|
+
if (thumb === 'min') {
|
|
2668
|
+
const next = snapToStep(valueMin + delta);
|
|
2669
|
+
onChange(Math.min(next, valueMax - step), valueMax);
|
|
2670
|
+
}
|
|
2671
|
+
else {
|
|
2672
|
+
const next = snapToStep(valueMax + delta);
|
|
2673
|
+
onChange(valueMin, Math.max(next, valueMin + step));
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
};
|
|
2677
|
+
const markEntries = marks
|
|
2678
|
+
? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))
|
|
2679
|
+
: null;
|
|
2680
|
+
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: "flex items-center justify-between mb-1", children: [jsx(Label, { className: labelClass, children: label }), labelHint] })), jsxs("div", { ref: trackRef, onMouseDown: handleTrackClick, className: "relative h-8 select-none w-full flex items-center cursor-pointer", "data-testid": "range-track", children: [jsx("div", { className: buildClassName('absolute top-1/2 left-0 right-0 rounded-full bg-gray-200 dark:bg-gray-700 -translate-y-1/2', currentSize.track) }), jsx("div", { className: buildClassName('absolute top-1/2 -translate-y-1/2 rounded-full transition-all duration-150 ease-out', hasError ? 'bg-red-500' : 'bg-blue-600 dark:bg-blue-500', currentSize.track), style: {
|
|
2681
|
+
left: `${percent(valueMin)}%`,
|
|
2682
|
+
width: `${percent(valueMax) - percent(valueMin)}%`,
|
|
2683
|
+
} }), jsx("div", { role: "slider", tabIndex: 0, "aria-label": "Minimum value", "aria-valuenow": valueMin, "aria-valuemin": min, "aria-valuemax": valueMax - step, onPointerDown: startDrag('min'), onMouseEnter: () => setHoveringThumb('min'), onMouseLeave: () => setHoveringThumb(null), onKeyDown: handleKeyDown('min'), className: buildClassName('absolute top-1/2 -translate-y-1/2 rounded-full focus:outline-none', 'bg-white border-2 shadow-md cursor-pointer touch-none', hasError ? 'border-red-600' : 'border-blue-600', 'transition-all duration-150 ease-out', currentSize.thumb, (activeThumbState === 'min' || hoveringThumb === 'min') &&
|
|
2684
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
2685
|
+
left: `calc(${percent(valueMin)}% - ${currentSize.thumbPx / 2}px)`,
|
|
2686
|
+
zIndex: activeThumbState === 'min' ? 50 : 30,
|
|
2687
|
+
}, "data-testid": "thumb-min", children: showTooltips && (activeThumbState === 'min' || hoveringThumb === 'min') && (jsxs("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 px-2 py-0.5 rounded bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-[11px] font-semibold shadow-md pointer-events-none z-50 whitespace-nowrap", children: [Math.round(valueMin), valueSuffix, jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-100" })] })) }), jsx("div", { role: "slider", tabIndex: 0, "aria-label": "Maximum value", "aria-valuenow": valueMax, "aria-valuemin": valueMin + step, "aria-valuemax": max, onPointerDown: startDrag('max'), onMouseEnter: () => setHoveringThumb('max'), onMouseLeave: () => setHoveringThumb(null), onKeyDown: handleKeyDown('max'), className: buildClassName('absolute top-1/2 -translate-y-1/2 rounded-full focus:outline-none', 'bg-white border-2 shadow-md cursor-pointer touch-none', hasError ? 'border-red-600' : 'border-blue-600', 'transition-all duration-150 ease-out', currentSize.thumb, (activeThumbState === 'max' || hoveringThumb === 'max') &&
|
|
2688
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
2689
|
+
left: `calc(${percent(valueMax)}% - ${currentSize.thumbPx / 2}px)`,
|
|
2690
|
+
zIndex: activeThumbState === 'max' ? 50 : 40,
|
|
2691
|
+
}, "data-testid": "thumb-max", children: showTooltips && (activeThumbState === 'max' || hoveringThumb === 'max') && (jsxs("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 px-2 py-0.5 rounded bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-[11px] font-semibold shadow-md pointer-events-none z-50 whitespace-nowrap", children: [Math.round(valueMax), valueSuffix, jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-100" })] })) })] }), markEntries && (jsx("div", { className: "relative w-full h-4 mt-1", children: markEntries.map((m) => {
|
|
2692
|
+
const markPercent = percent(m.value);
|
|
2693
|
+
return (jsxs("div", { className: "absolute top-0 transform -translate-x-1/2 flex flex-col items-center", style: { left: `${markPercent}%` }, children: [jsx("span", { className: "w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full" }), jsx("span", { className: "text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5", children: m.label })] }, m.value));
|
|
2694
|
+
}) })), jsxs("div", { className: buildClassName('flex justify-between font-medium text-gray-700 dark:text-gray-300', currentSize.text), children: [jsxs("span", { children: [Math.round(valueMin), valueSuffix] }), jsxs("span", { children: [Math.round(valueMax), valueSuffix] })] }), (showErrorMessage && hasError) || helperText ? (jsx("div", { className: "mt-1", children: showErrorMessage && hasError ? (jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsx(TextContent, { muted: true, small: true, children: helperText })) : null })) : null] }));
|
|
2695
|
+
};
|
|
2696
|
+
RangeSlider.displayName = 'RangeSlider';
|
|
2697
|
+
|
|
2698
|
+
const useDebounce = (value, delay) => {
|
|
2699
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
2700
|
+
useEffect(() => {
|
|
2701
|
+
const handler = setTimeout(() => {
|
|
2702
|
+
setDebouncedValue(value);
|
|
2703
|
+
}, delay);
|
|
2704
|
+
// Cancel the timeout if value or delay changes
|
|
2705
|
+
return () => {
|
|
2706
|
+
clearTimeout(handler);
|
|
2707
|
+
};
|
|
2708
|
+
}, [value, delay]);
|
|
2709
|
+
return debouncedValue;
|
|
2710
|
+
};
|
|
2711
|
+
const useDebounceFn = (fn, ms) => {
|
|
2712
|
+
const timeout = useRef(null);
|
|
2713
|
+
useEffect(() => {
|
|
2714
|
+
return () => clearTimeout(timeout.current);
|
|
2715
|
+
}, []);
|
|
2716
|
+
return useCallback((...args) => {
|
|
2717
|
+
clearTimeout(timeout.current);
|
|
2718
|
+
timeout.current = setTimeout(() => fn(...args), ms);
|
|
2719
|
+
}, [fn, ms]);
|
|
2720
|
+
};
|
|
2721
|
+
|
|
2722
|
+
var _path$2;
|
|
2723
|
+
function _extends$2() { return _extends$2 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$2.apply(null, arguments); }
|
|
2724
|
+
var SvgCheck = function SvgCheck(props) {
|
|
2725
|
+
return /*#__PURE__*/React.createElement("svg", _extends$2({
|
|
2726
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2727
|
+
width: 24,
|
|
2728
|
+
height: 24,
|
|
2729
|
+
fill: "none",
|
|
2730
|
+
stroke: "currentColor",
|
|
2731
|
+
strokeLinecap: "round",
|
|
2732
|
+
strokeLinejoin: "round",
|
|
2733
|
+
strokeWidth: 2,
|
|
2734
|
+
className: "lucide lucide-check-icon lucide-check",
|
|
2735
|
+
viewBox: "0 0 24 24"
|
|
2736
|
+
}, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
|
|
2737
|
+
d: "M20 6 9 17l-5-5"
|
|
2738
|
+
})));
|
|
2739
|
+
};
|
|
2740
|
+
|
|
2741
|
+
var _circle$1, _path$1;
|
|
2742
|
+
function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
|
|
2743
|
+
var SvgCirclePlus = function SvgCirclePlus(props) {
|
|
2744
|
+
return /*#__PURE__*/React.createElement("svg", _extends$1({
|
|
2745
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2746
|
+
width: 24,
|
|
2747
|
+
height: 24,
|
|
2748
|
+
fill: "none",
|
|
2749
|
+
stroke: "currentColor",
|
|
2750
|
+
strokeLinecap: "round",
|
|
2751
|
+
strokeLinejoin: "round",
|
|
2752
|
+
strokeWidth: 2,
|
|
2753
|
+
className: "lucide lucide-circle-plus-icon lucide-circle-plus",
|
|
2754
|
+
viewBox: "0 0 24 24"
|
|
2755
|
+
}, props), _circle$1 || (_circle$1 = /*#__PURE__*/React.createElement("circle", {
|
|
2756
|
+
cx: 12,
|
|
2757
|
+
cy: 12,
|
|
2758
|
+
r: 10
|
|
2759
|
+
})), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
|
|
2760
|
+
d: "M8 12h8M12 8v8"
|
|
2761
|
+
})));
|
|
2762
|
+
};
|
|
2763
|
+
|
|
2764
|
+
var _circle, _path;
|
|
2765
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2766
|
+
var SvgSearch = function SvgSearch(props) {
|
|
2767
|
+
return /*#__PURE__*/React.createElement("svg", _extends({
|
|
2768
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2769
|
+
width: 24,
|
|
2770
|
+
height: 24,
|
|
2771
|
+
fill: "none",
|
|
2772
|
+
stroke: "currentColor",
|
|
2773
|
+
strokeLinecap: "round",
|
|
2774
|
+
strokeLinejoin: "round",
|
|
2775
|
+
strokeWidth: 2,
|
|
2776
|
+
className: "lucide lucide-search-icon lucide-search",
|
|
2777
|
+
viewBox: "0 0 24 24"
|
|
2778
|
+
}, props), _circle || (_circle = /*#__PURE__*/React.createElement("circle", {
|
|
2779
|
+
cx: 11,
|
|
2780
|
+
cy: 11,
|
|
2781
|
+
r: 8
|
|
2782
|
+
})), _path || (_path = /*#__PURE__*/React.createElement("path", {
|
|
2783
|
+
d: "m21 21-4.3-4.3"
|
|
2784
|
+
})));
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
const sizeConfigMap = {
|
|
2788
|
+
sm: {
|
|
2789
|
+
input: 'h-8 text-xs px-2.5',
|
|
2790
|
+
icon: 'size-3.5',
|
|
2791
|
+
badgeSize: 'sm',
|
|
2792
|
+
group: 'w-8',
|
|
2793
|
+
},
|
|
2794
|
+
md: {
|
|
2795
|
+
input: 'h-10 text-sm px-3',
|
|
2796
|
+
icon: 'size-4',
|
|
2797
|
+
badgeSize: 'md',
|
|
2798
|
+
group: 'w-10',
|
|
2799
|
+
},
|
|
2800
|
+
lg: {
|
|
2801
|
+
input: 'h-12 text-base px-3.5',
|
|
2802
|
+
icon: 'size-5',
|
|
2803
|
+
badgeSize: 'md',
|
|
2804
|
+
group: 'w-12',
|
|
2805
|
+
},
|
|
2806
|
+
};
|
|
2807
|
+
function MobilePicker(props) {
|
|
2808
|
+
const { options = [], groups, selected = null, onChange = () => { }, size = 'md', labelKey = 'label', valueKey = 'value', id, name, label, labelWrapperClass, labelClass, labelHint, title, description, placeholder = 'Choose an option...', disabled = false, multiple = false, maxSelection, showSelectAll = false, confirmText = 'Apply Selection', searchable = true, searchPlaceholder = 'Search options...', async = false, onSearch, loading = false, typeToSearchText = 'Type to search options...', filterOption, quickOptions, quickOptionsTitle = 'Quick Picks', allowClear = false, allowFreeText = false, allowAdd = false, addNewText = 'Create', onAdd = () => { }, leftGroup, error, showErrorMessage = true, helperText, noOptionsText = 'No options available', renderOption, containerClass, sheetClass, } = props;
|
|
2809
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
2810
|
+
const [query, setQuery] = useState('');
|
|
2811
|
+
const debouncedQuery = useDebounce(query, 400);
|
|
2812
|
+
const [optionsLoading, setOptionsLoading] = useState(false);
|
|
2813
|
+
const [draftSelected, setDraftSelected] = useState(selected);
|
|
2814
|
+
const [viewportHeight, setViewportHeight] = useState(null);
|
|
2815
|
+
useEffect(() => {
|
|
2816
|
+
if (!isOpen) {
|
|
2817
|
+
setViewportHeight(null);
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2820
|
+
const updateHeight = () => {
|
|
2821
|
+
if (typeof window !== 'undefined' && window.visualViewport) {
|
|
2822
|
+
setViewportHeight(window.visualViewport.height);
|
|
2823
|
+
}
|
|
2824
|
+
};
|
|
2825
|
+
updateHeight();
|
|
2826
|
+
const vv = typeof window !== 'undefined' ? window.visualViewport : null;
|
|
2827
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('resize', updateHeight);
|
|
2828
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('scroll', updateHeight);
|
|
2829
|
+
return () => {
|
|
2830
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('resize', updateHeight);
|
|
2831
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('scroll', updateHeight);
|
|
2832
|
+
};
|
|
2833
|
+
}, [isOpen]);
|
|
2834
|
+
const currentSize = sizeConfigMap[size] || sizeConfigMap.md;
|
|
2835
|
+
const hasError = Boolean(error);
|
|
2836
|
+
const isAsyncLoading = loading || optionsLoading;
|
|
2837
|
+
const baseInputClass = useMemo(() => buildInputClass('', { disabled, hasError, size }), [disabled, hasError, size]);
|
|
2838
|
+
const onSearchRef = useRef(onSearch);
|
|
2839
|
+
useEffect(() => {
|
|
2840
|
+
onSearchRef.current = onSearch;
|
|
2841
|
+
}, [onSearch]);
|
|
2842
|
+
const handleAsyncSearch = useCallback(async (searchString) => {
|
|
2843
|
+
var _a;
|
|
2844
|
+
try {
|
|
2845
|
+
setOptionsLoading(true);
|
|
2846
|
+
await ((_a = onSearchRef.current) === null || _a === void 0 ? void 0 : _a.call(onSearchRef, searchString));
|
|
2847
|
+
}
|
|
2848
|
+
catch (err) {
|
|
2849
|
+
console.error('Error loading options:', err);
|
|
2850
|
+
}
|
|
2851
|
+
finally {
|
|
2852
|
+
setOptionsLoading(false);
|
|
2853
|
+
}
|
|
2854
|
+
}, []);
|
|
2855
|
+
useEffect(() => {
|
|
2856
|
+
if (isOpen && async) {
|
|
2857
|
+
handleAsyncSearch(debouncedQuery);
|
|
2858
|
+
}
|
|
2859
|
+
}, [isOpen, async, debouncedQuery, handleAsyncSearch]);
|
|
2860
|
+
const getDisplayValue = useCallback((opt) => {
|
|
2861
|
+
var _a, _b;
|
|
2862
|
+
if (typeof opt === 'string')
|
|
2863
|
+
return opt;
|
|
2864
|
+
return (_b = (_a = opt === null || opt === void 0 ? void 0 : opt[labelKey]) !== null && _a !== void 0 ? _a : opt === null || opt === void 0 ? void 0 : opt[valueKey]) !== null && _b !== void 0 ? _b : String(opt);
|
|
2865
|
+
}, [labelKey, valueKey]);
|
|
2866
|
+
const getValue = useCallback((opt) => {
|
|
2867
|
+
var _a, _b;
|
|
2868
|
+
if (typeof opt === 'string')
|
|
2869
|
+
return opt;
|
|
2870
|
+
return (_b = (_a = opt === null || opt === void 0 ? void 0 : opt[valueKey]) !== null && _a !== void 0 ? _a : opt === null || opt === void 0 ? void 0 : opt[labelKey]) !== null && _b !== void 0 ? _b : String(opt);
|
|
2871
|
+
}, [valueKey, labelKey]);
|
|
2872
|
+
const normalizedSelected = useMemo(() => {
|
|
2873
|
+
if (multiple) {
|
|
2874
|
+
if (Array.isArray(selected))
|
|
2875
|
+
return selected;
|
|
2876
|
+
if (selected !== null && selected !== undefined)
|
|
2877
|
+
return [selected];
|
|
2878
|
+
return [];
|
|
2879
|
+
}
|
|
2880
|
+
else {
|
|
2881
|
+
if (Array.isArray(selected))
|
|
2882
|
+
return selected.length > 0 ? selected[0] : null;
|
|
2883
|
+
return selected !== null && selected !== void 0 ? selected : null;
|
|
2884
|
+
}
|
|
2885
|
+
}, [multiple, selected]);
|
|
2886
|
+
const normalizedDraft = useMemo(() => {
|
|
2887
|
+
if (multiple) {
|
|
2888
|
+
if (Array.isArray(draftSelected))
|
|
2889
|
+
return draftSelected;
|
|
2890
|
+
if (draftSelected !== null && draftSelected !== undefined)
|
|
2891
|
+
return [draftSelected];
|
|
2892
|
+
return [];
|
|
2893
|
+
}
|
|
2894
|
+
else {
|
|
2895
|
+
if (Array.isArray(draftSelected))
|
|
2896
|
+
return draftSelected.length > 0 ? draftSelected[0] : null;
|
|
2897
|
+
return draftSelected !== null && draftSelected !== void 0 ? draftSelected : null;
|
|
2898
|
+
}
|
|
2899
|
+
}, [multiple, draftSelected]);
|
|
2900
|
+
const rawAllOptions = useMemo(() => {
|
|
2901
|
+
if (groups === null || groups === void 0 ? void 0 : groups.length) {
|
|
2902
|
+
return groups.flatMap((g) => g.options);
|
|
2903
|
+
}
|
|
2904
|
+
return options !== null && options !== void 0 ? options : [];
|
|
2905
|
+
}, [groups, options]);
|
|
2906
|
+
const allOptions = useMemo(() => {
|
|
2907
|
+
const list = [...rawAllOptions];
|
|
2908
|
+
const selectedList = Array.isArray(normalizedDraft)
|
|
2909
|
+
? normalizedDraft
|
|
2910
|
+
: normalizedDraft
|
|
2911
|
+
? [normalizedDraft]
|
|
2912
|
+
: [];
|
|
2913
|
+
for (const sel of selectedList) {
|
|
2914
|
+
if (sel !== null && sel !== undefined) {
|
|
2915
|
+
const selVal = getValue(sel);
|
|
2916
|
+
const exists = list.some((item) => getValue(item) === selVal);
|
|
2917
|
+
if (!exists) {
|
|
2918
|
+
list.unshift(sel);
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
return list;
|
|
2923
|
+
}, [rawAllOptions, normalizedDraft, getValue]);
|
|
2924
|
+
useEffect(() => {
|
|
2925
|
+
if (isOpen) {
|
|
2926
|
+
setDraftSelected(normalizedSelected);
|
|
2927
|
+
setQuery('');
|
|
2928
|
+
}
|
|
2929
|
+
}, [isOpen, normalizedSelected]);
|
|
2930
|
+
const defaultFilter = useCallback((opt, q) => {
|
|
2931
|
+
var _a;
|
|
2932
|
+
if (!q.trim())
|
|
2933
|
+
return true;
|
|
2934
|
+
const searchTarget = ((_a = getDisplayValue(opt)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
2935
|
+
return searchTarget.includes(q.trim().toLowerCase());
|
|
2936
|
+
}, [getDisplayValue]);
|
|
2937
|
+
const activeFilter = filterOption || defaultFilter;
|
|
2938
|
+
const filteredOptions = useMemo(() => {
|
|
2939
|
+
if (async)
|
|
2940
|
+
return allOptions;
|
|
2941
|
+
if (!query.trim())
|
|
2942
|
+
return allOptions;
|
|
2943
|
+
return allOptions.filter((opt) => activeFilter(opt, query));
|
|
2944
|
+
}, [allOptions, query, async, activeFilter]);
|
|
2945
|
+
const filteredGroups = useMemo(() => {
|
|
2946
|
+
if (!(groups === null || groups === void 0 ? void 0 : groups.length))
|
|
2947
|
+
return null;
|
|
2948
|
+
if (async)
|
|
2949
|
+
return groups;
|
|
2950
|
+
if (!query.trim())
|
|
2951
|
+
return groups;
|
|
2952
|
+
return groups
|
|
2953
|
+
.map((g) => ({
|
|
2954
|
+
...g,
|
|
2955
|
+
options: g.options.filter((opt) => activeFilter(opt, query)),
|
|
2956
|
+
}))
|
|
2957
|
+
.filter((g) => g.options.length > 0);
|
|
2958
|
+
}, [groups, query, async, activeFilter]);
|
|
2959
|
+
const createFreeTextOption = useCallback((text) => {
|
|
2960
|
+
const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected);
|
|
2961
|
+
if (typeof sample === 'string' ||
|
|
2962
|
+
(!sample && typeof labelKey === 'string' && labelKey === 'label')) {
|
|
2963
|
+
return text;
|
|
2964
|
+
}
|
|
2965
|
+
return {
|
|
2966
|
+
[labelKey]: text,
|
|
2967
|
+
[valueKey]: text,
|
|
2968
|
+
};
|
|
2969
|
+
}, [allOptions, selected, labelKey, valueKey]);
|
|
2970
|
+
const handleToggleOption = (option) => {
|
|
2971
|
+
const optVal = getValue(option);
|
|
2972
|
+
if (multiple) {
|
|
2973
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
2974
|
+
const index = current.findIndex((item) => getValue(item) === optVal);
|
|
2975
|
+
if (index > -1) {
|
|
2976
|
+
current.splice(index, 1);
|
|
2977
|
+
setDraftSelected(current);
|
|
2978
|
+
}
|
|
2979
|
+
else {
|
|
2980
|
+
if (maxSelection && current.length >= maxSelection)
|
|
2981
|
+
return;
|
|
2982
|
+
current.push(option);
|
|
2983
|
+
setDraftSelected(current);
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
else {
|
|
2987
|
+
setDraftSelected(option);
|
|
2988
|
+
onChange(option);
|
|
2989
|
+
setIsOpen(false);
|
|
2990
|
+
}
|
|
2991
|
+
};
|
|
2992
|
+
const handleCommitFreeText = (text) => {
|
|
2993
|
+
const trimmed = text.trim();
|
|
2994
|
+
if (!trimmed)
|
|
2995
|
+
return;
|
|
2996
|
+
const existing = allOptions.find((opt) => getDisplayValue(opt).toLowerCase() === trimmed.toLowerCase());
|
|
2997
|
+
const optionToCommit = existing || createFreeTextOption(trimmed);
|
|
2998
|
+
if (multiple) {
|
|
2999
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
3000
|
+
const already = current.some((item) => getDisplayValue(item).toLowerCase() === trimmed.toLowerCase());
|
|
3001
|
+
if (!already) {
|
|
3002
|
+
if (maxSelection && current.length >= maxSelection)
|
|
3003
|
+
return;
|
|
3004
|
+
current.push(optionToCommit);
|
|
3005
|
+
setDraftSelected(current);
|
|
3006
|
+
}
|
|
3007
|
+
setQuery('');
|
|
3008
|
+
}
|
|
3009
|
+
else {
|
|
3010
|
+
setDraftSelected(optionToCommit);
|
|
3011
|
+
onChange(optionToCommit);
|
|
3012
|
+
setIsOpen(false);
|
|
3013
|
+
}
|
|
3014
|
+
};
|
|
3015
|
+
const handleAddAndSelect = async (valueToAdd) => {
|
|
3016
|
+
try {
|
|
3017
|
+
const result = await onAdd(valueToAdd);
|
|
3018
|
+
const optionToCommit = (result || valueToAdd);
|
|
3019
|
+
if (multiple) {
|
|
3020
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
3021
|
+
current.push(optionToCommit);
|
|
3022
|
+
setDraftSelected(current);
|
|
3023
|
+
setQuery('');
|
|
3024
|
+
}
|
|
3025
|
+
else {
|
|
3026
|
+
setDraftSelected(optionToCommit);
|
|
3027
|
+
onChange(optionToCommit);
|
|
3028
|
+
setIsOpen(false);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
catch (err) {
|
|
3032
|
+
console.error('MobilePicker onAdd error:', err);
|
|
3033
|
+
}
|
|
3034
|
+
};
|
|
3035
|
+
const isAllSelected = useMemo(() => {
|
|
3036
|
+
if (!multiple || !Array.isArray(normalizedDraft) || !allOptions.length)
|
|
3037
|
+
return false;
|
|
3038
|
+
return allOptions.length === normalizedDraft.length;
|
|
3039
|
+
}, [multiple, normalizedDraft, allOptions]);
|
|
3040
|
+
const handleToggleSelectAll = () => {
|
|
3041
|
+
if (isAllSelected) {
|
|
3042
|
+
setDraftSelected([]);
|
|
3043
|
+
}
|
|
3044
|
+
else {
|
|
3045
|
+
setDraftSelected(allOptions);
|
|
3046
|
+
}
|
|
3047
|
+
};
|
|
3048
|
+
const handleConfirmMultiSelect = () => {
|
|
3049
|
+
onChange(normalizedDraft);
|
|
3050
|
+
setIsOpen(false);
|
|
3051
|
+
};
|
|
3052
|
+
const handleClearSingleSelect = (e) => {
|
|
3053
|
+
e.preventDefault();
|
|
3054
|
+
e.stopPropagation();
|
|
3055
|
+
setDraftSelected(multiple ? [] : null);
|
|
3056
|
+
onChange(multiple ? [] : null);
|
|
3057
|
+
};
|
|
3058
|
+
const handleTriggerClick = (e) => {
|
|
3059
|
+
if (disabled)
|
|
3060
|
+
return;
|
|
3061
|
+
const isClearClick = e.target.closest('[data-testid="mobile-picker-clear-button"]');
|
|
3062
|
+
if (isClearClick)
|
|
3063
|
+
return;
|
|
3064
|
+
setIsOpen(true);
|
|
3065
|
+
};
|
|
3066
|
+
const isOptionSelected = (option) => {
|
|
3067
|
+
const optVal = getValue(option);
|
|
3068
|
+
if (multiple) {
|
|
3069
|
+
return (Array.isArray(normalizedDraft) && normalizedDraft.some((item) => getValue(item) === optVal));
|
|
3070
|
+
}
|
|
3071
|
+
else {
|
|
3072
|
+
return Boolean(normalizedDraft && getValue(normalizedDraft) === optVal);
|
|
3073
|
+
}
|
|
3074
|
+
};
|
|
3075
|
+
const shouldShowTypeToSearch = async && !query && !isAsyncLoading && allOptions.length === 0;
|
|
3076
|
+
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
3077
|
+
return (jsxs("div", { className: buildClassName('group space-y-2 w-full', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("button", { type: "button", id: id, name: name, disabled: disabled, onClick: handleTriggerClick, className: buildClassName(baseInputClass, 'w-full flex items-center justify-between gap-2 cursor-pointer relative text-left', hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : ''), "data-testid": "mobile-picker-trigger", children: [hasLeftGroup && (jsx("span", { className: buildClassName('absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500', currentSize.group), children: leftGroup })), jsx("div", { className: "flex-1 flex flex-wrap items-center gap-1.5 min-w-0 overflow-hidden", children: multiple ? (Array.isArray(normalizedSelected) && normalizedSelected.length > 0 ? (normalizedSelected.map((item, idx) => (jsx(Badge, { theme: "secondary", size: currentSize.badgeSize, children: getDisplayValue(item) }, `${getValue(item)}-${idx}`)))) : (jsx("span", { className: "text-gray-400 dark:text-gray-500", children: placeholder }))) : normalizedSelected ? (jsx("span", { className: "text-gray-900 dark:text-white font-normal truncate", children: getDisplayValue(normalizedSelected) })) : (jsx("span", { className: "text-gray-400 dark:text-gray-500", children: placeholder })) }), jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [allowClear && !multiple && normalizedSelected && (jsx("span", { role: "button", "aria-label": "Clear selection", tabIndex: 0, onClick: handleClearSingleSelect, className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full cursor-pointer z-10", "data-testid": "mobile-picker-clear-button", children: jsx(SvgX, { className: "size-3.5 stroke-gray-500 dark:stroke-gray-400" }) })), jsx(SvgChevronDown, { className: buildClassName(currentSize.icon, 'stroke-gray-500 shrink-0') })] })] }), showErrorMessage && error && (jsx("div", { className: "mt-1", children: jsx(TextContent, { error: true, small: true, children: error }) })), !error && helperText && (jsx("div", { className: "mt-1", children: jsx(TextContent, { muted: true, small: true, children: helperText }) })), jsxs(Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: () => setIsOpen(false), transition: true, children: [jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/50 backdrop-blur-xs transition-opacity duration-200" }), jsx("div", { className: "fixed left-0 top-0 w-full flex items-end justify-center pointer-events-none z-50", style: {
|
|
3078
|
+
height: viewportHeight ? `${viewportHeight}px` : '100dvh',
|
|
3079
|
+
}, children: jsxs(DialogPanel, { transition: true, className: buildClassName('w-full max-w-full md:max-w-lg bg-white dark:bg-gray-900 shadow-2xl rounded-t-3xl max-h-[85vh] max-h-[85dvh] flex flex-col pointer-events-auto overscroll-contain touch-pan-y', 'duration-200 ease-out data-[closed]:translate-y-full data-[closed]:opacity-0', sheetClass), style: {
|
|
3080
|
+
maxHeight: viewportHeight ? `${Math.floor(viewportHeight * 0.9)}px` : undefined,
|
|
3081
|
+
}, "data-testid": "mobile-picker-sheet", children: [jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-700 mx-auto my-2.5 shrink-0" }), jsxs("div", { className: "px-4 pb-3 border-b border-[var(--ui-border-muted)] flex items-center justify-between gap-3 shrink-0", children: [jsxs("div", { className: "min-w-0 flex-1", children: [jsx(DialogTitle, { as: "h3", className: "text-base md:text-lg font-bold text-gray-900 dark:text-white truncate", children: title || label || 'Select Option' }), description && (jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate mt-0.5", children: description }))] }), jsx(Button, { iconOnly: true, "aria-label": "Close picker", variant: "plain", theme: "secondary", size: "xs", onClick: () => setIsOpen(false), className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) })] }), searchable && (jsx("div", { className: "p-3 border-b border-[var(--ui-border-muted)] bg-gray-50 dark:bg-gray-800/50 shrink-0", children: jsxs("div", { className: "relative", children: [jsx(SvgSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-gray-400" }), jsx("input", { type: "text", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: (e) => {
|
|
3082
|
+
if (allowFreeText && e.key === 'Enter' && query.trim()) {
|
|
3083
|
+
e.preventDefault();
|
|
3084
|
+
handleCommitFreeText(query);
|
|
3085
|
+
}
|
|
3086
|
+
}, placeholder: searchPlaceholder, className: "w-full pl-9 pr-10 py-2 text-sm bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-xl text-gray-900 dark:text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500", "data-testid": "mobile-picker-search-input" }), jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1.5", children: isAsyncLoading ? (jsx(Loader, { size: "xs" })) : (query && (jsx("button", { type: "button", onClick: () => setQuery(''), className: "p-0.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200", children: jsx(SvgX, { className: "size-3.5" }) }))) })] }) })), quickOptions && quickOptions.length > 0 && (jsxs("div", { className: "px-3 py-2 bg-gray-50/60 dark:bg-gray-800/40 border-b border-[var(--ui-border-muted)] shrink-0", children: [jsx("div", { className: "text-[11px] font-semibold text-gray-400 uppercase tracking-wider mb-1.5 px-1", children: quickOptionsTitle }), jsx("div", { className: "flex items-center gap-2 overflow-x-auto no-scrollbar pb-1", children: quickOptions.map((chip, cIdx) => {
|
|
3087
|
+
const isSelected = isOptionSelected(chip);
|
|
3088
|
+
return (jsx("button", { type: "button", onClick: () => handleToggleOption(chip), className: buildClassName('px-3 py-1 rounded-full text-xs font-medium shrink-0 transition-colors cursor-pointer border', isSelected
|
|
3089
|
+
? 'bg-blue-600 text-white border-blue-600'
|
|
3090
|
+
: 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-700'), children: getDisplayValue(chip) }, cIdx));
|
|
3091
|
+
}) })] })), multiple && showSelectAll && allOptions.length > 0 && (jsxs("div", { className: "px-4 py-2 bg-gray-50/80 dark:bg-gray-800/80 border-b border-[var(--ui-border-muted)] flex items-center justify-between text-xs shrink-0", children: [jsx("button", { type: "button", onClick: handleToggleSelectAll, className: "font-semibold text-blue-600 dark:text-blue-400 hover:underline cursor-pointer", children: isAllSelected ? 'Deselect All' : 'Select All' }), jsxs("span", { className: "text-gray-500 dark:text-gray-400 font-medium", children: [Array.isArray(normalizedDraft) ? normalizedDraft.length : 0, " of", ' ', allOptions.length] })] })), jsxs("div", { onScroll: (e) => {
|
|
3092
|
+
const el = e.currentTarget;
|
|
3093
|
+
if (el.scrollTop === 0) {
|
|
3094
|
+
el.scrollTop = 1;
|
|
3095
|
+
}
|
|
3096
|
+
else if (el.scrollTop + el.clientHeight >= el.scrollHeight) {
|
|
3097
|
+
el.scrollTop = el.scrollHeight - el.clientHeight - 1;
|
|
3098
|
+
}
|
|
3099
|
+
}, className: "flex-1 overflow-y-auto overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] p-2 space-y-1 divide-y divide-gray-100 dark:divide-gray-800/60", children: [allowFreeText &&
|
|
3100
|
+
query.trim() &&
|
|
3101
|
+
!allOptions.some((opt) => getDisplayValue(opt).toLowerCase() === query.trim().toLowerCase()) && (jsxs("button", { type: "button", onClick: () => handleCommitFreeText(query), className: "w-full text-left flex items-center justify-between p-3.5 rounded-2xl bg-blue-50/80 dark:bg-blue-950/30 text-blue-600 dark:text-blue-400 font-medium hover:bg-blue-100/80 cursor-pointer", "data-testid": "mobile-picker-freetext-item", children: [jsxs("span", { className: "text-sm font-medium", children: ["Use \"", query.trim(), "\""] }), jsx(SvgChevronDown, { className: "size-4 rotate-[-90deg]" })] })), isAsyncLoading && allOptions.length === 0 ? (jsxs("div", { className: "py-12 flex flex-col items-center justify-center gap-2 text-sm text-gray-500 dark:text-gray-400 select-none", children: [jsx(Loader, { size: "md" }), jsx("span", { children: "Loading options..." })] })) : shouldShowTypeToSearch ? (jsx("div", { className: "py-12 text-center text-sm text-gray-500 dark:text-gray-400 select-none", children: typeToSearchText })) : filteredGroups ? (filteredGroups.map((grp, gIdx) => (jsxs("div", { className: "pt-2", children: [jsx("div", { className: "text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500 px-3 py-1.5 select-none", children: grp.group }), jsx("div", { className: "space-y-1", children: grp.options.map((option) => {
|
|
3102
|
+
const optVal = getValue(option);
|
|
3103
|
+
const isSelected = isOptionSelected(option);
|
|
3104
|
+
const optDisabled = option.disabled;
|
|
3105
|
+
const optDesc = typeof option === 'object'
|
|
3106
|
+
? (option === null || option === void 0 ? void 0 : option.description) || (option === null || option === void 0 ? void 0 : option.subtitle)
|
|
3107
|
+
: null;
|
|
3108
|
+
return (jsxs("div", { onClick: () => !optDisabled && handleToggleOption(option), className: buildClassName('w-full flex items-center justify-between p-3.5 rounded-2xl transition-colors cursor-pointer select-none', isSelected
|
|
3109
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3110
|
+
: 'text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800/70', optDisabled && 'opacity-50 pointer-events-none'), children: [jsxs("div", { className: "flex-1 min-w-0 pr-3", children: [jsx("div", { className: "text-sm/6 truncate", children: renderOption
|
|
3111
|
+
? renderOption(option, isSelected)
|
|
3112
|
+
: getDisplayValue(option) }), optDesc && (jsx("div", { className: "text-xs text-gray-400 font-normal truncate mt-0.5", children: optDesc }))] }), isSelected && (jsx(SvgCheck, { className: "size-5 stroke-blue-600 dark:stroke-blue-400 shrink-0" }))] }, optVal));
|
|
3113
|
+
}) })] }, gIdx)))) : filteredOptions.length > 0 ? (filteredOptions.map((option) => {
|
|
3114
|
+
const optVal = getValue(option);
|
|
3115
|
+
const isSelected = isOptionSelected(option);
|
|
3116
|
+
const optDisabled = option.disabled;
|
|
3117
|
+
const optDesc = typeof option === 'object' ? (option === null || option === void 0 ? void 0 : option.description) || (option === null || option === void 0 ? void 0 : option.subtitle) : null;
|
|
3118
|
+
return (jsxs("div", { onClick: () => !optDisabled && handleToggleOption(option), className: buildClassName('w-full flex items-center justify-between p-3.5 rounded-2xl transition-colors cursor-pointer select-none', isSelected
|
|
3119
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3120
|
+
: 'text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800/70', optDisabled && 'opacity-50 pointer-events-none'), children: [jsxs("div", { className: "flex-1 min-w-0 pr-3", children: [jsx("div", { className: "text-sm/6 truncate", children: renderOption
|
|
3121
|
+
? renderOption(option, isSelected)
|
|
3122
|
+
: getDisplayValue(option) }), optDesc && (jsx("div", { className: "text-xs text-gray-400 font-normal truncate mt-0.5", children: optDesc }))] }), isSelected && (jsx(SvgCheck, { className: "size-5 stroke-blue-600 dark:stroke-blue-400 shrink-0" }))] }, optVal));
|
|
3123
|
+
})) : (!allowFreeText &&
|
|
3124
|
+
!(allowAdd && query.trim()) && (jsx("div", { className: "py-8 text-center text-sm text-gray-500 dark:text-gray-400 select-none", children: query
|
|
3125
|
+
? noOptionsText !== 'No options available'
|
|
3126
|
+
? noOptionsText
|
|
3127
|
+
: `No results found for "${query}"`
|
|
3128
|
+
: noOptionsText }))), !allowFreeText && allowAdd && Boolean(query.trim()) && (jsxs("button", { type: "button", onClick: () => handleAddAndSelect(query.trim()), className: "w-full flex items-center gap-2.5 p-3.5 rounded-2xl text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer", children: [jsx(SvgCirclePlus, { className: "size-5 text-blue-600 dark:text-blue-400" }), jsxs("span", { className: "text-sm font-medium", children: [addNewText, " \"", query.trim(), "\""] })] }))] }), multiple && (jsx("div", { className: "p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-900 shrink-0", children: jsxs(Button, { fullWidth: true, theme: "primary", size: "md", onClick: handleConfirmMultiSelect, "data-testid": "mobile-picker-confirm-button", children: [confirmText, ' ', Array.isArray(normalizedDraft) && normalizedDraft.length > 0
|
|
3129
|
+
? `(${normalizedDraft.length})`
|
|
3130
|
+
: ''] }) }))] }) })] })] }));
|
|
3131
|
+
}
|
|
3132
|
+
MobilePicker.displayName = 'MobilePicker';
|
|
3133
|
+
|
|
3134
|
+
function SingleWheelColumn({ column, itemHeight, height, disabled, onValueChange, }) {
|
|
3135
|
+
var _a;
|
|
3136
|
+
const containerRef = useRef(null);
|
|
3137
|
+
const [selectedValue, setSelectedValue] = useState(column.value !== undefined
|
|
3138
|
+
? column.value
|
|
3139
|
+
: column.defaultValue !== undefined
|
|
3140
|
+
? column.defaultValue
|
|
3141
|
+
: (_a = column.options[0]) === null || _a === void 0 ? void 0 : _a.value);
|
|
3142
|
+
const isControlled = column.value !== undefined;
|
|
3143
|
+
const currentValue = isControlled ? column.value : selectedValue;
|
|
3144
|
+
const selectedIndex = Math.max(0, column.options.findIndex((opt) => opt.value === currentValue));
|
|
3145
|
+
const paddingY = (height - itemHeight) / 2;
|
|
3146
|
+
// Sync scroll position when active value changes externally
|
|
3147
|
+
useEffect(() => {
|
|
3148
|
+
if (containerRef.current) {
|
|
3149
|
+
const targetScrollTop = selectedIndex * itemHeight;
|
|
3150
|
+
if (Math.abs(containerRef.current.scrollTop - targetScrollTop) > 2) {
|
|
3151
|
+
containerRef.current.scrollTop = targetScrollTop;
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
}, [selectedIndex, itemHeight]);
|
|
3155
|
+
const handleScroll = () => {
|
|
3156
|
+
var _a;
|
|
3157
|
+
if (!containerRef.current || disabled)
|
|
3158
|
+
return;
|
|
3159
|
+
const scrollTop = containerRef.current.scrollTop;
|
|
3160
|
+
const index = Math.round(scrollTop / itemHeight);
|
|
3161
|
+
const targetOption = column.options[index];
|
|
3162
|
+
if (targetOption && targetOption.value !== currentValue && !targetOption.disabled) {
|
|
3163
|
+
if (!isControlled) {
|
|
3164
|
+
setSelectedValue(targetOption.value);
|
|
3165
|
+
}
|
|
3166
|
+
(_a = column.onChange) === null || _a === void 0 ? void 0 : _a.call(column, targetOption.value);
|
|
3167
|
+
onValueChange(targetOption.value);
|
|
3168
|
+
}
|
|
3169
|
+
};
|
|
3170
|
+
return (jsx("div", { ref: containerRef, onScroll: handleScroll, className: buildClassName('flex-1 h-full overflow-y-auto no-scrollbar snap-y snap-mandatory relative z-10 select-none text-center', disabled && 'pointer-events-none opacity-40'), style: {
|
|
3171
|
+
paddingTop: `${paddingY}px`,
|
|
3172
|
+
paddingBottom: `${paddingY}px`,
|
|
3173
|
+
scrollSnapType: 'y mandatory',
|
|
3174
|
+
}, "data-testid": `wheel-column-${column.id}`, children: column.options.map((opt, index) => {
|
|
3175
|
+
const isSelected = opt.value === currentValue;
|
|
3176
|
+
return (jsx("div", { onClick: () => {
|
|
3177
|
+
if (disabled || opt.disabled || !containerRef.current)
|
|
3178
|
+
return;
|
|
3179
|
+
const targetTop = index * itemHeight;
|
|
3180
|
+
if (typeof containerRef.current.scrollTo === 'function') {
|
|
3181
|
+
containerRef.current.scrollTo({
|
|
3182
|
+
top: targetTop,
|
|
3183
|
+
behavior: 'smooth',
|
|
3184
|
+
});
|
|
3185
|
+
}
|
|
3186
|
+
else {
|
|
3187
|
+
containerRef.current.scrollTop = targetTop;
|
|
3188
|
+
}
|
|
3189
|
+
}, className: buildClassName('flex items-center justify-center font-semibold snap-center transition-all duration-150 cursor-pointer', opt.disabled && 'opacity-30 cursor-not-allowed', isSelected
|
|
3190
|
+
? 'text-blue-600 dark:text-blue-400 text-sm font-bold scale-105'
|
|
3191
|
+
: 'text-gray-500 dark:text-gray-400 text-xs hover:text-gray-800 dark:hover:text-gray-200'), style: { height: `${itemHeight}px` }, "data-testid": `wheel-item-${column.id}-${opt.value}`, children: opt.label }, `${opt.value}-${index}`));
|
|
3192
|
+
}) }));
|
|
3193
|
+
}
|
|
3194
|
+
function WheelPicker({ columns, height = 200, itemHeight = 40, onChange, disabled = false, containerClass = '', }) {
|
|
3195
|
+
const valuesRef = useRef({});
|
|
3196
|
+
const handleColumnChange = (columnId, value) => {
|
|
3197
|
+
valuesRef.current[columnId] = value;
|
|
3198
|
+
onChange === null || onChange === void 0 ? void 0 : onChange({ ...valuesRef.current });
|
|
3199
|
+
};
|
|
3200
|
+
const highlightTop = (height - itemHeight) / 2;
|
|
3201
|
+
return (jsxs("div", { className: buildClassName('w-full bg-white dark:bg-gray-900 border border-[var(--ui-border)] rounded-2xl relative overflow-hidden flex items-center shadow-xs select-none', containerClass), style: { height: `${height}px` }, "data-testid": "wheel-picker", children: [jsx("div", { className: "absolute inset-x-2 rounded-xl bg-gray-100/90 dark:bg-gray-800/90 border border-blue-500/20 dark:border-blue-400/20 z-0 pointer-events-none", style: {
|
|
3202
|
+
height: `${itemHeight}px`,
|
|
3203
|
+
top: `${highlightTop}px`,
|
|
3204
|
+
}, "data-testid": "wheel-highlight-window" }), jsx("div", { className: "absolute top-0 inset-x-0 bg-gradient-to-b from-white via-white/80 dark:from-gray-900 dark:via-gray-900/80 to-transparent pointer-events-none z-20", style: { height: `${highlightTop}px` } }), jsx("div", { className: "absolute bottom-0 inset-x-0 bg-gradient-to-t from-white via-white/80 dark:from-gray-900 dark:via-gray-900/80 to-transparent pointer-events-none z-20", style: { height: `${highlightTop}px` } }), jsx("div", { className: "w-full h-full flex items-center justify-around relative z-10 px-2", children: columns.map((col) => (jsx(SingleWheelColumn, { column: col, itemHeight: itemHeight, height: height, disabled: disabled, onValueChange: (val) => handleColumnChange(col.id, val) }, col.id))) })] }));
|
|
3205
|
+
}
|
|
3206
|
+
WheelPicker.displayName = 'WheelPicker';
|
|
3207
|
+
|
|
3208
|
+
function ChevronLeftIcon$1() {
|
|
3209
|
+
return (jsx("svg", { className: "size-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M15 19l-7-7 7-7" }) }));
|
|
3210
|
+
}
|
|
3211
|
+
function SearchIcon$1() {
|
|
3212
|
+
return (jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3213
|
+
}
|
|
3214
|
+
function ClearIcon() {
|
|
3215
|
+
return (jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }));
|
|
3216
|
+
}
|
|
3217
|
+
function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabel = 'Back', leading, actions, searchable = false, searchValue: externalSearchValue, onSearchChange, searchPlaceholder = 'Search...', sticky = true, transparent = false, bottomSlot, className = '', }) {
|
|
3218
|
+
const [isSearchActive, setIsSearchActive] = useState(false);
|
|
3219
|
+
const [internalSearchValue, setInternalSearchValue] = useState('');
|
|
3220
|
+
const searchValue = externalSearchValue !== undefined ? externalSearchValue : internalSearchValue;
|
|
3221
|
+
const handleSearchInput = (e) => {
|
|
3222
|
+
const val = e.target.value;
|
|
3223
|
+
setInternalSearchValue(val);
|
|
3224
|
+
onSearchChange === null || onSearchChange === void 0 ? void 0 : onSearchChange(val);
|
|
3225
|
+
};
|
|
3226
|
+
const handleClearSearch = () => {
|
|
3227
|
+
setInternalSearchValue('');
|
|
3228
|
+
onSearchChange === null || onSearchChange === void 0 ? void 0 : onSearchChange('');
|
|
3229
|
+
};
|
|
3230
|
+
return (jsxs("header", { className: buildClassName('w-full transition-colors select-none z-30', sticky && 'sticky top-0', transparent
|
|
3231
|
+
? 'bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b border-[var(--ui-border-muted)]'
|
|
3232
|
+
: 'bg-white dark:bg-gray-900 border-b border-[var(--ui-border)] shadow-xs', 'pt-[env(safe-area-inset-top,0px)]', className), "data-testid": "mobile-header", children: [jsx("div", { className: "h-14 px-3.5 flex items-center justify-between gap-3 relative", children: searchable && isSearchActive ? (jsxs("div", { className: "flex-1 flex items-center gap-2", "data-testid": "mobile-header-search-container", children: [jsxs("div", { className: "relative flex-1 flex items-center", children: [jsx("span", { className: "absolute left-3 pointer-events-none", children: jsx(SearchIcon$1, {}) }), jsx("input", { type: "text", value: searchValue, onChange: handleSearchInput, placeholder: searchPlaceholder, autoFocus: true, className: "w-full pl-9 pr-8 py-1.5 text-xs bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white rounded-full border border-transparent focus:border-blue-500 focus:outline-hidden transition-all", "data-testid": "mobile-header-search-input" }), searchValue && (jsx("button", { type: "button", onClick: handleClearSearch, "aria-label": "Clear search", className: "absolute right-2.5 p-0.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 cursor-pointer", children: jsx(ClearIcon, {}) }))] }), jsx("button", { type: "button", onClick: () => setIsSearchActive(false), className: "text-xs font-semibold text-blue-600 dark:text-blue-400 px-2 py-1.5 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-950/40 cursor-pointer", children: "Cancel" })] })) : (jsxs(Fragment, { children: [jsx("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 z-10", children: onBack ? (jsxs("button", { type: "button", onClick: onBack, "aria-label": backLabel, className: "flex items-center gap-0.5 text-blue-600 dark:text-blue-400 hover:text-blue-700 p-1 -ml-1 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-back-btn", children: [jsx(ChevronLeftIcon$1, {}), jsx("span", { className: "text-xs font-semibold hidden sm:inline", children: backLabel })] })) : (leading) }), jsxs("div", { className: buildClassName('flex-1 min-w-0 px-2', titleAlign === 'center'
|
|
3233
|
+
? 'absolute inset-x-12 text-center pointer-events-none flex flex-col items-center justify-center'
|
|
3234
|
+
: 'text-left'), children: [title && (jsx("div", { className: "text-sm font-bold text-gray-900 dark:text-white truncate pointer-events-auto", "data-testid": "mobile-header-title", children: title })), subtitle && (jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (jsx("button", { type: "button", onClick: () => setIsSearchActive(true), "aria-label": "Search", className: "p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors cursor-pointer", "data-testid": "mobile-header-search-toggle", children: jsx(SearchIcon$1, {}) })), actions === null || actions === void 0 ? void 0 : actions.map((action) => {
|
|
3235
|
+
const badgeColor = {
|
|
3236
|
+
danger: 'bg-red-500 text-white',
|
|
3237
|
+
info: 'bg-blue-500 text-white',
|
|
3238
|
+
success: 'bg-emerald-500 text-white',
|
|
3239
|
+
}[action.badgeVariant || 'danger'];
|
|
3240
|
+
return (jsxs("button", { type: "button", disabled: action.disabled, onClick: action.onClick, "aria-label": action.label, className: buildClassName('p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors relative cursor-pointer', action.disabled && 'opacity-40 cursor-not-allowed pointer-events-none'), "data-testid": `mobile-header-action-${action.id}`, children: [jsx("span", { className: "text-base", children: action.icon }), action.badge !== undefined && action.badge !== null && (jsx("span", { className: buildClassName('absolute top-1 right-1 min-w-[14px] h-3.5 px-0.5 rounded-full text-[9px] font-bold flex items-center justify-center shadow-xs', badgeColor), "data-testid": `mobile-header-badge-${action.id}`, children: action.badge }))] }, action.id));
|
|
3241
|
+
})] })] })) }), bottomSlot && (jsx("div", { className: "px-3 py-2 border-t border-[var(--ui-border-muted)]", "data-testid": "mobile-header-bottom-slot", children: bottomSlot }))] }));
|
|
3242
|
+
}
|
|
3243
|
+
MobileHeader.displayName = 'MobileHeader';
|
|
3244
|
+
|
|
3245
|
+
function ChevronLeftIcon() {
|
|
3246
|
+
return (jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M15 19l-7-7 7-7" }) }));
|
|
3247
|
+
}
|
|
3248
|
+
function ChevronRightIcon() {
|
|
3249
|
+
return (jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M9 5l7 7-7 7" }) }));
|
|
3250
|
+
}
|
|
3251
|
+
function MobileStepper({ steps, activeStep, variant = 'dots', onBack, onNext, backLabel = 'Back', nextLabel = 'Next', stepTitle, nextDisabled = false, backDisabled = false, nextLoading = false, className = '', }) {
|
|
3252
|
+
const isFirstStep = activeStep <= 0;
|
|
3253
|
+
const isLastStep = activeStep >= steps - 1;
|
|
3254
|
+
const progressPercent = Math.min(Math.max(((activeStep + 1) / steps) * 100, 0), 100);
|
|
3255
|
+
return (jsxs("div", { className: buildClassName('w-full flex flex-col gap-2 p-3 bg-white dark:bg-gray-900 border border-[var(--ui-border)] rounded-2xl shadow-xs select-none', className), "data-testid": "mobile-stepper", children: [stepTitle && (jsxs("div", { className: "flex items-center justify-between px-1", children: [jsx("span", { className: "text-xs font-bold text-gray-900 dark:text-white truncate", "data-testid": "mobile-stepper-title", children: stepTitle }), jsxs("span", { className: "text-[11px] font-medium text-gray-500 dark:text-gray-400 shrink-0 ml-2", children: [activeStep + 1, " / ", steps] })] })), jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsx(Button, { size: "xs", variant: "plain", theme: "secondary", disabled: disabledBack(isFirstStep, backDisabled), onClick: onBack, "aria-label": "Previous step", leftIcon: jsx(ChevronLeftIcon, {}), "data-testid": "mobile-stepper-back-btn", children: backLabel }), jsxs("div", { className: "flex items-center justify-center flex-1", "data-testid": "mobile-stepper-indicator", children: [variant === 'dots' && (jsx("div", { className: "flex items-center gap-1.5", "data-testid": "mobile-stepper-dots", children: Array.from({ length: steps }).map((_, index) => {
|
|
3256
|
+
const isActive = index === activeStep;
|
|
3257
|
+
const isCompleted = index < activeStep;
|
|
3258
|
+
return (jsx("span", { className: buildClassName('h-2 transition-all duration-300 rounded-full', isActive
|
|
3259
|
+
? 'w-5 bg-blue-600 dark:bg-blue-400'
|
|
3260
|
+
: isCompleted
|
|
3261
|
+
? 'w-2 bg-blue-300 dark:bg-blue-800'
|
|
3262
|
+
: 'w-2 bg-gray-200 dark:bg-gray-700'), "data-testid": `mobile-stepper-dot-${index}` }, index));
|
|
3263
|
+
}) })), variant === 'progress' && (jsx("div", { className: "w-full max-w-[140px] bg-gray-200 dark:bg-gray-700 h-2 rounded-full overflow-hidden", "data-testid": "mobile-stepper-progress", children: jsx("div", { className: "bg-blue-600 dark:bg-blue-400 h-full transition-all duration-300 rounded-full", style: { width: `${progressPercent}%` } }) })), variant === 'text' && (jsxs("div", { className: "text-xs font-semibold text-gray-600 dark:text-gray-300", "data-testid": "mobile-stepper-text", children: ["Step ", activeStep + 1, " of ", steps] }))] }), jsx(Button, { size: "xs", variant: "default", theme: "primary", disabled: nextDisabled, loading: nextLoading, onClick: onNext, "aria-label": "Next step", rightIcon: !isLastStep ? jsx(ChevronRightIcon, {}) : undefined, "data-testid": "mobile-stepper-next-btn", children: nextLabel })] })] }));
|
|
3264
|
+
}
|
|
3265
|
+
function disabledBack(isFirstStep, backDisabled) {
|
|
3266
|
+
return isFirstStep || backDisabled;
|
|
3267
|
+
}
|
|
3268
|
+
MobileStepper.displayName = 'MobileStepper';
|
|
3269
|
+
|
|
3270
|
+
const themeClasses = {
|
|
3271
|
+
danger: 'bg-red-600 text-white hover:bg-red-700 active:bg-red-800',
|
|
3272
|
+
primary: 'bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800',
|
|
3273
|
+
success: 'bg-emerald-600 text-white hover:bg-emerald-700 active:bg-emerald-800',
|
|
3274
|
+
warning: 'bg-amber-500 text-white hover:bg-amber-600 active:bg-amber-700',
|
|
3275
|
+
info: 'bg-cyan-600 text-white hover:bg-cyan-700 active:bg-cyan-800',
|
|
3276
|
+
secondary: 'bg-gray-600 text-white hover:bg-gray-700 active:bg-gray-800',
|
|
3277
|
+
gray: 'bg-gray-500 text-white hover:bg-gray-600 active:bg-gray-700',
|
|
3278
|
+
};
|
|
3279
|
+
const SwipeableRow = ({ children, leftActions = [], rightActions = [], actionWidth = 76, threshold = 40, fullSwipeToExecute = false, fullSwipeThreshold = 180, disabled = false, className = '', contentClassName = '', onOpen, onClose, }) => {
|
|
3280
|
+
const [offset, setOffset] = useState(0);
|
|
3281
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
3282
|
+
const containerRef = useRef(null);
|
|
3283
|
+
const startXRef = useRef(0);
|
|
3284
|
+
const startYRef = useRef(0);
|
|
3285
|
+
const initialOffsetRef = useRef(0);
|
|
3286
|
+
const isHorizontalSwipeRef = useRef(null);
|
|
3287
|
+
const maxLeftWidth = useMemo(() => leftActions.length * actionWidth, [leftActions, actionWidth]);
|
|
3288
|
+
const maxRightWidth = useMemo(() => rightActions.length * actionWidth, [rightActions, actionWidth]);
|
|
3289
|
+
const handleClose = useCallback(() => {
|
|
3290
|
+
setOffset(0);
|
|
3291
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
3292
|
+
}, [onClose]);
|
|
3293
|
+
const handleOpenLeft = useCallback(() => {
|
|
3294
|
+
if (maxLeftWidth > 0) {
|
|
3295
|
+
setOffset(maxLeftWidth);
|
|
3296
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen('left');
|
|
3297
|
+
}
|
|
3298
|
+
else {
|
|
3299
|
+
handleClose();
|
|
3300
|
+
}
|
|
3301
|
+
}, [maxLeftWidth, onOpen, handleClose]);
|
|
3302
|
+
const handleOpenRight = useCallback(() => {
|
|
3303
|
+
if (maxRightWidth > 0) {
|
|
3304
|
+
setOffset(-maxRightWidth);
|
|
3305
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen('right');
|
|
3306
|
+
}
|
|
3307
|
+
else {
|
|
3308
|
+
handleClose();
|
|
3309
|
+
}
|
|
3310
|
+
}, [maxRightWidth, onOpen, handleClose]);
|
|
3311
|
+
const handleDragStart = (clientX, clientY) => {
|
|
3312
|
+
if (disabled)
|
|
1968
3313
|
return;
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
3314
|
+
setIsDragging(true);
|
|
3315
|
+
startXRef.current = clientX;
|
|
3316
|
+
startYRef.current = clientY;
|
|
3317
|
+
initialOffsetRef.current = offset;
|
|
3318
|
+
isHorizontalSwipeRef.current = null;
|
|
3319
|
+
};
|
|
3320
|
+
const handleDragMove = (clientX, clientY) => {
|
|
3321
|
+
if (!isDragging || disabled)
|
|
1977
3322
|
return;
|
|
3323
|
+
const deltaX = clientX - startXRef.current;
|
|
3324
|
+
const deltaY = clientY - startYRef.current;
|
|
3325
|
+
// Lock direction once initial movement surpasses 5px
|
|
3326
|
+
if (isHorizontalSwipeRef.current === null) {
|
|
3327
|
+
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
|
3328
|
+
isHorizontalSwipeRef.current = Math.abs(deltaX) > Math.abs(deltaY);
|
|
3329
|
+
}
|
|
1978
3330
|
}
|
|
1979
|
-
if (
|
|
1980
|
-
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
3331
|
+
if (isHorizontalSwipeRef.current === false) {
|
|
1981
3332
|
return;
|
|
1982
3333
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
if (
|
|
1986
|
-
|
|
3334
|
+
let nextOffset = initialOffsetRef.current + deltaX;
|
|
3335
|
+
// Limit drag range with resistance overscroll
|
|
3336
|
+
if (nextOffset > 0) {
|
|
3337
|
+
if (!leftActions.length) {
|
|
3338
|
+
nextOffset = 0;
|
|
3339
|
+
}
|
|
3340
|
+
else if (nextOffset > maxLeftWidth && !fullSwipeToExecute) {
|
|
3341
|
+
const overflow = nextOffset - maxLeftWidth;
|
|
3342
|
+
nextOffset = maxLeftWidth + overflow * 0.2;
|
|
3343
|
+
}
|
|
1987
3344
|
}
|
|
1988
|
-
else {
|
|
1989
|
-
|
|
3345
|
+
else if (nextOffset < 0) {
|
|
3346
|
+
if (!rightActions.length) {
|
|
3347
|
+
nextOffset = 0;
|
|
3348
|
+
}
|
|
3349
|
+
else if (Math.abs(nextOffset) > maxRightWidth && !fullSwipeToExecute) {
|
|
3350
|
+
const overflow = Math.abs(nextOffset) - maxRightWidth;
|
|
3351
|
+
nextOffset = -(maxRightWidth + overflow * 0.2);
|
|
3352
|
+
}
|
|
1990
3353
|
}
|
|
3354
|
+
setOffset(nextOffset);
|
|
1991
3355
|
};
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
let delta = 0;
|
|
1995
|
-
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown')
|
|
1996
|
-
delta = -step;
|
|
1997
|
-
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp')
|
|
1998
|
-
delta = step;
|
|
1999
|
-
else if (e.key === 'Home') {
|
|
2000
|
-
if (thumb === 'min')
|
|
2001
|
-
onChange(min, valueMax);
|
|
2002
|
-
else
|
|
2003
|
-
onChange(valueMin, valueMin + step);
|
|
3356
|
+
const handleDragEnd = () => {
|
|
3357
|
+
if (!isDragging)
|
|
2004
3358
|
return;
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
if (thumb === 'min')
|
|
2008
|
-
onChange(valueMax - step, valueMax);
|
|
2009
|
-
else
|
|
2010
|
-
onChange(valueMin, max);
|
|
3359
|
+
setIsDragging(false);
|
|
3360
|
+
if (isHorizontalSwipeRef.current === false) {
|
|
2011
3361
|
return;
|
|
2012
3362
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
if (
|
|
2016
|
-
|
|
2017
|
-
|
|
3363
|
+
// Check full swipe auto-execution
|
|
3364
|
+
if (fullSwipeToExecute) {
|
|
3365
|
+
if (offset > fullSwipeThreshold && leftActions.length > 0) {
|
|
3366
|
+
leftActions[0].onClick();
|
|
3367
|
+
handleClose();
|
|
3368
|
+
return;
|
|
3369
|
+
}
|
|
3370
|
+
if (offset < -fullSwipeThreshold && rightActions.length > 0) {
|
|
3371
|
+
rightActions[0].onClick();
|
|
3372
|
+
handleClose();
|
|
3373
|
+
return;
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
// Snap logic
|
|
3377
|
+
if (offset > 0) {
|
|
3378
|
+
if (offset > threshold) {
|
|
3379
|
+
handleOpenLeft();
|
|
2018
3380
|
}
|
|
2019
3381
|
else {
|
|
2020
|
-
|
|
2021
|
-
|
|
3382
|
+
handleClose();
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
else if (offset < 0) {
|
|
3386
|
+
if (Math.abs(offset) > threshold) {
|
|
3387
|
+
handleOpenRight();
|
|
3388
|
+
}
|
|
3389
|
+
else {
|
|
3390
|
+
handleClose();
|
|
2022
3391
|
}
|
|
2023
3392
|
}
|
|
2024
3393
|
};
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
3394
|
+
// Touch Handlers
|
|
3395
|
+
const handleTouchStart = (e) => {
|
|
3396
|
+
const touch = e.touches[0];
|
|
3397
|
+
handleDragStart(touch.clientX, touch.clientY);
|
|
3398
|
+
};
|
|
3399
|
+
const handleTouchMove = (e) => {
|
|
3400
|
+
const touch = e.touches[0];
|
|
3401
|
+
handleDragMove(touch.clientX, touch.clientY);
|
|
3402
|
+
};
|
|
3403
|
+
const handleTouchEnd = () => {
|
|
3404
|
+
handleDragEnd();
|
|
3405
|
+
};
|
|
3406
|
+
// Pointer/Mouse Handlers
|
|
3407
|
+
const handlePointerDown = (e) => {
|
|
3408
|
+
if (e.pointerType === 'mouse' && e.button !== 0)
|
|
3409
|
+
return;
|
|
3410
|
+
handleDragStart(e.clientX, e.clientY);
|
|
3411
|
+
};
|
|
3412
|
+
const handlePointerMove = (e) => {
|
|
3413
|
+
if (!isDragging)
|
|
3414
|
+
return;
|
|
3415
|
+
handleDragMove(e.clientX, e.clientY);
|
|
3416
|
+
};
|
|
3417
|
+
const handlePointerUp = () => {
|
|
3418
|
+
handleDragEnd();
|
|
3419
|
+
};
|
|
3420
|
+
// Close row on click outside if swiped open
|
|
2048
3421
|
useEffect(() => {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
3422
|
+
if (offset === 0)
|
|
3423
|
+
return;
|
|
3424
|
+
const handleClickOutside = (e) => {
|
|
3425
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
3426
|
+
handleClose();
|
|
3427
|
+
}
|
|
3428
|
+
};
|
|
3429
|
+
document.addEventListener('click', handleClickOutside);
|
|
2053
3430
|
return () => {
|
|
2054
|
-
|
|
3431
|
+
document.removeEventListener('click', handleClickOutside);
|
|
2055
3432
|
};
|
|
2056
|
-
}, [
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
};
|
|
2069
|
-
|
|
2070
|
-
var _path$1;
|
|
2071
|
-
function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
|
|
2072
|
-
var SvgCheck = function SvgCheck(props) {
|
|
2073
|
-
return /*#__PURE__*/React.createElement("svg", _extends$1({
|
|
2074
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2075
|
-
width: 24,
|
|
2076
|
-
height: 24,
|
|
2077
|
-
fill: "none",
|
|
2078
|
-
stroke: "currentColor",
|
|
2079
|
-
strokeLinecap: "round",
|
|
2080
|
-
strokeLinejoin: "round",
|
|
2081
|
-
strokeWidth: 2,
|
|
2082
|
-
className: "lucide lucide-check-icon lucide-check",
|
|
2083
|
-
viewBox: "0 0 24 24"
|
|
2084
|
-
}, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
|
|
2085
|
-
d: "M20 6 9 17l-5-5"
|
|
2086
|
-
})));
|
|
3433
|
+
}, [offset, handleClose]);
|
|
3434
|
+
const renderActionButton = (action) => {
|
|
3435
|
+
const themeStyle = themeClasses[action.theme || 'primary'];
|
|
3436
|
+
return (jsxs("button", { type: "button", style: { width: `${actionWidth}px` }, onClick: (e) => {
|
|
3437
|
+
e.stopPropagation();
|
|
3438
|
+
action.onClick();
|
|
3439
|
+
handleClose();
|
|
3440
|
+
}, className: buildClassName('h-full flex flex-col items-center justify-center gap-1 text-xs font-semibold shrink-0 cursor-pointer transition-colors px-2 select-none', themeStyle, action.className), "data-testid": `swipe-action-${action.id}`, children: [action.icon && jsx("span", { className: "shrink-0", children: action.icon }), action.label && jsx("span", { className: "truncate max-w-full", children: action.label })] }, action.id));
|
|
3441
|
+
};
|
|
3442
|
+
return (jsxs("div", { ref: containerRef, className: buildClassName('relative overflow-hidden rounded-xl border border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 select-none touch-pan-y', className), "data-testid": "swipeable-row", children: [leftActions.length > 0 && (jsx("div", { className: "absolute left-0 top-0 bottom-0 flex items-center h-full z-0", style: { width: `${maxLeftWidth}px` }, "data-testid": "swipe-left-actions", children: leftActions.map(renderActionButton) })), rightActions.length > 0 && (jsx("div", { className: "absolute right-0 top-0 bottom-0 flex items-center justify-end h-full z-0", style: { width: `${maxRightWidth}px` }, "data-testid": "swipe-right-actions", children: rightActions.map(renderActionButton) })), jsx("div", { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onPointerCancel: handlePointerUp, style: {
|
|
3443
|
+
transform: `translateX(${offset}px)`,
|
|
3444
|
+
transition: isDragging ? 'none' : 'transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1)',
|
|
3445
|
+
}, className: buildClassName('relative z-10 w-full bg-white dark:bg-gray-800 shadow-xs cursor-grab active:cursor-grabbing', contentClassName), "data-testid": "swipeable-row-content", children: children })] }));
|
|
2087
3446
|
};
|
|
3447
|
+
SwipeableRow.displayName = 'SwipeableRow';
|
|
2088
3448
|
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
fill: "none",
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
strokeLinejoin: "round",
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
d: "M8 12h8M12 8v8"
|
|
2109
|
-
})));
|
|
3449
|
+
function SearchIcon() {
|
|
3450
|
+
return (jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3451
|
+
}
|
|
3452
|
+
function FilterIcon() {
|
|
3453
|
+
return (jsx("svg", { className: "size-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" }) }));
|
|
3454
|
+
}
|
|
3455
|
+
function SortIcon() {
|
|
3456
|
+
return (jsx("svg", { className: "size-3.5 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) }));
|
|
3457
|
+
}
|
|
3458
|
+
function CheckIcon() {
|
|
3459
|
+
return (jsx("svg", { className: "size-4 text-blue-600 dark:text-blue-400 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M5 13l4 4L19 7" }) }));
|
|
3460
|
+
}
|
|
3461
|
+
const parseNumericValue = (val) => {
|
|
3462
|
+
if (typeof val === 'number')
|
|
3463
|
+
return val;
|
|
3464
|
+
if (val === null || val === undefined)
|
|
3465
|
+
return NaN;
|
|
3466
|
+
const cleaned = String(val).replace(/[^0-9.-]/g, '');
|
|
3467
|
+
return cleaned !== '' ? Number(cleaned) : NaN;
|
|
2110
3468
|
};
|
|
3469
|
+
function DataList({ items, columns, renderItem, searchable = false, searchQuery: externalSearchQuery, onSearchChange, searchFields, filterFields, selectedFilters: externalFilters, onFilterChange, sorting: externalSorting, onSortChange, swipeableActions, rowKey = 'id', selectable = false, selectedKeys = [], onSelectionChange, onItemClick, loading = false, emptyMessage = 'No items found', pagination, setPagination, containerClass = '', itemClass = '', }) {
|
|
3470
|
+
// Internal Search State
|
|
3471
|
+
const [internalSearchQuery, setInternalSearchQuery] = useState('');
|
|
3472
|
+
const searchQuery = externalSearchQuery !== undefined ? externalSearchQuery : internalSearchQuery;
|
|
3473
|
+
const handleSearchInput = (query) => {
|
|
3474
|
+
onSearchChange ? onSearchChange(query) : setInternalSearchQuery(query);
|
|
3475
|
+
};
|
|
3476
|
+
// Internal Filter State
|
|
3477
|
+
const [internalFilters, setInternalFilters] = useState({});
|
|
3478
|
+
const selectedFilters = externalFilters !== undefined ? externalFilters : internalFilters;
|
|
3479
|
+
// Mobile Bottom Sheet Filter Drawer State
|
|
3480
|
+
const [isFilterSheetOpen, setIsFilterSheetOpen] = useState(false);
|
|
3481
|
+
const [draftFilters, setDraftFilters] = useState({});
|
|
3482
|
+
// Mobile Bottom Sheet Sort Drawer State
|
|
3483
|
+
const [isSortSheetOpen, setIsSortSheetOpen] = useState(false);
|
|
3484
|
+
// Active Filter Count Calculation
|
|
3485
|
+
const activeFilterCount = useMemo(() => {
|
|
3486
|
+
let count = 0;
|
|
3487
|
+
Object.values(selectedFilters).forEach((val) => {
|
|
3488
|
+
if (Array.isArray(val)) {
|
|
3489
|
+
count += val.length;
|
|
3490
|
+
}
|
|
3491
|
+
else if (val !== '' && val !== null && val !== undefined && val !== 'all') {
|
|
3492
|
+
count += 1;
|
|
3493
|
+
}
|
|
3494
|
+
});
|
|
3495
|
+
return count;
|
|
3496
|
+
}, [selectedFilters]);
|
|
3497
|
+
// Internal Sort State
|
|
3498
|
+
const [internalSort, setInternalSort] = useState(() => {
|
|
3499
|
+
if (externalSorting && Object.keys(externalSorting).length > 0) {
|
|
3500
|
+
const field = Object.keys(externalSorting)[0];
|
|
3501
|
+
return { field, dir: externalSorting[field] };
|
|
3502
|
+
}
|
|
3503
|
+
return null;
|
|
3504
|
+
});
|
|
3505
|
+
React__default.useEffect(() => {
|
|
3506
|
+
if (externalSorting !== undefined) {
|
|
3507
|
+
if (Object.keys(externalSorting).length > 0) {
|
|
3508
|
+
const field = Object.keys(externalSorting)[0];
|
|
3509
|
+
setInternalSort({ field, dir: externalSorting[field] });
|
|
3510
|
+
}
|
|
3511
|
+
else {
|
|
3512
|
+
setInternalSort(null);
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
}, [externalSorting]);
|
|
3516
|
+
const activeSort = internalSort;
|
|
3517
|
+
const sortableColumns = useMemo(() => (columns === null || columns === void 0 ? void 0 : columns.filter((c) => c.sortable)) || [], [columns]);
|
|
3518
|
+
const sortOptions = useMemo(() => {
|
|
3519
|
+
const opts = [{ label: 'Default Order', value: '' }];
|
|
3520
|
+
sortableColumns.forEach((col) => {
|
|
3521
|
+
const isNum = col.type === 'number';
|
|
3522
|
+
const isDate = col.type === 'date';
|
|
3523
|
+
const lowHigh = isNum
|
|
3524
|
+
? `${col.label} (Low to High)`
|
|
3525
|
+
: isDate
|
|
3526
|
+
? `${col.label} (Oldest First)`
|
|
3527
|
+
: `${col.label} (A to Z)`;
|
|
3528
|
+
const highLow = isNum
|
|
3529
|
+
? `${col.label} (High to Low)`
|
|
3530
|
+
: isDate
|
|
3531
|
+
? `${col.label} (Newest First)`
|
|
3532
|
+
: `${col.label} (Z to A)`;
|
|
3533
|
+
opts.push({ label: lowHigh, value: `${col.name}:asc` });
|
|
3534
|
+
opts.push({ label: highLow, value: `${col.name}:desc` });
|
|
3535
|
+
});
|
|
3536
|
+
return opts;
|
|
3537
|
+
}, [sortableColumns]);
|
|
3538
|
+
const handleSortSelect = (val) => {
|
|
3539
|
+
if (!val) {
|
|
3540
|
+
setInternalSort(null);
|
|
3541
|
+
onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange({});
|
|
3542
|
+
return;
|
|
3543
|
+
}
|
|
3544
|
+
const [field, dir] = val.split(':');
|
|
3545
|
+
const sortObj = { [field]: dir };
|
|
3546
|
+
setInternalSort({ field, dir: dir });
|
|
3547
|
+
onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange(sortObj);
|
|
3548
|
+
};
|
|
3549
|
+
const activeSortLabel = useMemo(() => {
|
|
3550
|
+
if (!activeSort)
|
|
3551
|
+
return 'Sort';
|
|
3552
|
+
const currVal = `${activeSort.field}:${activeSort.dir}`;
|
|
3553
|
+
const match = sortOptions.find((o) => o.value === currVal);
|
|
3554
|
+
if (!match || !match.value)
|
|
3555
|
+
return 'Sort';
|
|
3556
|
+
return `Sort: ${match.label}`;
|
|
3557
|
+
}, [activeSort, sortOptions]);
|
|
3558
|
+
// Processed Items (Filter + Search + Sort)
|
|
3559
|
+
const processedItems = useMemo(() => {
|
|
3560
|
+
let result = [...items];
|
|
3561
|
+
// 1. Apply Search
|
|
3562
|
+
if (searchQuery.trim()) {
|
|
3563
|
+
const q = searchQuery.toLowerCase().trim();
|
|
3564
|
+
const fieldsToSearch = searchFields || (columns === null || columns === void 0 ? void 0 : columns.map((c) => c.name)) || ['id', 'name', 'title'];
|
|
3565
|
+
result = result.filter((item) => fieldsToSearch.some((field) => {
|
|
3566
|
+
const val = get(item, field);
|
|
3567
|
+
return val !== null && val !== undefined && String(val).toLowerCase().includes(q);
|
|
3568
|
+
}));
|
|
3569
|
+
}
|
|
3570
|
+
// 2. Apply Filters (supporting array checkboxes or single values)
|
|
3571
|
+
const filterKeys = Object.keys(selectedFilters);
|
|
3572
|
+
if (filterKeys.length > 0) {
|
|
3573
|
+
result = result.filter((item) => filterKeys.every((key) => {
|
|
3574
|
+
const filterVal = selectedFilters[key];
|
|
3575
|
+
if (filterVal === undefined || filterVal === null || filterVal === '')
|
|
3576
|
+
return true;
|
|
3577
|
+
const actual = String(get(item, key));
|
|
3578
|
+
if (Array.isArray(filterVal)) {
|
|
3579
|
+
if (filterVal.length === 0)
|
|
3580
|
+
return true;
|
|
3581
|
+
return filterVal.map(String).includes(actual);
|
|
3582
|
+
}
|
|
3583
|
+
return actual === String(filterVal);
|
|
3584
|
+
}));
|
|
3585
|
+
}
|
|
3586
|
+
// 3. Apply Auto Sorting
|
|
3587
|
+
if (activeSort) {
|
|
3588
|
+
const { field, dir } = activeSort;
|
|
3589
|
+
const colDef = columns === null || columns === void 0 ? void 0 : columns.find((c) => c.name === field);
|
|
3590
|
+
const isAsc = dir === 'asc' || dir === '1';
|
|
3591
|
+
result.sort((a, b) => {
|
|
3592
|
+
const valA = get(a, field);
|
|
3593
|
+
const valB = get(b, field);
|
|
3594
|
+
const numA = parseNumericValue(valA);
|
|
3595
|
+
const numB = parseNumericValue(valB);
|
|
3596
|
+
if ((colDef === null || colDef === void 0 ? void 0 : colDef.type) === 'number' || (!isNaN(numA) && !isNaN(numB))) {
|
|
3597
|
+
return isAsc ? numA - numB : numB - numA;
|
|
3598
|
+
}
|
|
3599
|
+
if ((colDef === null || colDef === void 0 ? void 0 : colDef.type) === 'date') {
|
|
3600
|
+
const dA = new Date(valA).getTime();
|
|
3601
|
+
const dB = new Date(valB).getTime();
|
|
3602
|
+
if (!isNaN(dA) && !isNaN(dB)) {
|
|
3603
|
+
return isAsc ? dA - dB : dB - dA;
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
const strA = String(valA !== null && valA !== void 0 ? valA : '');
|
|
3607
|
+
const strB = String(valB !== null && valB !== void 0 ? valB : '');
|
|
3608
|
+
return isAsc
|
|
3609
|
+
? strA.localeCompare(strB, undefined, { numeric: true })
|
|
3610
|
+
: strB.localeCompare(strA, undefined, { numeric: true });
|
|
3611
|
+
});
|
|
3612
|
+
}
|
|
3613
|
+
return result;
|
|
3614
|
+
}, [items, searchQuery, searchFields, columns, selectedFilters, activeSort]);
|
|
3615
|
+
// Draft Filters Matching Count
|
|
3616
|
+
const draftMatchingCount = useMemo(() => {
|
|
3617
|
+
let result = [...items];
|
|
3618
|
+
const filterKeys = Object.keys(draftFilters);
|
|
3619
|
+
if (filterKeys.length > 0) {
|
|
3620
|
+
result = result.filter((item) => filterKeys.every((key) => {
|
|
3621
|
+
const filterVal = draftFilters[key];
|
|
3622
|
+
if (filterVal === undefined || filterVal === null || filterVal === '')
|
|
3623
|
+
return true;
|
|
3624
|
+
const actual = String(get(item, key));
|
|
3625
|
+
if (Array.isArray(filterVal)) {
|
|
3626
|
+
if (filterVal.length === 0)
|
|
3627
|
+
return true;
|
|
3628
|
+
return filterVal.map(String).includes(actual);
|
|
3629
|
+
}
|
|
3630
|
+
return actual === String(filterVal);
|
|
3631
|
+
}));
|
|
3632
|
+
}
|
|
3633
|
+
return result.length;
|
|
3634
|
+
}, [items, draftFilters]);
|
|
3635
|
+
const getKey = (item, idx) => {
|
|
3636
|
+
var _a;
|
|
3637
|
+
if (typeof rowKey === 'function')
|
|
3638
|
+
return rowKey(item);
|
|
3639
|
+
return (_a = item[rowKey]) !== null && _a !== void 0 ? _a : idx;
|
|
3640
|
+
};
|
|
3641
|
+
const isSelected = (key) => selectedKeys.includes(key);
|
|
3642
|
+
const toggleSelectAll = () => {
|
|
3643
|
+
if (selectedKeys.length === processedItems.length) {
|
|
3644
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([], []);
|
|
3645
|
+
}
|
|
3646
|
+
else {
|
|
3647
|
+
const allKeys = processedItems.map(getKey);
|
|
3648
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(allKeys, processedItems);
|
|
3649
|
+
}
|
|
3650
|
+
};
|
|
3651
|
+
const toggleItemSelect = (key, item) => {
|
|
3652
|
+
const nextKeys = isSelected(key)
|
|
3653
|
+
? selectedKeys.filter((k) => k !== key)
|
|
3654
|
+
: [...selectedKeys, key];
|
|
3655
|
+
const nextItems = processedItems.filter((it, idx) => nextKeys.includes(getKey(it, idx)));
|
|
3656
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(nextKeys, nextItems);
|
|
3657
|
+
};
|
|
3658
|
+
const getItemClassStr = (item, idx) => {
|
|
3659
|
+
if (typeof itemClass === 'function')
|
|
3660
|
+
return itemClass(item, idx);
|
|
3661
|
+
return itemClass;
|
|
3662
|
+
};
|
|
3663
|
+
return (jsxs("div", { className: buildClassName('w-full space-y-3', containerClass), "data-testid": "data-list", children: [(searchable || (filterFields && filterFields.length > 0) || sortableColumns.length > 0) && (jsxs("div", { className: "p-3 bg-gray-50 dark:bg-gray-800/80 rounded-xl border border-[var(--ui-border)] space-y-3", children: [searchable && (jsx(Input, { value: searchQuery, onChange: (e) => handleSearchInput(e.target.value), placeholder: "Search items...", leftGroup: jsx(SearchIcon, {}), clearable: true, onClear: () => handleSearchInput(''), className: "w-full text-xs", size: "sm" })), ((filterFields && filterFields.length > 0) || sortableColumns.length > 0) && (jsxs("div", { className: "flex items-center gap-2", children: [filterFields && filterFields.length > 0 && (jsxs(Button, { theme: "secondary", size: "sm", onClick: () => {
|
|
3664
|
+
setDraftFilters(selectedFilters);
|
|
3665
|
+
setIsFilterSheetOpen(true);
|
|
3666
|
+
}, className: "flex items-center gap-1.5 text-xs font-semibold flex-1 justify-center", "data-testid": "data-list-filter-btn", children: [jsx(FilterIcon, {}), jsx("span", { children: "Filters" }), activeFilterCount > 0 && (jsx("span", { className: "ml-1 size-4 rounded-full bg-blue-600 text-white text-[10px] font-bold flex items-center justify-center", children: activeFilterCount }))] })), sortableColumns.length > 0 && (jsxs(Button, { theme: "secondary", size: "sm", onClick: () => setIsSortSheetOpen(true), className: "flex items-center gap-1.5 text-xs font-semibold flex-1 justify-center", "data-testid": "data-list-sort-btn", children: [jsx(SortIcon, {}), jsx("span", { children: activeSortLabel })] }))] }))] })), filterFields && filterFields.length > 0 && (jsx(Drawer, { isOpen: isFilterSheetOpen, onClose: () => setIsFilterSheetOpen(false), align: "bottom", title: "Filter Items", dragHandle: true, panelClass: "max-h-[85vh] rounded-t-2xl", footer: jsxs("div", { className: "flex items-center gap-3 w-full", children: [jsx(Button, { theme: "secondary", size: "md", onClick: () => setDraftFilters({}), className: "flex-1 text-xs", children: "Clear All" }), jsxs(Button, { theme: "primary", size: "md", onClick: () => {
|
|
3667
|
+
onFilterChange ? onFilterChange(draftFilters) : setInternalFilters(draftFilters);
|
|
3668
|
+
setIsFilterSheetOpen(false);
|
|
3669
|
+
}, className: "flex-1 text-xs font-semibold", "data-testid": "data-list-apply-filters-btn", children: ["Apply Filters (", draftMatchingCount, ")"] })] }), footerSticky: true, children: jsx("div", { className: "space-y-6 py-2", children: filterFields.map((field) => {
|
|
3670
|
+
const selectedArray = Array.isArray(draftFilters[field.name])
|
|
3671
|
+
? draftFilters[field.name]
|
|
3672
|
+
: draftFilters[field.name] !== undefined && draftFilters[field.name] !== ''
|
|
3673
|
+
? [draftFilters[field.name]]
|
|
3674
|
+
: [];
|
|
3675
|
+
return (jsxs("div", { className: "space-y-2.5", children: [jsx("h4", { className: "text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400 px-1", children: field.label }), jsx("div", { className: "space-y-1.5 bg-gray-50 dark:bg-gray-800/60 p-2.5 rounded-xl border border-[var(--ui-border-muted)]", children: field.options.map((opt) => {
|
|
3676
|
+
const checked = selectedArray.includes(opt.value);
|
|
3677
|
+
return (jsxs("label", { className: "flex items-center justify-between p-2 rounded-lg hover:bg-white dark:hover:bg-gray-800 cursor-pointer transition-colors", children: [jsx("span", { className: "text-sm font-medium text-gray-800 dark:text-gray-200", children: opt.label }), jsx(Checkbox, { checked: checked, onChange: () => {
|
|
3678
|
+
const next = checked
|
|
3679
|
+
? selectedArray.filter((v) => v !== opt.value)
|
|
3680
|
+
: [...selectedArray, opt.value];
|
|
3681
|
+
setDraftFilters((prev) => ({
|
|
3682
|
+
...prev,
|
|
3683
|
+
[field.name]: next,
|
|
3684
|
+
}));
|
|
3685
|
+
} })] }, String(opt.value)));
|
|
3686
|
+
}) })] }, field.name));
|
|
3687
|
+
}) }) })), sortableColumns.length > 0 && (jsx(Drawer, { isOpen: isSortSheetOpen, onClose: () => setIsSortSheetOpen(false), align: "bottom", title: "Sort Items By", dragHandle: true, panelClass: "max-h-[70vh] rounded-t-2xl", children: jsx("div", { className: "space-y-1 py-2", children: sortOptions.map((opt) => {
|
|
3688
|
+
const isSelected = (activeSort ? `${activeSort.field}:${activeSort.dir}` : '') === opt.value;
|
|
3689
|
+
return (jsxs("button", { type: "button", onClick: () => {
|
|
3690
|
+
handleSortSelect(opt.value);
|
|
3691
|
+
setIsSortSheetOpen(false);
|
|
3692
|
+
}, className: buildClassName('w-full flex items-center justify-between p-3.5 rounded-xl text-left transition-colors cursor-pointer', isSelected
|
|
3693
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3694
|
+
: 'hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-200 font-medium'), "data-testid": `data-list-sort-opt-${opt.value || 'default'}`, children: [jsx("span", { className: "text-sm", children: opt.label }), isSelected && jsx(CheckIcon, {})] }, opt.value));
|
|
3695
|
+
}) }) })), selectable && processedItems.length > 0 && (jsxs("div", { className: "p-3 bg-gray-50 dark:bg-gray-800/80 rounded-xl border border-[var(--ui-border)] flex items-center justify-between text-xs", children: [jsxs("label", { className: "flex items-center gap-2 font-medium text-gray-700 dark:text-gray-300 cursor-pointer", children: [jsx(Checkbox, { checked: processedItems.length > 0 && selectedKeys.length === processedItems.length, onChange: toggleSelectAll }), jsx("span", { children: "Select All Items" })] }), jsxs("span", { className: "text-gray-400 font-semibold", children: [selectedKeys.length, " of ", processedItems.length] })] })), jsx("div", { className: "space-y-3", children: loading ? (jsx("div", { className: "p-8 text-center text-sm text-gray-500 bg-white dark:bg-gray-800 rounded-xl border border-[var(--ui-border)]", children: "Loading items..." })) : processedItems.length === 0 ? (jsx("div", { className: "p-8 text-center text-sm text-gray-500 bg-white dark:bg-gray-800 rounded-xl border border-[var(--ui-border)]", children: emptyMessage })) : (processedItems.map((item, idx) => {
|
|
3696
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3697
|
+
const key = getKey(item, idx);
|
|
3698
|
+
const selected = isSelected(key);
|
|
3699
|
+
const actions = swipeableActions === null || swipeableActions === void 0 ? void 0 : swipeableActions(item);
|
|
3700
|
+
const customClass = getItemClassStr(item, idx);
|
|
3701
|
+
const contentNode = renderItem ? (renderItem(item, idx)) : (jsxs("div", { onClick: () => onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick(item, idx), className: buildClassName('p-4 bg-white dark:bg-gray-800 rounded-xl border border-[var(--ui-border)] shadow-xs space-y-3 transition-colors', onItemClick && 'cursor-pointer hover:border-blue-500/50', selected && 'ring-2 ring-blue-500/50 bg-blue-50/20 dark:bg-blue-950/20', customClass), "data-testid": `data-list-item-${key}`, children: [jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-[var(--ui-border-muted)] pb-2.5", children: [jsx("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: selectable ? (jsx(Checkbox, { checked: selected, onChange: () => toggleItemSelect(key), "aria-label": `Select item ${key}`, label: jsx("span", { className: "font-bold text-sm text-gray-900 dark:text-white truncate block", children: columns && ((_a = columns[0]) === null || _a === void 0 ? void 0 : _a.render)
|
|
3702
|
+
? columns[0].render(item)
|
|
3703
|
+
: String((_d = get(item, (_c = (_b = columns === null || columns === void 0 ? void 0 : columns[0]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : 'title')) !== null && _d !== void 0 ? _d : '') }) })) : (jsx("div", { className: "font-bold text-sm text-gray-900 dark:text-white truncate", children: columns && ((_e = columns[0]) === null || _e === void 0 ? void 0 : _e.render)
|
|
3704
|
+
? columns[0].render(item)
|
|
3705
|
+
: String((_h = get(item, (_g = (_f = columns === null || columns === void 0 ? void 0 : columns[0]) === null || _f === void 0 ? void 0 : _f.name) !== null && _g !== void 0 ? _g : 'title')) !== null && _h !== void 0 ? _h : '') })) }), columns && columns[1] && (jsx("div", { className: "shrink-0 text-xs", children: columns[1].render
|
|
3706
|
+
? columns[1].render(item)
|
|
3707
|
+
: String((_j = get(item, columns[1].name)) !== null && _j !== void 0 ? _j : '') }))] }), columns && columns.length > 2 && (jsx("div", { className: "grid grid-cols-2 gap-2 text-xs pt-1", children: columns.slice(2).map((col) => {
|
|
3708
|
+
const val = col.render ? col.render(item) : get(item, col.name);
|
|
3709
|
+
if (val === null || val === undefined || val === '')
|
|
3710
|
+
return null;
|
|
3711
|
+
return (jsxs("div", { className: "min-w-0", children: [jsx("span", { className: "text-gray-400 dark:text-gray-500 font-medium block truncate", children: col.label }), jsx("span", { className: "text-gray-800 dark:text-gray-200 font-semibold block truncate mt-0.5", children: val })] }, String(col.name)));
|
|
3712
|
+
}) }))] }));
|
|
3713
|
+
if (actions && (((_k = actions.leftActions) === null || _k === void 0 ? void 0 : _k.length) || ((_l = actions.rightActions) === null || _l === void 0 ? void 0 : _l.length))) {
|
|
3714
|
+
return (jsx(SwipeableRow, { leftActions: actions.leftActions, rightActions: actions.rightActions, children: contentNode }, key));
|
|
3715
|
+
}
|
|
3716
|
+
return jsx("div", { children: contentNode }, key);
|
|
3717
|
+
})) }), pagination && pagination.total > 0 && (jsx("div", { className: "pt-2 flex justify-center", children: jsx(Pagination, { ...pagination, onChange: (newPag) => setPagination === null || setPagination === void 0 ? void 0 : setPagination(newPag) }) }))] }));
|
|
3718
|
+
}
|
|
3719
|
+
DataList.displayName = 'DataList';
|
|
2111
3720
|
|
|
2112
3721
|
const sizeClasses$1 = {
|
|
2113
3722
|
sm: {
|
|
2114
|
-
input: 'px-2.5 py-1 text-xs leading-5 min-h-[
|
|
3723
|
+
input: 'px-2.5 py-1.5 text-xs leading-5 min-h-[32px]',
|
|
2115
3724
|
group: 'w-8 text-xs',
|
|
2116
3725
|
icon: 'size-3.5',
|
|
2117
3726
|
badgeSize: 'sm',
|
|
@@ -2130,7 +3739,10 @@ const sizeClasses$1 = {
|
|
|
2130
3739
|
},
|
|
2131
3740
|
};
|
|
2132
3741
|
const SelectBox = forwardRef((props, forwardedRef) => {
|
|
2133
|
-
const { labelKey = 'label', valueKey = 'value', name, id = name, options = [], groups, selected, size = 'md', label = null, labelWrapperClass = '', labelClass = '', labelHint = null, disabled = false, containerClass = '', onChange = () => { }, placeholder, dropdownContainerClass = 'z-20', multiple = false, maxSelection, showSelectAll = false, immediate = true, showErrorMessage = true, error = null, helperText, leftGroup, renderOption, async = false, searchable = true, required = false, allowAdd = false, addNewText = 'Create', onAdd = () => { }, allowClear = false, modalDropdown = false, noOptionsText = 'No options available', } = props;
|
|
3742
|
+
const { labelKey = 'label', valueKey = 'value', name, id = name, options = [], groups, selected, size = 'md', label = null, labelWrapperClass = '', labelClass = '', labelHint = null, disabled = false, containerClass = '', onChange = () => { }, placeholder, dropdownContainerClass = 'z-20', multiple = false, maxSelection, showSelectAll = false, immediate = true, showErrorMessage = true, error = null, helperText, leftGroup, renderOption, async = false, searchable = true, required = false, allowAdd = false, addNewText = 'Create', onAdd = () => { }, allowClear = false, allowFreeText = false, modalDropdown = false, noOptionsText = 'No options available', } = props;
|
|
3743
|
+
if (props.asBottomSheet || props.mobileMode === 'sheet') {
|
|
3744
|
+
return jsx(MobilePicker, { ...props });
|
|
3745
|
+
}
|
|
2134
3746
|
const hasError = Boolean(error);
|
|
2135
3747
|
const [query, setQuery] = useState('');
|
|
2136
3748
|
const debouncedQuery = useDebounce(query, 500);
|
|
@@ -2178,6 +3790,49 @@ const SelectBox = forwardRef((props, forwardedRef) => {
|
|
|
2178
3790
|
const getValue = useCallback((opt) => {
|
|
2179
3791
|
return typeof opt === 'string' ? opt : opt[valueKey];
|
|
2180
3792
|
}, [valueKey]);
|
|
3793
|
+
const createFreeTextOption = useCallback((text) => {
|
|
3794
|
+
const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected);
|
|
3795
|
+
if (typeof sample === 'string' ||
|
|
3796
|
+
(!sample && typeof labelKey === 'string' && labelKey === 'label')) {
|
|
3797
|
+
return text;
|
|
3798
|
+
}
|
|
3799
|
+
return {
|
|
3800
|
+
[labelKey]: text,
|
|
3801
|
+
[valueKey]: text,
|
|
3802
|
+
};
|
|
3803
|
+
}, [allOptions, selected, labelKey, valueKey]);
|
|
3804
|
+
const handleFreeTextCommit = useCallback((queryText) => {
|
|
3805
|
+
const trimmed = queryText.trim();
|
|
3806
|
+
if (!trimmed)
|
|
3807
|
+
return;
|
|
3808
|
+
const existing = allOptions.find((opt) => {
|
|
3809
|
+
const display = getDisplayValue(opt);
|
|
3810
|
+
return (display === null || display === void 0 ? void 0 : display.toLowerCase()) === trimmed.toLowerCase();
|
|
3811
|
+
});
|
|
3812
|
+
const valueToCommit = existing || createFreeTextOption(trimmed);
|
|
3813
|
+
if (multiple) {
|
|
3814
|
+
const current = isArray(selected) ? selected : [];
|
|
3815
|
+
const alreadySelected = current.some((item) => { var _a; return ((_a = getDisplayValue(item)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === trimmed.toLowerCase(); });
|
|
3816
|
+
if (!alreadySelected) {
|
|
3817
|
+
if (maxSelection && current.length >= maxSelection)
|
|
3818
|
+
return;
|
|
3819
|
+
onChange([...current, valueToCommit]);
|
|
3820
|
+
}
|
|
3821
|
+
setQuery('');
|
|
3822
|
+
}
|
|
3823
|
+
else {
|
|
3824
|
+
onChange(valueToCommit);
|
|
3825
|
+
setQuery('');
|
|
3826
|
+
}
|
|
3827
|
+
}, [
|
|
3828
|
+
allOptions,
|
|
3829
|
+
getDisplayValue,
|
|
3830
|
+
createFreeTextOption,
|
|
3831
|
+
multiple,
|
|
3832
|
+
selected,
|
|
3833
|
+
maxSelection,
|
|
3834
|
+
onChange,
|
|
3835
|
+
]);
|
|
2181
3836
|
const removeSelection = (idx) => {
|
|
2182
3837
|
var _a;
|
|
2183
3838
|
if (!isArray(selected))
|
|
@@ -2250,11 +3905,25 @@ const SelectBox = forwardRef((props, forwardedRef) => {
|
|
|
2250
3905
|
if (async && debouncedQuery)
|
|
2251
3906
|
handleSearch(debouncedQuery);
|
|
2252
3907
|
}, [debouncedQuery, async, handleSearch]);
|
|
3908
|
+
const normalizedSelected = useMemo(() => {
|
|
3909
|
+
if (multiple) {
|
|
3910
|
+
if (Array.isArray(selected))
|
|
3911
|
+
return selected;
|
|
3912
|
+
if (selected !== null && selected !== undefined)
|
|
3913
|
+
return [selected];
|
|
3914
|
+
return [];
|
|
3915
|
+
}
|
|
3916
|
+
else {
|
|
3917
|
+
if (Array.isArray(selected))
|
|
3918
|
+
return selected.length > 0 ? selected[0] : null;
|
|
3919
|
+
return selected !== null && selected !== void 0 ? selected : null;
|
|
3920
|
+
}
|
|
3921
|
+
}, [multiple, selected]);
|
|
2253
3922
|
const isAllSelected = useMemo(() => {
|
|
2254
|
-
if (!multiple || !Array.isArray(
|
|
3923
|
+
if (!multiple || !Array.isArray(normalizedSelected) || !allOptions.length)
|
|
2255
3924
|
return false;
|
|
2256
|
-
return allOptions.length ===
|
|
2257
|
-
}, [multiple,
|
|
3925
|
+
return allOptions.length === normalizedSelected.length;
|
|
3926
|
+
}, [multiple, normalizedSelected, allOptions]);
|
|
2258
3927
|
const handleToggleSelectAll = () => {
|
|
2259
3928
|
if (isAllSelected) {
|
|
2260
3929
|
onChange([]);
|
|
@@ -2264,30 +3933,69 @@ const SelectBox = forwardRef((props, forwardedRef) => {
|
|
|
2264
3933
|
}
|
|
2265
3934
|
};
|
|
2266
3935
|
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
2267
|
-
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), ref: containerRef, children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs(Combobox, { multiple: multiple, immediate: immediate, name: name, value:
|
|
2268
|
-
(
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
3936
|
+
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), ref: containerRef, children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs(Combobox, { multiple: multiple, immediate: immediate, name: name, value: normalizedSelected, onChange: comboboxOnChangeWrapper, onClose: () => setQuery(''), disabled: disabled, by: (a, b) => (a && b ? getValue(a) === getValue(b) : a === b), children: [multiple ? (jsxs("div", { className: buildClassName(baseInputClass, 'flex flex-wrap gap-2 peer relative', hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : ''), ref: forwardedRef, children: [hasLeftGroup && (jsx("span", { className: buildClassName('absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500', currentSize.group), children: leftGroup })), isArray(normalizedSelected) &&
|
|
3937
|
+
(normalizedSelected === null || normalizedSelected === void 0 ? void 0 : normalizedSelected.length) > 0 &&
|
|
3938
|
+
normalizedSelected.map((option, idx) => (jsx(Badge, { theme: "secondary", size: currentSize.badgeSize, removable: !disabled, onRemove: () => removeSelection(idx), children: getDisplayValue(option) }, `${getValue(option)}-${idx}`))), jsx(ComboboxInput, { className: "outline-none flex-1 dark:placeholder-gray-400 placeholder-gray-400 bg-transparent", "aria-label": name, value: query, autoComplete: "off", placeholder: (normalizedSelected === null || normalizedSelected === void 0 ? void 0 : normalizedSelected.length) ? '' : placeholder, onChange: (e) => {
|
|
3939
|
+
const val = e.target.value;
|
|
3940
|
+
if (allowFreeText && multiple && val.includes(',')) {
|
|
3941
|
+
const parts = val.split(',');
|
|
3942
|
+
parts.forEach((p) => {
|
|
3943
|
+
if (p.trim())
|
|
3944
|
+
handleFreeTextCommit(p.trim());
|
|
3945
|
+
});
|
|
3946
|
+
setQuery('');
|
|
3947
|
+
}
|
|
3948
|
+
else {
|
|
3949
|
+
setQuery(val);
|
|
3950
|
+
}
|
|
3951
|
+
}, id: id, ref: inputRef, onKeyDown: (e) => {
|
|
3952
|
+
if (allowFreeText && (e.key === 'Enter' || e.key === ',') && query.trim()) {
|
|
3953
|
+
e.preventDefault();
|
|
3954
|
+
handleFreeTextCommit(query.replace(/,/g, ''));
|
|
3955
|
+
}
|
|
3956
|
+
else if (multiple && e.key === 'Backspace' && !query) {
|
|
3957
|
+
if (Array.isArray(normalizedSelected) && normalizedSelected.length > 0) {
|
|
3958
|
+
removeSelection(normalizedSelected.length - 1);
|
|
2273
3959
|
}
|
|
2274
3960
|
}
|
|
2275
|
-
},
|
|
3961
|
+
}, onBlur: () => {
|
|
3962
|
+
if (allowFreeText && query.trim()) {
|
|
3963
|
+
handleFreeTextCommit(query.replace(/,/g, ''));
|
|
3964
|
+
}
|
|
3965
|
+
}, "data-testid": "combobox-input" }), jsx(ComboboxButton, { className: "group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center", "data-testid": "combobox-button", children: jsx(SvgChevronDown, { className: chevronIconClass }) })] })) : (jsxs("div", { className: "relative", ref: forwardedRef, children: [hasLeftGroup && (jsx("span", { className: buildClassName('absolute left-0 top-0 h-full flex items-center justify-center text-gray-400 dark:text-gray-500 z-10', currentSize.group), children: leftGroup })), jsx(ComboboxInput, { "aria-label": name, displayValue: (option) => (option ? getDisplayValue(option) : null), autoComplete: "off", placeholder: placeholder, onChange: (event) => setQuery(event.target.value), onKeyDown: (e) => {
|
|
3966
|
+
if (allowFreeText && e.key === 'Enter' && query.trim()) {
|
|
3967
|
+
e.preventDefault();
|
|
3968
|
+
handleFreeTextCommit(query);
|
|
3969
|
+
}
|
|
3970
|
+
}, onBlur: () => {
|
|
3971
|
+
if (allowFreeText && query.trim()) {
|
|
3972
|
+
handleFreeTextCommit(query);
|
|
3973
|
+
}
|
|
3974
|
+
}, onFocus: () => {
|
|
3975
|
+
setQuery('');
|
|
3976
|
+
}, className: buildClassName(baseInputClass, hasLeftGroup ? (size === 'lg' ? 'ps-12' : size === 'sm' ? 'ps-8' : 'ps-10') : ''), disabled: disabled, id: id, readOnly: !searchable, ref: inputRef, "data-testid": "combobox-input" }), allowClear && !isEmpty(normalizedSelected) && (jsx(Button, { size: "xs", iconOnly: true, "aria-label": "Clear selection", theme: "secondary", variant: "plain", className: "group absolute inset-y-0 right-8 h-6 top-2", onClick: () => handleOnChangeInternal(multiple ? [] : null), disabled: disabled, "data-testid": "combobox-clear-button", noOutlineOnFocus: true, children: jsx(SvgX, { className: "size-4 stroke-gray-500 dark:stroke-gray-300" }) })), jsx(ComboboxButton, { className: "group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center", "data-testid": "combobox-button", children: jsx(SvgChevronDown, { className: chevronIconClass }) })] })), jsxs(ComboboxOptions, { anchor: { to: 'bottom', gap: 5 }, as: "div", modal: modalDropdown, className: buildClassName('w-[var(--input-width)] rounded-lg border border-[var(--ui-border)] bg-white dark:bg-gray-800 p-1 shadow-lg max-h-80 overflow-y-auto z-50 [--anchor-gap:var(--spacing-1)]', '[--anchor-max-height:20rem]', 'origin-top border transition duration-200 ease-[cubic-bezier(0.4, 0.0, 0.2, 1)] data-[closed]:translate-y-[-15%] data-[closed]:opacity-0', dropdownContainerClass), transition: true, "data-testid": "combobox-options", children: [multiple && showSelectAll && allOptions.length > 0 && (jsxs("div", { className: "pb-1 mb-1 border-b border-[var(--ui-border-muted)] px-3 pt-1 flex items-center justify-between", children: [jsx("button", { type: "button", onClick: handleToggleSelectAll, className: "text-xs font-semibold text-blue-600 dark:text-blue-400 hover:underline cursor-pointer", children: isAllSelected ? 'Deselect All' : 'Select All' }), jsxs("span", { className: "text-[11px] font-medium text-gray-400", children: [Array.isArray(normalizedSelected) ? normalizedSelected.length : 0, " of", ' ', allOptions.length] })] })), optionsLoading ? (jsx(BodyText, { "data-testid": "options-loading", className: "flex items-center justify-center py-2 px-3 select-none", children: jsx(Loader, { size: "sm" }) })) : shouldShowTypeToSearch ? (jsx(BodyText, { className: "flex items-center justify-between py-2 px-3 select-none", children: "Type to search..." })) : (jsxs("div", { children: [allowFreeText &&
|
|
3977
|
+
query.trim() &&
|
|
3978
|
+
!allOptions.some((opt) => { var _a; return ((_a = getDisplayValue(opt)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === query.trim().toLowerCase(); }) && (jsx(ComboboxOption, { value: createFreeTextOption(query.trim()), className: "group flex items-center gap-2 rounded-lg py-1.5 px-3 select-none text-sm data-[focus]:bg-blue-50 dark:data-[focus]:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-medium cursor-pointer w-full", "data-testid": "freetext-option", children: jsxs("span", { children: ["Use \"", query.trim(), "\""] }) }, `freetext-${query.trim()}`)), filteredGroups
|
|
2276
3979
|
? filteredGroups.map((grp, gIdx) => (jsxs("div", { children: [jsx("div", { className: "text-[11px] font-bold uppercase tracking-wider text-gray-400 dark:text-gray-500 px-3 py-1 select-none", children: grp.group }), grp.options.map((option) => {
|
|
2277
3980
|
const optVal = getValue(option);
|
|
2278
3981
|
const isOptSelected = multiple
|
|
2279
|
-
? isArray(
|
|
2280
|
-
|
|
2281
|
-
|
|
3982
|
+
? isArray(normalizedSelected) &&
|
|
3983
|
+
normalizedSelected.some((s) => getValue(s) === optVal)
|
|
3984
|
+
: normalizedSelected && getValue(normalizedSelected) === optVal;
|
|
3985
|
+
return (jsx(ComboboxOption, { disabled: option.disabled, value: option, className: "group rounded-lg py-1.5 px-3 select-none data-[focus]:bg-gray-100 dark:data-[focus]:bg-white/10 data-disabled:opacity-50 cursor-pointer data-disabled:pointer-events-none", children: renderOption ? (renderOption(option, Boolean(isOptSelected))) : (jsxs("div", { className: "flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600", children: [jsx("span", { className: "text-sm/6", children: getDisplayValue(option) }), jsx(SvgCheck, { className: "invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible" })] })) }, optVal));
|
|
2282
3986
|
})] }, gIdx)))
|
|
2283
3987
|
: /* Render Standard Flat Options */
|
|
2284
3988
|
filteredOptions.map((option) => {
|
|
2285
3989
|
const optVal = getValue(option);
|
|
2286
3990
|
const isOptSelected = multiple
|
|
2287
|
-
? isArray(
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
3991
|
+
? isArray(normalizedSelected) &&
|
|
3992
|
+
normalizedSelected.some((s) => getValue(s) === optVal)
|
|
3993
|
+
: normalizedSelected && getValue(normalizedSelected) === optVal;
|
|
3994
|
+
return (jsx(ComboboxOption, { disabled: option.disabled, value: option, className: "group rounded-lg py-1.5 px-3 select-none data-[focus]:bg-gray-100 dark:data-[focus]:bg-white/10 data-disabled:opacity-50 cursor-pointer data-disabled:pointer-events-none", children: renderOption ? (renderOption(option, Boolean(isOptSelected))) : (jsxs("div", { className: "flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600", children: [jsx("span", { className: "text-sm/6", children: getDisplayValue(option) }), jsx(SvgCheck, { className: "invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible" })] })) }, optVal));
|
|
3995
|
+
}), filteredOptions.length === 0 &&
|
|
3996
|
+
!(filteredGroups === null || filteredGroups === void 0 ? void 0 : filteredGroups.length) &&
|
|
3997
|
+
!allowFreeText &&
|
|
3998
|
+
!(allowAdd && query.trim()) && (jsxs("div", { "data-testid": "no-result-found", className: "flex items-center gap-2 py-1.5 px-3 select-none", children: [jsx(TextContent, { muted: true, small: true, children: noOptionsText }), jsx(TextContent, { strong: true, small: true, children: query })] })), !allowFreeText && allowAdd && Boolean(query.trim()) && (jsx(ComboboxOption, { value: query, className: "group rounded-lg py-1.5 px-3 cursor-pointer text-gray-700 dark:text-gray-300 data-[focus]:bg-gray-100 dark:data-[focus]:bg-gray-700", onClick: () => void handleAddAndSelect(query), children: jsxs("div", { className: "flex items-center gap-2", children: [jsx(SvgCirclePlus, { className: "size-4.5" }), jsxs(TextContent, { children: [addNewText, " \"", query, "\""] })] }) }, `add-${query.trim()}`))] }))] })] }), showErrorMessage && error && (jsx("div", { className: "mt-1", children: jsx(TextContent, { error: true, small: true, children: error }) })), !error && helperText && (jsx("div", { className: "mt-1", children: jsx(TextContent, { muted: true, small: true, children: helperText }) }))] }));
|
|
2291
3999
|
});
|
|
2292
4000
|
SelectBox.displayName = 'SelectBox';
|
|
2293
4001
|
|
|
@@ -2321,10 +4029,15 @@ Skeleton.displayName = 'Skeleton';
|
|
|
2321
4029
|
|
|
2322
4030
|
const MinusIcon = ({ className }) => (jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) }));
|
|
2323
4031
|
const PlusIcon = ({ className }) => (jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: [jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }));
|
|
4032
|
+
const CONTAINER_SIZE_CLASS = {
|
|
4033
|
+
sm: 'h-8 text-xs',
|
|
4034
|
+
md: 'h-10 text-sm',
|
|
4035
|
+
lg: 'h-12 text-base',
|
|
4036
|
+
};
|
|
2324
4037
|
const BUTTON_SIZE_CLASS = {
|
|
2325
|
-
sm: '
|
|
2326
|
-
md: '
|
|
2327
|
-
lg: '
|
|
4038
|
+
sm: 'w-7.5 h-full',
|
|
4039
|
+
md: 'w-9.5 h-full',
|
|
4040
|
+
lg: 'w-11 h-full',
|
|
2328
4041
|
};
|
|
2329
4042
|
const ICON_SIZE_CLASS = {
|
|
2330
4043
|
sm: 'size-3.5',
|
|
@@ -2332,12 +4045,15 @@ const ICON_SIZE_CLASS = {
|
|
|
2332
4045
|
lg: 'size-4.5',
|
|
2333
4046
|
};
|
|
2334
4047
|
const INPUT_TEXT_CLASS = {
|
|
2335
|
-
sm: 'w-12 text-xs
|
|
2336
|
-
md: 'w-16 text-sm
|
|
2337
|
-
lg: 'w-20 text-base
|
|
4048
|
+
sm: 'w-12 text-xs',
|
|
4049
|
+
md: 'w-16 text-sm',
|
|
4050
|
+
lg: 'w-20 text-base',
|
|
2338
4051
|
};
|
|
2339
4052
|
const QuantityStepper = forwardRef((props, ref) => {
|
|
2340
|
-
const { value, onChange, min = 0, max = 99999, step = 1, label, size = 'md', prefix, suffix, disabled = false, className, onFocus, ...restProps } = props;
|
|
4053
|
+
const { value, onChange, min = 0, max = 99999, step = 1, label, labelHint, helperText, error, showErrorMessage = true, size = 'md', prefix, suffix, disabled = false, className, onFocus, id: customId, ...restProps } = props;
|
|
4054
|
+
const autoId = useId();
|
|
4055
|
+
const stepperId = customId || `stepper-${autoId}`;
|
|
4056
|
+
const hasError = Boolean(error);
|
|
2341
4057
|
const handleDecrement = () => {
|
|
2342
4058
|
if (disabled)
|
|
2343
4059
|
return;
|
|
@@ -2363,10 +4079,18 @@ const QuantityStepper = forwardRef((props, ref) => {
|
|
|
2363
4079
|
};
|
|
2364
4080
|
const isAtMin = disabled || value <= min;
|
|
2365
4081
|
const isAtMax = disabled || value >= max;
|
|
2366
|
-
return (jsxs("div", { className: buildClassName('flex flex-col gap-1 inline-flex', className), children: [label && (
|
|
4082
|
+
return (jsxs("div", { className: buildClassName('flex flex-col gap-1 inline-flex', className), children: [label && (jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsx(Label, { htmlFor: stepperId, className: disabled ? 'opacity-70 cursor-not-allowed' : '', children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: buildClassName('inline-flex items-center rounded-lg shadow-2xs transition-all duration-150', 'outline outline-1 -outline-offset-1', CONTAINER_SIZE_CLASS[size], hasError
|
|
4083
|
+
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
4084
|
+
: 'outline-[var(--ui-border)]', disabled
|
|
4085
|
+
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 outline-[var(--ui-border-muted)]'
|
|
4086
|
+
: 'bg-white dark:bg-gray-700', 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2'), "data-testid": "quantity-stepper", children: [jsx("button", { type: "button", disabled: isAtMin, onClick: handleDecrement, tabIndex: -1, "aria-label": "Decrease quantity", className: buildClassName('flex items-center justify-center rounded-l-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0', BUTTON_SIZE_CLASS[size], isAtMin
|
|
4087
|
+
? 'opacity-30 hover:bg-transparent cursor-not-allowed'
|
|
4088
|
+
: 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60'), "data-testid": "stepper-decrement", children: jsx(MinusIcon, { className: ICON_SIZE_CLASS[size] }) }), prefix && (jsx("span", { className: "pl-1 text-gray-400 dark:text-gray-400 select-none text-xs shrink-0", children: prefix })), jsx("input", { ref: ref, id: stepperId, type: "number", min: min, max: max, step: step, value: value === 0 ? '' : value, placeholder: "0", disabled: disabled, onFocus: (e) => {
|
|
2367
4089
|
e.target.select();
|
|
2368
4090
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
|
|
2369
|
-
}, onChange: handleInputChange, className: buildClassName('text-center font-semibold text-gray-900 dark:text-white bg-transparent focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none', INPUT_TEXT_CLASS[size]), "data-testid": "stepper-input", ...restProps }), suffix && jsx("span", { className: "pr-1 text-
|
|
4091
|
+
}, onChange: handleInputChange, className: buildClassName('text-center font-semibold text-gray-900 dark:text-white bg-transparent focus:outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none', INPUT_TEXT_CLASS[size]), "data-testid": "stepper-input", ...restProps }), suffix && (jsx("span", { className: "pr-1 text-gray-500 dark:text-gray-400 select-none text-xs shrink-0", children: suffix })), jsx("button", { type: "button", disabled: isAtMax, onClick: handleIncrement, tabIndex: -1, "aria-label": "Increase quantity", className: buildClassName('flex items-center justify-center rounded-r-lg text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-white transition-colors shrink-0', BUTTON_SIZE_CLASS[size], isAtMax
|
|
4092
|
+
? 'opacity-30 hover:bg-transparent cursor-not-allowed'
|
|
4093
|
+
: 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60'), "data-testid": "stepper-increment", children: jsx(PlusIcon, { className: ICON_SIZE_CLASS[size] }) })] }), (showErrorMessage && error) || helperText ? (jsx("div", { className: "flex items-center justify-between gap-2 mt-0.5", children: showErrorMessage && error ? (jsx(TextContent, { xsmall: true, className: "text-red-500 dark:text-red-400 font-medium", children: error })) : helperText ? (jsx(TextContent, { xsmall: true, muted: true, children: helperText })) : null })) : null] }));
|
|
2370
4094
|
});
|
|
2371
4095
|
QuantityStepper.displayName = 'QuantityStepper';
|
|
2372
4096
|
|
|
@@ -2412,7 +4136,7 @@ const SegmentedControl = forwardRef((props, ref) => {
|
|
|
2412
4136
|
onChange(enabledOptions[enabledOptions.length - 1].value);
|
|
2413
4137
|
}
|
|
2414
4138
|
};
|
|
2415
|
-
return (jsx("div", { ref: ref, role: "tablist", "aria-orientation": "horizontal", className: buildClassName('inline-flex items-center border border-
|
|
4139
|
+
return (jsx("div", { ref: ref, role: "tablist", "aria-orientation": "horizontal", className: buildClassName('inline-flex items-center border border-[var(--ui-border)] bg-gray-100/80 dark:bg-gray-800/80', SIZE_CONTAINER_CLASS[size], fullWidth ? 'w-full flex' : '', disabled ? 'opacity-60 cursor-not-allowed' : '', className), "data-testid": "segmented-control", ...restProps, children: options.map((option, index) => {
|
|
2416
4140
|
const isSelected = value === option.value;
|
|
2417
4141
|
const isOptionDisabled = disabled || option.disabled;
|
|
2418
4142
|
return (jsxs("button", { type: "button", role: "tab", "aria-selected": isSelected, "aria-disabled": isOptionDisabled, tabIndex: isSelected && !isOptionDisabled ? 0 : -1, disabled: isOptionDisabled, title: option.title, onClick: () => {
|
|
@@ -2473,7 +4197,7 @@ const StickyActionBar = forwardRef((props, ref) => {
|
|
|
2473
4197
|
: position === 'sticky'
|
|
2474
4198
|
? 'sticky bottom-0 z-30'
|
|
2475
4199
|
: 'relative z-10';
|
|
2476
|
-
return (jsxs(Fragment, { children: [jsx("div", { ref: ref, className: buildClassName(positionClass, 'border-t border-
|
|
4200
|
+
return (jsxs(Fragment, { children: [jsx("div", { ref: ref, className: buildClassName(positionClass, 'border-t border-[var(--ui-border)] bg-white/90 p-3.5 backdrop-blur-md shadow-lg dark:bg-gray-900/90 transition-all', className), "data-testid": "sticky-action-bar", ...restProps, children: jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (jsxs("button", { type: "button", onClick: () => setIsDrawerOpen(true), className: "flex items-center gap-2 text-left transition-opacity hover:opacity-80 cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)] rounded-lg p-1 -m-1", "aria-label": "Expand summary details", "data-testid": "summary-trigger", children: [jsx("div", { children: summaryContent }), jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsx("div", { children: summaryContent })) })), actionsContent && (jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (jsx(Drawer, { isOpen: isDrawerOpen, onClose: () => setIsDrawerOpen(false), align: "bottom", size: "full", title: drawerTitle, showBackButton: true, contentClass: "px-4 pb-6 max-h-[calc(100svh-6rem)] overflow-y-auto", children: drawerContent }))] }));
|
|
2477
4201
|
});
|
|
2478
4202
|
StickyActionBar.displayName = 'StickyActionBar';
|
|
2479
4203
|
|
|
@@ -2503,7 +4227,7 @@ function buildTabClass({ selected, variant, stretch, isVertical, tabClass, }) {
|
|
|
2503
4227
|
variantClass = isVertical
|
|
2504
4228
|
? buildClassName('px-3 py-2 w-full text-left border-l-2', selected
|
|
2505
4229
|
? 'border-[var(--ui-primary)] text-gray-900 dark:text-white'
|
|
2506
|
-
: 'border-transparent text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:border-
|
|
4230
|
+
: 'border-transparent text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:border-[var(--ui-border)]')
|
|
2507
4231
|
: buildClassName('px-3 py-1.5 relative text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white', selected &&
|
|
2508
4232
|
'text-gray-900 dark:text-white after:absolute after:z-10 after:left-0 after:right-0 after:-bottom-1 after:h-0.5 after:bg-[var(--ui-primary)]');
|
|
2509
4233
|
break;
|
|
@@ -2521,6 +4245,89 @@ function buildTabClass({ selected, variant, stretch, isVertical, tabClass, }) {
|
|
|
2521
4245
|
return buildClassName(base, variantClass, tabClass);
|
|
2522
4246
|
}
|
|
2523
4247
|
|
|
4248
|
+
function SwipeableTabs({ items, activeId: externalActiveId, defaultActiveId, onChange, swipeable = true, threshold = 50, headerVariant = 'default', containerClass = '', headerClass = '', contentClass = '', }) {
|
|
4249
|
+
var _a;
|
|
4250
|
+
const [internalActiveId, setInternalActiveId] = useState(defaultActiveId || ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.id) || '');
|
|
4251
|
+
const activeId = externalActiveId !== undefined ? externalActiveId : internalActiveId;
|
|
4252
|
+
const activeIndex = Math.max(0, items.findIndex((item) => item.id === activeId));
|
|
4253
|
+
const touchStartX = useRef(0);
|
|
4254
|
+
const touchStartY = useRef(0);
|
|
4255
|
+
const touchDeltaX = useRef(0);
|
|
4256
|
+
const isSwipingHorizontal = useRef(null);
|
|
4257
|
+
const handleTabChange = (item) => {
|
|
4258
|
+
if (item.disabled)
|
|
4259
|
+
return;
|
|
4260
|
+
setInternalActiveId(item.id);
|
|
4261
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(item.id);
|
|
4262
|
+
};
|
|
4263
|
+
const handleTouchStart = (e) => {
|
|
4264
|
+
if (!swipeable)
|
|
4265
|
+
return;
|
|
4266
|
+
touchStartX.current = e.touches[0].clientX;
|
|
4267
|
+
touchStartY.current = e.touches[0].clientY;
|
|
4268
|
+
touchDeltaX.current = 0;
|
|
4269
|
+
isSwipingHorizontal.current = null;
|
|
4270
|
+
};
|
|
4271
|
+
const handleTouchMove = (e) => {
|
|
4272
|
+
if (!swipeable)
|
|
4273
|
+
return;
|
|
4274
|
+
const currentX = e.touches[0].clientX;
|
|
4275
|
+
const currentY = e.touches[0].clientY;
|
|
4276
|
+
const deltaX = currentX - touchStartX.current;
|
|
4277
|
+
const deltaY = currentY - touchStartY.current;
|
|
4278
|
+
if (isSwipingHorizontal.current === null) {
|
|
4279
|
+
if (Math.abs(deltaX) > 8 || Math.abs(deltaY) > 8) {
|
|
4280
|
+
isSwipingHorizontal.current = Math.abs(deltaX) > Math.abs(deltaY);
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
if (isSwipingHorizontal.current) {
|
|
4284
|
+
touchDeltaX.current = deltaX;
|
|
4285
|
+
}
|
|
4286
|
+
};
|
|
4287
|
+
const handleTouchEnd = () => {
|
|
4288
|
+
if (!swipeable || !isSwipingHorizontal.current)
|
|
4289
|
+
return;
|
|
4290
|
+
const deltaX = touchDeltaX.current;
|
|
4291
|
+
if (Math.abs(deltaX) >= threshold) {
|
|
4292
|
+
if (deltaX < 0 && activeIndex < items.length - 1) {
|
|
4293
|
+
// Swiped Left -> Go to Next Tab
|
|
4294
|
+
const nextItem = items[activeIndex + 1];
|
|
4295
|
+
if (nextItem && !nextItem.disabled) {
|
|
4296
|
+
handleTabChange(nextItem);
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
else if (deltaX > 0 && activeIndex > 0) {
|
|
4300
|
+
// Swiped Right -> Go to Previous Tab
|
|
4301
|
+
const prevItem = items[activeIndex - 1];
|
|
4302
|
+
if (prevItem && !prevItem.disabled) {
|
|
4303
|
+
handleTabChange(prevItem);
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
}
|
|
4307
|
+
touchDeltaX.current = 0;
|
|
4308
|
+
isSwipingHorizontal.current = null;
|
|
4309
|
+
};
|
|
4310
|
+
return (jsxs("div", { className: buildClassName('w-full flex flex-col', containerClass), "data-testid": "swipeable-tabs", children: [jsx("div", { className: buildClassName('w-full flex items-center gap-1 border-b border-[var(--ui-border)] overflow-x-auto no-scrollbar select-none', headerVariant === 'segmented' &&
|
|
4311
|
+
'p-1 bg-gray-100 dark:bg-gray-800/80 rounded-2xl border-none gap-0', headerClass), "data-testid": "swipeable-tabs-header", children: items.map((item) => {
|
|
4312
|
+
const isActive = item.id === activeId;
|
|
4313
|
+
if (headerVariant === 'segmented') {
|
|
4314
|
+
return (jsxs("button", { type: "button", disabled: item.disabled, onClick: () => handleTabChange(item), className: buildClassName('flex-1 flex items-center justify-center gap-1.5 py-1.5 px-3 rounded-xl text-xs font-semibold transition-all duration-150 cursor-pointer', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive
|
|
4315
|
+
? 'bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow-xs'
|
|
4316
|
+
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'), "data-testid": `swipeable-tab-btn-${item.id}`, children: [item.icon && jsx("span", { className: "text-sm", children: item.icon }), jsx("span", { children: item.label }), item.badge !== undefined && (jsx("span", { className: "px-1.5 py-0.5 text-[10px] rounded-full bg-blue-100 dark:bg-blue-950 text-blue-600 dark:text-blue-400 font-bold", children: item.badge }))] }, item.id));
|
|
4317
|
+
}
|
|
4318
|
+
if (headerVariant === 'pills') {
|
|
4319
|
+
return (jsxs("button", { type: "button", disabled: item.disabled, onClick: () => handleTabChange(item), className: buildClassName('flex items-center justify-center gap-1.5 py-1.5 px-3.5 rounded-full text-xs font-semibold transition-all duration-150 cursor-pointer whitespace-nowrap', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive
|
|
4320
|
+
? 'bg-blue-600 text-white shadow-xs'
|
|
4321
|
+
: 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'), "data-testid": `swipeable-tab-btn-${item.id}`, children: [item.icon && jsx("span", { className: "text-sm", children: item.icon }), jsx("span", { children: item.label }), item.badge !== undefined && (jsx("span", { className: "px-1.5 py-0.5 text-[10px] rounded-full bg-white/20 text-current font-bold", children: item.badge }))] }, item.id));
|
|
4322
|
+
}
|
|
4323
|
+
// Default Underline Tab Header
|
|
4324
|
+
return (jsxs("button", { type: "button", disabled: item.disabled, onClick: () => handleTabChange(item), className: buildClassName('flex items-center justify-center gap-1.5 py-2.5 px-4 text-xs font-semibold transition-all duration-150 cursor-pointer relative whitespace-nowrap border-b-2 -mb-px', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive
|
|
4325
|
+
? 'border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400'
|
|
4326
|
+
: 'border-transparent text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'), "data-testid": `swipeable-tab-btn-${item.id}`, children: [item.icon && jsx("span", { className: "text-sm", children: item.icon }), jsx("span", { children: item.label }), item.badge !== undefined && (jsx("span", { className: "px-1.5 py-0.5 text-[10px] rounded-full bg-blue-100 dark:bg-blue-950 text-blue-600 dark:text-blue-400 font-bold", children: item.badge }))] }, item.id));
|
|
4327
|
+
}) }), jsx("div", { className: buildClassName('w-full overflow-hidden relative touch-pan-y', contentClass), onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, "data-testid": "swipeable-tabs-viewport", children: jsx("div", { className: "flex w-full transition-transform duration-300 ease-out", style: { transform: `translateX(-${activeIndex * 100}%)` }, "data-testid": "swipeable-tabs-track", children: items.map((item) => (jsx("div", { className: "w-full shrink-0 min-w-full", "data-testid": `swipeable-tab-panel-${item.id}`, children: item.content }, item.id))) }) })] }));
|
|
4328
|
+
}
|
|
4329
|
+
SwipeableTabs.displayName = 'SwipeableTabs';
|
|
4330
|
+
|
|
2524
4331
|
const sizeClasses = {
|
|
2525
4332
|
sm: {
|
|
2526
4333
|
textarea: 'px-2.5 py-1.5 text-xs leading-5 min-h-[60px]',
|
|
@@ -2568,7 +4375,7 @@ const Textarea = forwardRef((props, ref) => {
|
|
|
2568
4375
|
const currentSize = sizeClasses[size] || sizeClasses.md;
|
|
2569
4376
|
return (jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxs("div", { className: "relative", children: [hasLeftGroup && (jsx("span", { className: "absolute top-2.5 left-3 flex items-center justify-center text-gray-400 dark:text-gray-500", children: leftGroup })), jsx("textarea", { ref: innerRef, autoComplete: "off", ...inputProps, value: value, defaultValue: defaultValue, onChange: handleTextareaChange, maxLength: maxLength, name: name, id: id, className: buildClassName('transition-all duration-150', 'block w-full rounded-lg bg-white', currentSize.textarea, autoSize ? 'resize-none overflow-hidden' : resizeClasses[resize], 'text-gray-900 outline outline-1 -outline-offset-1', hasError
|
|
2570
4377
|
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
2571
|
-
: 'outline-
|
|
4378
|
+
: 'outline-[var(--ui-border)]', 'focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2', 'dark:bg-gray-700 dark:placeholder-gray-400 placeholder:text-gray-400 dark:text-white', 'disabled:pointer-events-none disabled:bg-gray-100 disabled:outline-[var(--ui-border-muted)]', 'dark:disabled:bg-gray-800 dark:disabled:text-gray-600 dark:disabled:placeholder-gray-600 dark:disabled:outline-[var(--ui-border-muted)]', hasRightGroup ? 'pe-10' : '', hasLeftGroup ? 'ps-10' : '', className) }), hasRightGroup && (jsx("span", { className: "absolute end-3 top-2.5 flex items-center justify-center text-gray-400 dark:text-gray-500", children: rightGroup }))] }), (showErrorMessage && error) || helperText || showCount ? (jsxs("div", { className: "mt-1.5 flex items-center justify-between gap-2 text-xs", children: [jsx("div", { className: "min-w-0 flex-1", children: showErrorMessage && error ? (jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsx(TextContent, { muted: true, small: true, children: helperText })) : null }), showCount && (jsxs("span", { className: buildClassName('text-[11px] font-medium shrink-0 ml-auto', maxLength && charLength >= maxLength
|
|
2572
4379
|
? 'text-red-500 font-semibold'
|
|
2573
4380
|
: 'text-gray-400 dark:text-gray-500'), children: [charLength, maxLength ? ` / ${maxLength}` : ''] }))] })) : null] }));
|
|
2574
4381
|
});
|
|
@@ -2603,10 +4410,10 @@ const progressBarColorMap = {
|
|
|
2603
4410
|
};
|
|
2604
4411
|
const variantStyleMap = {
|
|
2605
4412
|
accent: {
|
|
2606
|
-
success: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-
|
|
2607
|
-
error: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-
|
|
2608
|
-
info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-
|
|
2609
|
-
warning: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-
|
|
4413
|
+
success: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-success)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',
|
|
4414
|
+
error: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-danger)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',
|
|
4415
|
+
info: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-info)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',
|
|
4416
|
+
warning: 'bg-white dark:bg-gray-900 border-l-4 border-[var(--ui-warning)] text-gray-900 dark:text-gray-100 shadow-lg border-y border-r border-[var(--ui-border)]',
|
|
2610
4417
|
},
|
|
2611
4418
|
filled: {
|
|
2612
4419
|
success: 'bg-[var(--ui-success)] text-white shadow-lg',
|
|
@@ -2946,7 +4753,10 @@ const useIsMobile = () => {
|
|
|
2946
4753
|
useEffect(() => {
|
|
2947
4754
|
const detect = () => {
|
|
2948
4755
|
const width = window.innerWidth;
|
|
2949
|
-
const isTouch = navigator.maxTouchPoints > 1 ||
|
|
4756
|
+
const isTouch = (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1) ||
|
|
4757
|
+
(typeof window !== 'undefined' &&
|
|
4758
|
+
typeof window.matchMedia === 'function' &&
|
|
4759
|
+
window.matchMedia('(pointer: coarse)').matches);
|
|
2950
4760
|
setIsMobile(width < 600 && isTouch);
|
|
2951
4761
|
};
|
|
2952
4762
|
detect();
|
|
@@ -2977,5 +4787,5 @@ const useIsTabletOrMobile = () => {
|
|
|
2977
4787
|
return isMobile || isTablet;
|
|
2978
4788
|
};
|
|
2979
4789
|
|
|
2980
|
-
export { Accordion, Alert, Badge, Banner, BodyText, Breadcrumb, Button, ButtonGroup, Card, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, DOTS, DataTable, DetailedInformation, Dot, Drawer, Dropdown, EmptyState, EmptyTableRow, HeadingText, Input, Label, Loader, PASSWORD_PLACEHOLDER, PASSWORD_TYPE, Pagination, PasswordInput, QuantityStepper, Radio, RadioGroup, RadioSwitch, RangeInput, RangeSlider, SegmentedControl, SelectBox, Skeleton, SortIconMap, StatusPill, StickyActionBar, Table, TableBody, TableCell, TableFoot, TableHead, TableHeaderCell, TableRow, Tabs, TextContent, Textarea, Toast, ToastProvider, VirtualizedDataTable, buildClassName, buildInputClass, evaluatePasswordStrength, get, getSortIcon, isArray, isEmpty, nextSortDirection, updateSortQuery, useDebounce, useDebounceFn, useIsMobile, useIsTablet, useIsTabletOrMobile, usePagination, useRowSelection, useToast };
|
|
4790
|
+
export { Accordion, ActionSheet, Alert, Badge, Banner, BodyText, BottomNavigation, Breadcrumb, Button, ButtonGroup, Card, CardContent, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle, Checkbox, CheckboxGroup, DOTS, DataList, DataTable, DetailedInformation, Dot, Drawer, Dropdown, EmptyState, EmptyTableRow, Flex, FlexItem, FloatingActionButton, Grid, GridCol, HeadingText, Input, Label, Loader, MobileHeader, MobilePicker, MobileStepper, PASSWORD_PLACEHOLDER, PASSWORD_TYPE, Pagination, PasswordInput, PinInput, PullToRefresh, QuantityStepper, Radio, RadioGroup, RadioSwitch, RangeInput, RangeSlider, SegmentedControl, SelectBox, Skeleton, SortIconMap, StatusPill, StickyActionBar, SwipeableRow, SwipeableTabs, Table, TableBody, TableCell, TableFoot, TableHead, TableHeaderCell, TableRow, Tabs, TextContent, Textarea, Toast, ToastProvider, VirtualizedDataTable, WheelPicker, buildClassName, buildInputClass, evaluatePasswordStrength, get, getSortIcon, isArray, isEmpty, nextSortDirection, updateSortQuery, useDebounce, useDebounceFn, useIsMobile, useIsTablet, useIsTabletOrMobile, usePagination, useRowSelection, useToast };
|
|
2981
4791
|
//# sourceMappingURL=react-tailwind.es.js.map
|