@pk-design/react-tailwind 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/Accordion/Accordion.js +61 -0
- package/dist/cjs/components/Accordion/Accordion.js.map +1 -0
- package/dist/cjs/components/ActionSheet/ActionSheet.js +38 -0
- package/dist/cjs/components/ActionSheet/ActionSheet.js.map +1 -0
- package/dist/cjs/components/Alert/Alert.js +34 -0
- package/dist/cjs/components/Alert/Alert.js.map +1 -0
- package/dist/cjs/components/Badge/Badge.js +33 -0
- package/dist/cjs/components/Badge/Badge.js.map +1 -0
- package/dist/cjs/components/Banner/Banner.js +41 -0
- package/dist/cjs/components/Banner/Banner.js.map +1 -0
- package/dist/cjs/components/BodyText/BodyText.js +59 -0
- package/dist/cjs/components/BodyText/BodyText.js.map +1 -0
- package/dist/cjs/components/BottomNavigation/BottomNavigation.js +52 -0
- package/dist/cjs/components/BottomNavigation/BottomNavigation.js.map +1 -0
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js +63 -0
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/cjs/components/Button/Button.js +118 -0
- package/dist/cjs/components/Button/Button.js.map +1 -0
- package/dist/cjs/components/ButtonGroup/ButtonGroup.js +100 -0
- package/dist/cjs/components/ButtonGroup/ButtonGroup.js.map +1 -0
- package/dist/cjs/components/Card/Card.js +65 -0
- package/dist/cjs/components/Card/Card.js.map +1 -0
- package/dist/cjs/components/Checkbox/Checkbox.js +64 -0
- package/dist/cjs/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/cjs/components/CheckboxGroup/CheckboxGroup.js +82 -0
- package/dist/cjs/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
- package/dist/cjs/components/DataList/DataList.js +287 -0
- package/dist/cjs/components/DataList/DataList.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.icons.js +20 -0
- package/dist/cjs/components/DataTable/DataTable.icons.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.js +110 -0
- package/dist/cjs/components/DataTable/DataTable.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTable.utils.js +87 -0
- package/dist/cjs/components/DataTable/DataTable.utils.js.map +1 -0
- package/dist/cjs/components/DetailedInformation/DetailedInformation.js +67 -0
- package/dist/cjs/components/DetailedInformation/DetailedInformation.js.map +1 -0
- package/dist/cjs/components/Dot/index.js +12 -0
- package/dist/cjs/components/Dot/index.js.map +1 -0
- package/dist/cjs/components/Drawer/Drawer.js +67 -0
- package/dist/cjs/components/Drawer/Drawer.js.map +1 -0
- package/dist/cjs/components/Dropdown/Dropdown.js +50 -0
- package/dist/cjs/components/Dropdown/Dropdown.js.map +1 -0
- package/dist/cjs/components/EmptyState/index.js +14 -0
- package/dist/cjs/components/EmptyState/index.js.map +1 -0
- package/dist/cjs/components/Flex/Flex.js +25 -0
- package/dist/cjs/components/Flex/Flex.js.map +1 -0
- package/dist/cjs/components/FloatingActionButton/FloatingActionButton.js +71 -0
- package/dist/cjs/components/FloatingActionButton/FloatingActionButton.js.map +1 -0
- package/dist/cjs/components/Grid/Grid.js +33 -0
- package/dist/cjs/components/Grid/Grid.js.map +1 -0
- package/dist/cjs/components/HeadingText/HeadingText.js +89 -0
- package/dist/cjs/components/HeadingText/HeadingText.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownAZ.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownAZ.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownNarrowWide.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownNarrowWide.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownWideNarrow.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownWideNarrow.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowDownZA.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowDownZA.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ArrowUpDown.svg.js +46 -0
- package/dist/cjs/components/Icons/ArrowUpDown.svg.js.map +1 -0
- package/dist/cjs/components/Icons/BadgeCheck.svg.js +48 -0
- package/dist/cjs/components/Icons/BadgeCheck.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Check.svg.js +46 -0
- package/dist/cjs/components/Icons/Check.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronDown.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronDown.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronLeft.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronLeft.svg.js.map +1 -0
- package/dist/cjs/components/Icons/ChevronRight.svg.js +46 -0
- package/dist/cjs/components/Icons/ChevronRight.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleAlert.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleAlert.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleCheck.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleCheck.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CirclePlus.svg.js +50 -0
- package/dist/cjs/components/Icons/CirclePlus.svg.js.map +1 -0
- package/dist/cjs/components/Icons/CircleX.svg.js +50 -0
- package/dist/cjs/components/Icons/CircleX.svg.js.map +1 -0
- package/dist/cjs/components/Icons/FolderPlus.svg.js +46 -0
- package/dist/cjs/components/Icons/FolderPlus.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Info.svg.js +50 -0
- package/dist/cjs/components/Icons/Info.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Search.svg.js +50 -0
- package/dist/cjs/components/Icons/Search.svg.js.map +1 -0
- package/dist/cjs/components/Icons/Slash.svg.js +46 -0
- package/dist/cjs/components/Icons/Slash.svg.js.map +1 -0
- package/dist/cjs/components/Icons/TriangleAlert.svg.js +46 -0
- package/dist/cjs/components/Icons/TriangleAlert.svg.js.map +1 -0
- package/dist/cjs/components/Icons/X.svg.js +46 -0
- package/dist/cjs/components/Icons/X.svg.js.map +1 -0
- package/dist/cjs/components/Input/Input.js +85 -0
- package/dist/cjs/components/Input/Input.js.map +1 -0
- package/dist/cjs/components/Label/Label.js +14 -0
- package/dist/cjs/components/Label/Label.js.map +1 -0
- package/dist/cjs/components/Loader/index.js +18 -0
- package/dist/cjs/components/Loader/index.js.map +1 -0
- package/dist/cjs/components/MobileHeader/MobileHeader.js +45 -0
- package/dist/cjs/components/MobileHeader/MobileHeader.js.map +1 -0
- package/dist/cjs/components/MobilePicker/MobilePicker.js +368 -0
- package/dist/cjs/components/MobilePicker/MobilePicker.js.map +1 -0
- package/dist/cjs/components/MobileStepper/MobileStepper.js +33 -0
- package/dist/cjs/components/MobileStepper/MobileStepper.js.map +1 -0
- package/dist/cjs/components/Pagination/Pagination.js +33 -0
- package/dist/cjs/components/Pagination/Pagination.js.map +1 -0
- package/dist/cjs/components/Pagination/usePagination.js +33 -0
- package/dist/cjs/components/Pagination/usePagination.js.map +1 -0
- package/dist/cjs/components/PasswordInput/PasswordInput.js +56 -0
- package/dist/cjs/components/PasswordInput/PasswordInput.js.map +1 -0
- package/dist/cjs/components/PinInput/PinInput.js +98 -0
- package/dist/cjs/components/PinInput/PinInput.js.map +1 -0
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js +83 -0
- package/dist/cjs/components/PullToRefresh/PullToRefresh.js.map +1 -0
- package/dist/cjs/components/QuantityStepper/QuantityStepper.js +77 -0
- package/dist/cjs/components/QuantityStepper/QuantityStepper.js.map +1 -0
- package/dist/cjs/components/Radio/Radio.js +34 -0
- package/dist/cjs/components/Radio/Radio.js.map +1 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.js +50 -0
- package/dist/cjs/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/cjs/components/RadioSwitch/RadioSwitch.js +116 -0
- package/dist/cjs/components/RadioSwitch/RadioSwitch.js.map +1 -0
- package/dist/cjs/components/RangeInput/RangeInput.js +66 -0
- package/dist/cjs/components/RangeInput/RangeInput.js.map +1 -0
- package/dist/cjs/components/RangeSlider/RangeSlider.js +167 -0
- package/dist/cjs/components/RangeSlider/RangeSlider.js.map +1 -0
- package/dist/cjs/components/SegmentedControl/SegmentedControl.js +64 -0
- package/dist/cjs/components/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/cjs/components/SelectBox/SelectBox.js +305 -0
- package/dist/cjs/components/SelectBox/SelectBox.js.map +1 -0
- package/dist/cjs/components/Skeleton/Skeleton.js +36 -0
- package/dist/cjs/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/cjs/components/StatusPill/StatusPill.js +46 -0
- package/dist/cjs/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js +22 -0
- package/dist/cjs/components/StickyActionBar/StickyActionBar.js.map +1 -0
- package/dist/cjs/components/SwipeableRow/SwipeableRow.js +187 -0
- package/dist/cjs/components/SwipeableRow/SwipeableRow.js.map +1 -0
- package/dist/cjs/components/SwipeableTabs/SwipeableTabs.js +91 -0
- package/dist/cjs/components/SwipeableTabs/SwipeableTabs.js.map +1 -0
- package/dist/cjs/components/Table/Table.js +57 -0
- package/dist/cjs/components/Table/Table.js.map +1 -0
- package/dist/cjs/components/Tabs/Tabs.js +53 -0
- package/dist/cjs/components/Tabs/Tabs.js.map +1 -0
- package/dist/cjs/components/TextContent/TextContent.js +47 -0
- package/dist/cjs/components/TextContent/TextContent.js.map +1 -0
- package/dist/cjs/components/Textarea/Textarea.js +64 -0
- package/dist/cjs/components/Textarea/Textarea.js.map +1 -0
- package/dist/cjs/components/Toast/Toast.js +96 -0
- package/dist/cjs/components/Toast/Toast.js.map +1 -0
- package/dist/cjs/components/Toast/ToastProvider.js +151 -0
- package/dist/cjs/components/Toast/ToastProvider.js.map +1 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedDataTable.js +122 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedDataTable.js.map +1 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedRow.js +48 -0
- package/dist/cjs/components/VirtualizedDataTable/VirtualizedRow.js.map +1 -0
- package/dist/cjs/components/WheelPicker/WheelPicker.js +82 -0
- package/dist/cjs/components/WheelPicker/WheelPicker.js.map +1 -0
- package/dist/cjs/components/common-responsive.js +310 -0
- package/dist/cjs/components/common-responsive.js.map +1 -0
- package/dist/cjs/hooks/use-debounce.js +31 -0
- package/dist/cjs/hooks/use-debounce.js.map +1 -0
- package/dist/cjs/hooks/use-is-mobile.js +24 -0
- package/dist/cjs/hooks/use-is-mobile.js.map +1 -0
- package/dist/cjs/hooks/use-is-tablet-or-mobile.js +13 -0
- package/dist/cjs/hooks/use-is-tablet-or-mobile.js.map +1 -0
- package/dist/cjs/hooks/use-is-tablet.js +21 -0
- package/dist/cjs/hooks/use-is-tablet.js.map +1 -0
- package/dist/cjs/index.js +163 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/react-tailwind.css +2 -0
- package/dist/cjs/react-tailwind.css.map +1 -0
- package/dist/cjs/utils/build-classname.js +8 -0
- package/dist/cjs/utils/build-classname.js.map +1 -0
- package/dist/cjs/utils/get.js +20 -0
- package/dist/cjs/utils/get.js.map +1 -0
- package/dist/cjs/utils/is-array.js +12 -0
- package/dist/cjs/utils/is-array.js.map +1 -0
- package/dist/cjs/utils/is-empty.js +26 -0
- package/dist/cjs/utils/is-empty.js.map +1 -0
- package/dist/es/components/Accordion/Accordion.js +59 -0
- package/dist/es/components/Accordion/Accordion.js.map +1 -0
- package/dist/es/components/ActionSheet/ActionSheet.js +36 -0
- package/dist/es/components/ActionSheet/ActionSheet.js.map +1 -0
- package/dist/es/components/Alert/Alert.js +32 -0
- package/dist/es/components/Alert/Alert.js.map +1 -0
- package/dist/es/components/Badge/Badge.js +31 -0
- package/dist/es/components/Badge/Badge.js.map +1 -0
- package/dist/es/components/Banner/Banner.js +39 -0
- package/dist/es/components/Banner/Banner.js.map +1 -0
- package/dist/es/components/BodyText/BodyText.js +57 -0
- package/dist/es/components/BodyText/BodyText.js.map +1 -0
- package/dist/es/components/BottomNavigation/BottomNavigation.js +50 -0
- package/dist/es/components/BottomNavigation/BottomNavigation.js.map +1 -0
- package/dist/es/components/Breadcrumb/Breadcrumb.js +61 -0
- package/dist/es/components/Breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/es/components/Button/Button.js +116 -0
- package/dist/es/components/Button/Button.js.map +1 -0
- package/dist/es/components/ButtonGroup/ButtonGroup.js +98 -0
- package/dist/es/components/ButtonGroup/ButtonGroup.js.map +1 -0
- package/dist/es/components/Card/Card.js +57 -0
- package/dist/es/components/Card/Card.js.map +1 -0
- package/dist/es/components/Checkbox/Checkbox.js +62 -0
- package/dist/es/components/Checkbox/Checkbox.js.map +1 -0
- package/dist/es/components/CheckboxGroup/CheckboxGroup.js +80 -0
- package/dist/es/components/CheckboxGroup/CheckboxGroup.js.map +1 -0
- package/dist/es/components/DataList/DataList.js +285 -0
- package/dist/es/components/DataList/DataList.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.icons.js +17 -0
- package/dist/es/components/DataTable/DataTable.icons.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.js +108 -0
- package/dist/es/components/DataTable/DataTable.js.map +1 -0
- package/dist/es/components/DataTable/DataTable.utils.js +83 -0
- package/dist/es/components/DataTable/DataTable.utils.js.map +1 -0
- package/dist/es/components/DetailedInformation/DetailedInformation.js +65 -0
- package/dist/es/components/DetailedInformation/DetailedInformation.js.map +1 -0
- package/dist/es/components/Dot/index.js +10 -0
- package/dist/es/components/Dot/index.js.map +1 -0
- package/dist/es/components/Drawer/Drawer.js +65 -0
- package/dist/es/components/Drawer/Drawer.js.map +1 -0
- package/dist/es/components/Dropdown/Dropdown.js +48 -0
- package/dist/es/components/Dropdown/Dropdown.js.map +1 -0
- package/dist/es/components/EmptyState/index.js +12 -0
- package/dist/es/components/EmptyState/index.js.map +1 -0
- package/dist/es/components/Flex/Flex.js +22 -0
- package/dist/es/components/Flex/Flex.js.map +1 -0
- package/dist/es/components/FloatingActionButton/FloatingActionButton.js +69 -0
- package/dist/es/components/FloatingActionButton/FloatingActionButton.js.map +1 -0
- package/dist/es/components/Grid/Grid.js +30 -0
- package/dist/es/components/Grid/Grid.js.map +1 -0
- package/dist/es/components/HeadingText/HeadingText.js +87 -0
- package/dist/es/components/HeadingText/HeadingText.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownAZ.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownAZ.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownNarrowWide.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownNarrowWide.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownWideNarrow.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownWideNarrow.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowDownZA.svg.js +23 -0
- package/dist/es/components/Icons/ArrowDownZA.svg.js.map +1 -0
- package/dist/es/components/Icons/ArrowUpDown.svg.js +23 -0
- package/dist/es/components/Icons/ArrowUpDown.svg.js.map +1 -0
- package/dist/es/components/Icons/BadgeCheck.svg.js +25 -0
- package/dist/es/components/Icons/BadgeCheck.svg.js.map +1 -0
- package/dist/es/components/Icons/Check.svg.js +23 -0
- package/dist/es/components/Icons/Check.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronDown.svg.js +23 -0
- package/dist/es/components/Icons/ChevronDown.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronLeft.svg.js +23 -0
- package/dist/es/components/Icons/ChevronLeft.svg.js.map +1 -0
- package/dist/es/components/Icons/ChevronRight.svg.js +23 -0
- package/dist/es/components/Icons/ChevronRight.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleAlert.svg.js +27 -0
- package/dist/es/components/Icons/CircleAlert.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleCheck.svg.js +27 -0
- package/dist/es/components/Icons/CircleCheck.svg.js.map +1 -0
- package/dist/es/components/Icons/CirclePlus.svg.js +27 -0
- package/dist/es/components/Icons/CirclePlus.svg.js.map +1 -0
- package/dist/es/components/Icons/CircleX.svg.js +27 -0
- package/dist/es/components/Icons/CircleX.svg.js.map +1 -0
- package/dist/es/components/Icons/FolderPlus.svg.js +23 -0
- package/dist/es/components/Icons/FolderPlus.svg.js.map +1 -0
- package/dist/es/components/Icons/Info.svg.js +27 -0
- package/dist/es/components/Icons/Info.svg.js.map +1 -0
- package/dist/es/components/Icons/Search.svg.js +27 -0
- package/dist/es/components/Icons/Search.svg.js.map +1 -0
- package/dist/es/components/Icons/Slash.svg.js +23 -0
- package/dist/es/components/Icons/Slash.svg.js.map +1 -0
- package/dist/es/components/Icons/TriangleAlert.svg.js +23 -0
- package/dist/es/components/Icons/TriangleAlert.svg.js.map +1 -0
- package/dist/es/components/Icons/X.svg.js +23 -0
- package/dist/es/components/Icons/X.svg.js.map +1 -0
- package/dist/es/components/Input/Input.js +82 -0
- package/dist/es/components/Input/Input.js.map +1 -0
- package/dist/es/components/Label/Label.js +12 -0
- package/dist/es/components/Label/Label.js.map +1 -0
- package/dist/es/components/Loader/index.js +16 -0
- package/dist/es/components/Loader/index.js.map +1 -0
- package/dist/es/components/MobileHeader/MobileHeader.js +43 -0
- package/dist/es/components/MobileHeader/MobileHeader.js.map +1 -0
- package/dist/es/components/MobilePicker/MobilePicker.js +366 -0
- package/dist/es/components/MobilePicker/MobilePicker.js.map +1 -0
- package/dist/es/components/MobileStepper/MobileStepper.js +31 -0
- package/dist/es/components/MobileStepper/MobileStepper.js.map +1 -0
- package/dist/es/components/Pagination/Pagination.js +31 -0
- package/dist/es/components/Pagination/Pagination.js.map +1 -0
- package/dist/es/components/Pagination/usePagination.js +30 -0
- package/dist/es/components/Pagination/usePagination.js.map +1 -0
- package/dist/es/components/PasswordInput/PasswordInput.js +51 -0
- package/dist/es/components/PasswordInput/PasswordInput.js.map +1 -0
- package/dist/es/components/PinInput/PinInput.js +96 -0
- package/dist/es/components/PinInput/PinInput.js.map +1 -0
- package/dist/es/components/PullToRefresh/PullToRefresh.js +81 -0
- package/dist/es/components/PullToRefresh/PullToRefresh.js.map +1 -0
- package/dist/es/components/QuantityStepper/QuantityStepper.js +75 -0
- package/dist/es/components/QuantityStepper/QuantityStepper.js.map +1 -0
- package/dist/es/components/Radio/Radio.js +32 -0
- package/dist/es/components/Radio/Radio.js.map +1 -0
- package/dist/es/components/RadioGroup/RadioGroup.js +48 -0
- package/dist/es/components/RadioGroup/RadioGroup.js.map +1 -0
- package/dist/es/components/RadioSwitch/RadioSwitch.js +114 -0
- package/dist/es/components/RadioSwitch/RadioSwitch.js.map +1 -0
- package/dist/es/components/RangeInput/RangeInput.js +64 -0
- package/dist/es/components/RangeInput/RangeInput.js.map +1 -0
- package/dist/es/components/RangeSlider/RangeSlider.js +165 -0
- package/dist/es/components/RangeSlider/RangeSlider.js.map +1 -0
- package/dist/es/components/SegmentedControl/SegmentedControl.js +62 -0
- package/dist/es/components/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/es/components/SelectBox/SelectBox.js +303 -0
- package/dist/es/components/SelectBox/SelectBox.js.map +1 -0
- package/dist/es/components/Skeleton/Skeleton.js +34 -0
- package/dist/es/components/Skeleton/Skeleton.js.map +1 -0
- package/dist/es/components/StatusPill/StatusPill.js +44 -0
- package/dist/es/components/StatusPill/StatusPill.js.map +1 -0
- package/dist/es/components/StickyActionBar/StickyActionBar.js +20 -0
- package/dist/es/components/StickyActionBar/StickyActionBar.js.map +1 -0
- package/dist/es/components/SwipeableRow/SwipeableRow.js +185 -0
- package/dist/es/components/SwipeableRow/SwipeableRow.js.map +1 -0
- package/dist/es/components/SwipeableTabs/SwipeableTabs.js +89 -0
- package/dist/es/components/SwipeableTabs/SwipeableTabs.js.map +1 -0
- package/dist/es/components/Table/Table.js +48 -0
- package/dist/es/components/Table/Table.js.map +1 -0
- package/dist/es/components/Tabs/Tabs.js +51 -0
- package/dist/es/components/Tabs/Tabs.js.map +1 -0
- package/dist/es/components/TextContent/TextContent.js +45 -0
- package/dist/es/components/TextContent/TextContent.js.map +1 -0
- package/dist/es/components/Textarea/Textarea.js +62 -0
- package/dist/es/components/Textarea/Textarea.js.map +1 -0
- package/dist/es/components/Toast/Toast.js +94 -0
- package/dist/es/components/Toast/Toast.js.map +1 -0
- package/dist/es/components/Toast/ToastProvider.js +148 -0
- package/dist/es/components/Toast/ToastProvider.js.map +1 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedDataTable.js +120 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedDataTable.js.map +1 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedRow.js +46 -0
- package/dist/es/components/VirtualizedDataTable/VirtualizedRow.js.map +1 -0
- package/dist/es/components/WheelPicker/WheelPicker.js +80 -0
- package/dist/es/components/WheelPicker/WheelPicker.js.map +1 -0
- package/dist/es/components/common-responsive.js +287 -0
- package/dist/es/components/common-responsive.js.map +1 -0
- package/dist/es/hooks/use-debounce.js +28 -0
- package/dist/es/hooks/use-debounce.js.map +1 -0
- package/dist/es/hooks/use-is-mobile.js +22 -0
- package/dist/es/hooks/use-is-mobile.js.map +1 -0
- package/dist/es/hooks/use-is-tablet-or-mobile.js +11 -0
- package/dist/es/hooks/use-is-tablet-or-mobile.js.map +1 -0
- package/dist/es/hooks/use-is-tablet.js +19 -0
- package/dist/es/hooks/use-is-tablet.js.map +1 -0
- package/dist/es/index.js +67 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react-tailwind.css +2 -0
- package/dist/es/react-tailwind.css.map +1 -0
- package/dist/es/utils/build-classname.js +6 -0
- package/dist/es/utils/build-classname.js.map +1 -0
- package/dist/es/utils/get.js +18 -0
- package/dist/es/utils/get.js.map +1 -0
- package/dist/es/utils/is-array.js +10 -0
- package/dist/es/utils/is-array.js.map +1 -0
- package/dist/es/utils/is-empty.js +24 -0
- package/dist/es/utils/is-empty.js.map +1 -0
- package/dist/react-tailwind.cjs.js +2298 -472
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +2284 -474
- package/dist/react-tailwind.es.js.map +1 -1
- package/dist/types/components/ActionSheet/ActionSheet.d.ts +5 -0
- package/dist/types/components/ActionSheet/ActionSheet.test.d.ts +1 -0
- package/dist/types/components/ActionSheet/ActionSheet.types.d.ts +44 -0
- package/dist/types/components/ActionSheet/index.d.ts +2 -0
- package/dist/types/components/Badge/Badge.types.d.ts +1 -1
- package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +5 -0
- package/dist/types/components/BottomNavigation/BottomNavigation.test.d.ts +1 -0
- package/dist/types/components/BottomNavigation/BottomNavigation.types.d.ts +41 -0
- package/dist/types/components/BottomNavigation/index.d.ts +2 -0
- package/dist/types/components/Card/Card.types.d.ts +25 -0
- package/dist/types/components/DataList/DataList.d.ts +5 -0
- package/dist/types/components/DataList/DataList.test.d.ts +1 -0
- package/dist/types/components/DataList/DataList.types.d.ts +81 -0
- package/dist/types/components/DataList/index.d.ts +2 -0
- package/dist/types/components/DataTable/DataTable.d.ts +1 -1
- package/dist/types/components/DataTable/DataTable.types.d.ts +10 -0
- package/dist/types/components/Flex/Flex.d.ts +3 -0
- package/dist/types/components/Flex/Flex.test.d.ts +1 -0
- package/dist/types/components/Flex/Flex.types.d.ts +92 -0
- package/dist/types/components/Flex/index.d.ts +2 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.test.d.ts +1 -0
- package/dist/types/components/FloatingActionButton/FloatingActionButton.types.d.ts +48 -0
- package/dist/types/components/FloatingActionButton/index.d.ts +2 -0
- package/dist/types/components/Grid/Grid.d.ts +3 -0
- package/dist/types/components/Grid/Grid.test.d.ts +1 -0
- package/dist/types/components/Grid/Grid.types.d.ts +136 -0
- package/dist/types/components/Grid/index.d.ts +2 -0
- package/dist/types/components/Input/Input.types.d.ts +3 -3
- package/dist/types/components/MobileHeader/MobileHeader.d.ts +5 -0
- package/dist/types/components/MobileHeader/MobileHeader.test.d.ts +1 -0
- package/dist/types/components/MobileHeader/MobileHeader.types.d.ts +49 -0
- package/dist/types/components/MobileHeader/index.d.ts +2 -0
- package/dist/types/components/MobilePicker/MobilePicker.d.ts +6 -0
- package/dist/types/components/MobilePicker/MobilePicker.test.d.ts +1 -0
- package/dist/types/components/MobilePicker/MobilePicker.types.d.ts +90 -0
- package/dist/types/components/MobilePicker/index.d.ts +2 -0
- package/dist/types/components/MobileStepper/MobileStepper.d.ts +5 -0
- package/dist/types/components/MobileStepper/MobileStepper.test.d.ts +1 -0
- package/dist/types/components/MobileStepper/MobileStepper.types.d.ts +28 -0
- package/dist/types/components/MobileStepper/index.d.ts +2 -0
- package/dist/types/components/PinInput/PinInput.d.ts +5 -0
- package/dist/types/components/PinInput/PinInput.test.d.ts +1 -0
- package/dist/types/components/PinInput/PinInput.types.d.ts +29 -0
- package/dist/types/components/PinInput/index.d.ts +2 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.d.ts +5 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.test.d.ts +1 -0
- package/dist/types/components/PullToRefresh/PullToRefresh.types.d.ts +23 -0
- package/dist/types/components/PullToRefresh/index.d.ts +2 -0
- package/dist/types/components/QuantityStepper/QuantityStepper.types.d.ts +18 -1
- package/dist/types/components/SelectBox/SelectBox.types.d.ts +9 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.d.ts +3 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.test.d.ts +1 -0
- package/dist/types/components/SwipeableRow/SwipeableRow.types.d.ts +42 -0
- package/dist/types/components/SwipeableRow/index.d.ts +2 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.d.ts +5 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.test.d.ts +1 -0
- package/dist/types/components/SwipeableTabs/SwipeableTabs.types.d.ts +38 -0
- package/dist/types/components/SwipeableTabs/index.d.ts +2 -0
- package/dist/types/components/WheelPicker/WheelPicker.d.ts +5 -0
- package/dist/types/components/WheelPicker/WheelPicker.test.d.ts +1 -0
- package/dist/types/components/WheelPicker/WheelPicker.types.d.ts +35 -0
- package/dist/types/components/WheelPicker/index.d.ts +2 -0
- package/dist/types/components/common-responsive.d.ts +57 -0
- package/dist/types/index.d.ts +14 -0
- package/package.json +11 -3
|
@@ -27,10 +27,10 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
27
27
|
|
|
28
28
|
const buildClassName = (...classes) => tailwindMerge.twMerge(classes.filter(Boolean));
|
|
29
29
|
|
|
30
|
-
var _path$
|
|
31
|
-
function _extends$
|
|
30
|
+
var _path$j;
|
|
31
|
+
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); }
|
|
32
32
|
var SvgChevronDown = function SvgChevronDown(props) {
|
|
33
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
33
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$j({
|
|
34
34
|
xmlns: "http://www.w3.org/2000/svg",
|
|
35
35
|
width: 24,
|
|
36
36
|
height: 24,
|
|
@@ -41,19 +41,19 @@ var SvgChevronDown = function SvgChevronDown(props) {
|
|
|
41
41
|
strokeWidth: 2,
|
|
42
42
|
className: "lucide lucide-chevron-down-icon lucide-chevron-down",
|
|
43
43
|
viewBox: "0 0 24 24"
|
|
44
|
-
}, props), _path$
|
|
44
|
+
}, props), _path$j || (_path$j = /*#__PURE__*/React__namespace.createElement("path", {
|
|
45
45
|
d: "m6 9 6 6 6-6"
|
|
46
46
|
})));
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
const CONTAINER_CLASS = {
|
|
50
|
-
bordered: 'rounded-lg border border-
|
|
50
|
+
bordered: 'rounded-lg border border-[var(--ui-border)] divide-y divide-[var(--ui-border)] bg-white dark:bg-gray-800 overflow-hidden',
|
|
51
51
|
separated: 'space-y-2',
|
|
52
|
-
plain: 'divide-y divide-
|
|
52
|
+
plain: 'divide-y divide-[var(--ui-border)]',
|
|
53
53
|
};
|
|
54
54
|
const ITEM_CLASS = {
|
|
55
55
|
bordered: '',
|
|
56
|
-
separated: 'rounded-lg border border-
|
|
56
|
+
separated: 'rounded-lg border border-[var(--ui-border)] bg-white dark:bg-gray-800 overflow-hidden',
|
|
57
57
|
plain: '',
|
|
58
58
|
};
|
|
59
59
|
const HEADER_CLASS = 'flex w-full items-center justify-between gap-2 py-3 px-4 text-left text-sm font-medium ' +
|
|
@@ -98,115 +98,6 @@ const Accordion = ({ items, type = 'single', variant = 'bordered', collapsible =
|
|
|
98
98
|
};
|
|
99
99
|
Accordion.displayName = 'Accordion';
|
|
100
100
|
|
|
101
|
-
var _path$h, _path2;
|
|
102
|
-
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); }
|
|
103
|
-
var SvgBadgeCheck = function SvgBadgeCheck(props) {
|
|
104
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$h({
|
|
105
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
106
|
-
width: 24,
|
|
107
|
-
height: 24,
|
|
108
|
-
fill: "none",
|
|
109
|
-
stroke: "currentColor",
|
|
110
|
-
strokeLinecap: "round",
|
|
111
|
-
strokeLinejoin: "round",
|
|
112
|
-
strokeWidth: 2,
|
|
113
|
-
className: "lucide lucide-badge-check-icon lucide-badge-check",
|
|
114
|
-
viewBox: "0 0 24 24"
|
|
115
|
-
}, props), _path$h || (_path$h = /*#__PURE__*/React__namespace.createElement("path", {
|
|
116
|
-
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"
|
|
117
|
-
})), _path2 || (_path2 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
118
|
-
d: "m9 12 2 2 4-4"
|
|
119
|
-
})));
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
var _circle$4, _path$g;
|
|
123
|
-
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); }
|
|
124
|
-
var SvgCircleX = function SvgCircleX(props) {
|
|
125
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$g({
|
|
126
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
127
|
-
width: 24,
|
|
128
|
-
height: 24,
|
|
129
|
-
fill: "none",
|
|
130
|
-
stroke: "currentColor",
|
|
131
|
-
strokeLinecap: "round",
|
|
132
|
-
strokeLinejoin: "round",
|
|
133
|
-
strokeWidth: 2,
|
|
134
|
-
className: "lucide lucide-circle-x-icon lucide-circle-x",
|
|
135
|
-
viewBox: "0 0 24 24"
|
|
136
|
-
}, props), _circle$4 || (_circle$4 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
137
|
-
cx: 12,
|
|
138
|
-
cy: 12,
|
|
139
|
-
r: 10
|
|
140
|
-
})), _path$g || (_path$g = /*#__PURE__*/React__namespace.createElement("path", {
|
|
141
|
-
d: "m15 9-6 6M9 9l6 6"
|
|
142
|
-
})));
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
var _circle$3, _path$f;
|
|
146
|
-
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); }
|
|
147
|
-
var SvgCircleAlert = function SvgCircleAlert(props) {
|
|
148
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$f({
|
|
149
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
150
|
-
width: 24,
|
|
151
|
-
height: 24,
|
|
152
|
-
fill: "none",
|
|
153
|
-
stroke: "currentColor",
|
|
154
|
-
strokeLinecap: "round",
|
|
155
|
-
strokeLinejoin: "round",
|
|
156
|
-
strokeWidth: 2,
|
|
157
|
-
className: "lucide lucide-circle-alert-icon lucide-circle-alert",
|
|
158
|
-
viewBox: "0 0 24 24"
|
|
159
|
-
}, props), _circle$3 || (_circle$3 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
160
|
-
cx: 12,
|
|
161
|
-
cy: 12,
|
|
162
|
-
r: 10
|
|
163
|
-
})), _path$f || (_path$f = /*#__PURE__*/React__namespace.createElement("path", {
|
|
164
|
-
d: "M12 8v4M12 16h.01"
|
|
165
|
-
})));
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
var _circle$2, _path$e;
|
|
169
|
-
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); }
|
|
170
|
-
var SvgInfo = function SvgInfo(props) {
|
|
171
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$e({
|
|
172
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
173
|
-
width: 24,
|
|
174
|
-
height: 24,
|
|
175
|
-
fill: "none",
|
|
176
|
-
stroke: "currentColor",
|
|
177
|
-
strokeLinecap: "round",
|
|
178
|
-
strokeLinejoin: "round",
|
|
179
|
-
strokeWidth: 2,
|
|
180
|
-
className: "lucide lucide-info-icon lucide-info",
|
|
181
|
-
viewBox: "0 0 24 24"
|
|
182
|
-
}, props), _circle$2 || (_circle$2 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
183
|
-
cx: 12,
|
|
184
|
-
cy: 12,
|
|
185
|
-
r: 10
|
|
186
|
-
})), _path$e || (_path$e = /*#__PURE__*/React__namespace.createElement("path", {
|
|
187
|
-
d: "M12 16v-4M12 8h.01"
|
|
188
|
-
})));
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
var _path$d;
|
|
192
|
-
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); }
|
|
193
|
-
var SvgX = function SvgX(props) {
|
|
194
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$d({
|
|
195
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
196
|
-
width: 24,
|
|
197
|
-
height: 24,
|
|
198
|
-
fill: "none",
|
|
199
|
-
stroke: "currentColor",
|
|
200
|
-
strokeLinecap: "round",
|
|
201
|
-
strokeLinejoin: "round",
|
|
202
|
-
strokeWidth: 2,
|
|
203
|
-
className: "lucide lucide-x-icon lucide-x",
|
|
204
|
-
viewBox: "0 0 24 24"
|
|
205
|
-
}, props), _path$d || (_path$d = /*#__PURE__*/React__namespace.createElement("path", {
|
|
206
|
-
d: "M18 6 6 18M6 6l12 12"
|
|
207
|
-
})));
|
|
208
|
-
};
|
|
209
|
-
|
|
210
101
|
const loaderSizeMap = {
|
|
211
102
|
xs: 'size-4',
|
|
212
103
|
sm: 'size-6',
|
|
@@ -273,8 +164,8 @@ const THEMED_BTN_CLASS = {
|
|
|
273
164
|
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)]',
|
|
274
165
|
},
|
|
275
166
|
secondary: {
|
|
276
|
-
default: 'text-gray-700 bg-white border border-
|
|
277
|
-
outlined: 'text-gray-700 hover:text-white border border-
|
|
167
|
+
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',
|
|
168
|
+
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)]',
|
|
278
169
|
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',
|
|
279
170
|
},
|
|
280
171
|
success: {
|
|
@@ -366,52 +257,132 @@ const Button = React.forwardRef(({ as, type, ...props }, ref) => {
|
|
|
366
257
|
});
|
|
367
258
|
Button.displayName = 'Button';
|
|
368
259
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
260
|
+
var _path$i;
|
|
261
|
+
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); }
|
|
262
|
+
var SvgChevronLeft = function SvgChevronLeft(props) {
|
|
263
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$i({
|
|
264
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
265
|
+
width: 24,
|
|
266
|
+
height: 24,
|
|
267
|
+
fill: "none",
|
|
268
|
+
stroke: "currentColor",
|
|
269
|
+
strokeLinecap: "round",
|
|
270
|
+
strokeLinejoin: "round",
|
|
271
|
+
strokeWidth: 2,
|
|
272
|
+
className: "lucide lucide-chevron-left-icon lucide-chevron-left",
|
|
273
|
+
viewBox: "0 0 24 24"
|
|
274
|
+
}, props), _path$i || (_path$i = /*#__PURE__*/React__namespace.createElement("path", {
|
|
275
|
+
d: "m15 18-6-6 6-6"
|
|
276
|
+
})));
|
|
374
277
|
};
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
278
|
+
|
|
279
|
+
var _path$h;
|
|
280
|
+
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); }
|
|
281
|
+
var SvgX = function SvgX(props) {
|
|
282
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$h({
|
|
283
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
284
|
+
width: 24,
|
|
285
|
+
height: 24,
|
|
286
|
+
fill: "none",
|
|
287
|
+
stroke: "currentColor",
|
|
288
|
+
strokeLinecap: "round",
|
|
289
|
+
strokeLinejoin: "round",
|
|
290
|
+
strokeWidth: 2,
|
|
291
|
+
className: "lucide lucide-x-icon lucide-x",
|
|
292
|
+
viewBox: "0 0 24 24"
|
|
293
|
+
}, props), _path$h || (_path$h = /*#__PURE__*/React__namespace.createElement("path", {
|
|
294
|
+
d: "M18 6 6 18M6 6l12 12"
|
|
295
|
+
})));
|
|
380
296
|
};
|
|
381
|
-
const Alert = React.forwardRef((props, ref) => {
|
|
382
|
-
const { type = 'info', className, message, children, removable = false, onRemove, icon, title, ...restProps } = props;
|
|
383
|
-
const DefaultIcon = AlertTypeIconMap[type] || SvgInfo;
|
|
384
|
-
const iconNode = icon !== undefined ? (icon) : (jsxRuntime.jsx(DefaultIcon, { className: "size-5 shrink-0", "data-testid": `alert-${type}-icon` }));
|
|
385
|
-
return (jsxRuntime.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: [jsxRuntime.jsxs("span", { className: "inline-flex items-start gap-2 min-w-0", children: [iconNode && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex mt-0.5", children: iconNode }), jsxRuntime.jsxs("span", { className: "inline-flex flex-col gap-0.5 min-w-0", children: [title && jsxRuntime.jsx("span", { className: "font-semibold", children: title }), jsxRuntime.jsx("span", { className: "inline-flex items-center", children: message !== null && message !== void 0 ? message : children })] })] }), removable && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
386
|
-
});
|
|
387
|
-
Alert.displayName = 'Alert';
|
|
388
297
|
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
298
|
+
const alignmentMap = {
|
|
299
|
+
center: 'items-center justify-center h-full',
|
|
300
|
+
start: 'justify-start h-full',
|
|
301
|
+
end: 'justify-end h-full',
|
|
302
|
+
top: 'items-start justify-center w-full',
|
|
303
|
+
bottom: 'items-end justify-center h-full',
|
|
395
304
|
};
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
305
|
+
const panelAlignmentMap = {
|
|
306
|
+
center: 'data-[closed]:scale-95 rounded-2xl',
|
|
307
|
+
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
308
|
+
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
309
|
+
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
310
|
+
bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh]',
|
|
399
311
|
};
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
312
|
+
const panelSizeMap = {
|
|
313
|
+
xs: 'max-w-xs',
|
|
314
|
+
sm: 'max-w-sm',
|
|
315
|
+
md: 'max-w-md',
|
|
316
|
+
lg: 'max-w-lg',
|
|
317
|
+
xl: 'max-w-xl',
|
|
318
|
+
'2xl': 'max-w-2xl',
|
|
319
|
+
full: 'w-full',
|
|
320
|
+
};
|
|
321
|
+
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, }) => {
|
|
322
|
+
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
323
|
+
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
324
|
+
const [viewportHeight, setViewportHeight] = React.useState(null);
|
|
325
|
+
React.useEffect(() => {
|
|
326
|
+
if (!isOpen) {
|
|
327
|
+
setViewportHeight(null);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const updateHeight = () => {
|
|
331
|
+
if (typeof window !== 'undefined' && window.visualViewport) {
|
|
332
|
+
setViewportHeight(window.visualViewport.height);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
updateHeight();
|
|
336
|
+
const vv = typeof window !== 'undefined' ? window.visualViewport : null;
|
|
337
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('resize', updateHeight);
|
|
338
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('scroll', updateHeight);
|
|
339
|
+
return () => {
|
|
340
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('resize', updateHeight);
|
|
341
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('scroll', updateHeight);
|
|
342
|
+
};
|
|
343
|
+
}, [isOpen]);
|
|
344
|
+
const handleDialogClose = () => {
|
|
345
|
+
if (closeOnOutsideClick) {
|
|
346
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
return (jsxRuntime.jsxs(react.Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsxRuntime.jsx(react.DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsxRuntime.jsx("div", { className: "fixed left-0 top-0 w-full", style: { height: viewportHeight ? `${viewportHeight}px` : '100dvh' }, children: jsxRuntime.jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxRuntime.jsxs(react.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 && (jsxRuntime.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 && (jsxRuntime.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: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsxRuntime.jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsxRuntime.jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsxRuntime.jsx(react.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 && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4" }) }))] }), description && (jsxRuntime.jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsxRuntime.jsx("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass), children: children }), footer && (jsxRuntime.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 }))] }) }) })] }));
|
|
350
|
+
};
|
|
351
|
+
Drawer.displayName = 'Drawer';
|
|
410
352
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
var
|
|
414
|
-
|
|
353
|
+
function ActionSheet({ isOpen, onClose, title, description, actions, showCancelButton = true, cancelLabel = 'Cancel', onCancel, closeOnBackdropClick = true, dragHandle = true, panelClass = '', containerClass = '', }) {
|
|
354
|
+
const handleItemClick = (action) => {
|
|
355
|
+
var _a;
|
|
356
|
+
if (action.disabled)
|
|
357
|
+
return;
|
|
358
|
+
(_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action);
|
|
359
|
+
onClose();
|
|
360
|
+
};
|
|
361
|
+
const handleCancelClick = () => {
|
|
362
|
+
onCancel === null || onCancel === void 0 ? void 0 : onCancel();
|
|
363
|
+
onClose();
|
|
364
|
+
};
|
|
365
|
+
return (jsxRuntime.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: jsxRuntime.jsxs("div", { className: buildClassName('space-y-4 py-1', containerClass), "data-testid": "action-sheet", children: [(title || description) && (jsxRuntime.jsxs("div", { className: "text-center px-4 pb-2 border-b border-[var(--ui-border-muted)]", children: [title && (jsxRuntime.jsx("h3", { className: "text-sm font-bold text-gray-900 dark:text-white truncate", children: title })), description && (jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate", children: description }))] })), jsxRuntime.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) => {
|
|
366
|
+
const isDanger = action.theme === 'danger';
|
|
367
|
+
const isPrimary = action.theme === 'primary';
|
|
368
|
+
return (jsxRuntime.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 &&
|
|
369
|
+
(isDanger
|
|
370
|
+
? 'hover:bg-red-50 dark:hover:bg-red-950/40 text-red-600 dark:text-red-400 font-semibold'
|
|
371
|
+
: isPrimary
|
|
372
|
+
? 'hover:bg-blue-50 dark:hover:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
373
|
+
: '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 && (jsxRuntime.jsx("span", { className: buildClassName('shrink-0 text-base transition-colors', isDanger
|
|
374
|
+
? 'text-red-500 dark:text-red-400'
|
|
375
|
+
: isPrimary
|
|
376
|
+
? 'text-blue-500 dark:text-blue-400'
|
|
377
|
+
: 'text-gray-500 dark:text-gray-400 group-hover:text-gray-700 dark:group-hover:text-gray-200'), children: action.icon })), jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntime.jsx("div", { className: "text-sm truncate", children: action.label }), action.description && (jsxRuntime.jsx("div", { className: "text-xs text-gray-400 dark:text-gray-500 truncate font-normal mt-0.5", children: action.description }))] })] }, action.id));
|
|
378
|
+
}) }), showCancelButton && (jsxRuntime.jsx("div", { className: "pt-1", children: jsxRuntime.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 }) }))] }) }));
|
|
379
|
+
}
|
|
380
|
+
ActionSheet.displayName = 'ActionSheet';
|
|
381
|
+
|
|
382
|
+
var _path$g, _path2;
|
|
383
|
+
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); }
|
|
384
|
+
var SvgBadgeCheck = function SvgBadgeCheck(props) {
|
|
385
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$g({
|
|
415
386
|
xmlns: "http://www.w3.org/2000/svg",
|
|
416
387
|
width: 24,
|
|
417
388
|
height: 24,
|
|
@@ -420,17 +391,19 @@ var SvgTriangleAlert = function SvgTriangleAlert(props) {
|
|
|
420
391
|
strokeLinecap: "round",
|
|
421
392
|
strokeLinejoin: "round",
|
|
422
393
|
strokeWidth: 2,
|
|
423
|
-
className: "lucide lucide-
|
|
394
|
+
className: "lucide lucide-badge-check-icon lucide-badge-check",
|
|
424
395
|
viewBox: "0 0 24 24"
|
|
425
|
-
}, props), _path$
|
|
426
|
-
d: "
|
|
396
|
+
}, props), _path$g || (_path$g = /*#__PURE__*/React__namespace.createElement("path", {
|
|
397
|
+
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"
|
|
398
|
+
})), _path2 || (_path2 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
399
|
+
d: "m9 12 2 2 4-4"
|
|
427
400
|
})));
|
|
428
401
|
};
|
|
429
402
|
|
|
430
|
-
var _circle$
|
|
431
|
-
function _extends$
|
|
432
|
-
var
|
|
433
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
403
|
+
var _circle$5, _path$f;
|
|
404
|
+
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); }
|
|
405
|
+
var SvgCircleX = function SvgCircleX(props) {
|
|
406
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$f({
|
|
434
407
|
xmlns: "http://www.w3.org/2000/svg",
|
|
435
408
|
width: 24,
|
|
436
409
|
height: 24,
|
|
@@ -439,28 +412,159 @@ var SvgCircleCheck = function SvgCircleCheck(props) {
|
|
|
439
412
|
strokeLinecap: "round",
|
|
440
413
|
strokeLinejoin: "round",
|
|
441
414
|
strokeWidth: 2,
|
|
442
|
-
className: "lucide lucide-circle-
|
|
415
|
+
className: "lucide lucide-circle-x-icon lucide-circle-x",
|
|
443
416
|
viewBox: "0 0 24 24"
|
|
444
|
-
}, props), _circle$
|
|
417
|
+
}, props), _circle$5 || (_circle$5 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
445
418
|
cx: 12,
|
|
446
419
|
cy: 12,
|
|
447
420
|
r: 10
|
|
448
|
-
})), _path$
|
|
449
|
-
d: "
|
|
421
|
+
})), _path$f || (_path$f = /*#__PURE__*/React__namespace.createElement("path", {
|
|
422
|
+
d: "m15 9-6 6M9 9l6 6"
|
|
450
423
|
})));
|
|
451
424
|
};
|
|
452
425
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
426
|
+
var _circle$4, _path$e;
|
|
427
|
+
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); }
|
|
428
|
+
var SvgCircleAlert = function SvgCircleAlert(props) {
|
|
429
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$e({
|
|
430
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
431
|
+
width: 24,
|
|
432
|
+
height: 24,
|
|
433
|
+
fill: "none",
|
|
434
|
+
stroke: "currentColor",
|
|
435
|
+
strokeLinecap: "round",
|
|
436
|
+
strokeLinejoin: "round",
|
|
437
|
+
strokeWidth: 2,
|
|
438
|
+
className: "lucide lucide-circle-alert-icon lucide-circle-alert",
|
|
439
|
+
viewBox: "0 0 24 24"
|
|
440
|
+
}, props), _circle$4 || (_circle$4 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
441
|
+
cx: 12,
|
|
442
|
+
cy: 12,
|
|
443
|
+
r: 10
|
|
444
|
+
})), _path$e || (_path$e = /*#__PURE__*/React__namespace.createElement("path", {
|
|
445
|
+
d: "M12 8v4M12 16h.01"
|
|
446
|
+
})));
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
var _circle$3, _path$d;
|
|
450
|
+
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); }
|
|
451
|
+
var SvgInfo = function SvgInfo(props) {
|
|
452
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$d({
|
|
453
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
454
|
+
width: 24,
|
|
455
|
+
height: 24,
|
|
456
|
+
fill: "none",
|
|
457
|
+
stroke: "currentColor",
|
|
458
|
+
strokeLinecap: "round",
|
|
459
|
+
strokeLinejoin: "round",
|
|
460
|
+
strokeWidth: 2,
|
|
461
|
+
className: "lucide lucide-info-icon lucide-info",
|
|
462
|
+
viewBox: "0 0 24 24"
|
|
463
|
+
}, props), _circle$3 || (_circle$3 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
464
|
+
cx: 12,
|
|
465
|
+
cy: 12,
|
|
466
|
+
r: 10
|
|
467
|
+
})), _path$d || (_path$d = /*#__PURE__*/React__namespace.createElement("path", {
|
|
468
|
+
d: "M12 16v-4M12 8h.01"
|
|
469
|
+
})));
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const AlertTypeIconMap = {
|
|
473
|
+
success: SvgBadgeCheck,
|
|
474
|
+
danger: SvgCircleX,
|
|
475
|
+
warning: SvgCircleAlert,
|
|
476
|
+
info: SvgInfo,
|
|
477
|
+
};
|
|
478
|
+
const TypeClassMap$1 = {
|
|
479
|
+
success: 'bg-[var(--ui-success-light)] ring-[var(--ui-success-ring-subtle)] text-[var(--ui-success-text)]',
|
|
480
|
+
danger: 'bg-[var(--ui-danger-light)] ring-[var(--ui-danger-ring-subtle)] text-[var(--ui-danger-text)]',
|
|
481
|
+
warning: 'bg-[var(--ui-warning-light)] ring-[var(--ui-warning-ring-subtle)] text-[var(--ui-warning-text)]',
|
|
482
|
+
info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',
|
|
483
|
+
};
|
|
484
|
+
const Alert = React.forwardRef((props, ref) => {
|
|
485
|
+
const { type = 'info', className, message, children, removable = false, onRemove, icon, title, ...restProps } = props;
|
|
486
|
+
const DefaultIcon = AlertTypeIconMap[type] || SvgInfo;
|
|
487
|
+
const iconNode = icon !== undefined ? (icon) : (jsxRuntime.jsx(DefaultIcon, { className: "size-5 shrink-0", "data-testid": `alert-${type}-icon` }));
|
|
488
|
+
return (jsxRuntime.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: [jsxRuntime.jsxs("span", { className: "inline-flex items-start gap-2 min-w-0", children: [iconNode && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex mt-0.5", children: iconNode }), jsxRuntime.jsxs("span", { className: "inline-flex flex-col gap-0.5 min-w-0", children: [title && jsxRuntime.jsx("span", { className: "font-semibold", children: title }), jsxRuntime.jsx("span", { className: "inline-flex items-center", children: message !== null && message !== void 0 ? message : children })] })] }), removable && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4.5", "data-testid": "alert-remove-icon" }) }))] }));
|
|
489
|
+
});
|
|
490
|
+
Alert.displayName = 'Alert';
|
|
491
|
+
|
|
492
|
+
const ThemeClassMap = {
|
|
493
|
+
success: 'bg-[var(--ui-success-light)] text-[var(--ui-success-text)] ring-[var(--ui-success-ring-subtle)]',
|
|
494
|
+
danger: 'bg-[var(--ui-danger-light)] text-[var(--ui-danger-text)] ring-[var(--ui-danger-ring-subtle)]',
|
|
495
|
+
warning: 'bg-[var(--ui-warning-light)] text-[var(--ui-warning-text)] ring-[var(--ui-warning-ring-subtle)]',
|
|
496
|
+
info: 'bg-[var(--ui-info-light)] text-[var(--ui-info-text)] ring-[var(--ui-info-ring-subtle)]',
|
|
497
|
+
primary: 'bg-[var(--ui-info-light)] text-[var(--ui-info-text)] ring-[var(--ui-info-ring-subtle)]',
|
|
498
|
+
secondary: 'bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 ring-[var(--ui-secondary-ring-subtle)]',
|
|
499
|
+
};
|
|
500
|
+
const SIZE_CLASS$1 = {
|
|
501
|
+
sm: 'text-xs py-0.5 px-2',
|
|
502
|
+
md: 'text-xs py-1 px-3',
|
|
503
|
+
};
|
|
504
|
+
const Badge = React.forwardRef((props, ref) => {
|
|
505
|
+
const { theme = 'info', className, children, removable = false, rounded = false, onRemove, size = 'md', icon, ...restProps } = props;
|
|
506
|
+
return (jsxRuntime.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 && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex", children: icon }), children, removable && (jsxRuntime.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) => {
|
|
507
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
508
|
+
e.preventDefault();
|
|
509
|
+
onRemove === null || onRemove === void 0 ? void 0 : onRemove();
|
|
510
|
+
}
|
|
511
|
+
} }))] }));
|
|
512
|
+
});
|
|
513
|
+
Badge.displayName = 'Badge';
|
|
514
|
+
|
|
515
|
+
var _path$c;
|
|
516
|
+
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); }
|
|
517
|
+
var SvgTriangleAlert = function SvgTriangleAlert(props) {
|
|
518
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$c({
|
|
519
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
520
|
+
width: 24,
|
|
521
|
+
height: 24,
|
|
522
|
+
fill: "none",
|
|
523
|
+
stroke: "currentColor",
|
|
524
|
+
strokeLinecap: "round",
|
|
525
|
+
strokeLinejoin: "round",
|
|
526
|
+
strokeWidth: 2,
|
|
527
|
+
className: "lucide lucide-triangle-alert-icon lucide-triangle-alert",
|
|
528
|
+
viewBox: "0 0 24 24"
|
|
529
|
+
}, props), _path$c || (_path$c = /*#__PURE__*/React__namespace.createElement("path", {
|
|
530
|
+
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"
|
|
531
|
+
})));
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
var _circle$2, _path$b;
|
|
535
|
+
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); }
|
|
536
|
+
var SvgCircleCheck = function SvgCircleCheck(props) {
|
|
537
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$b({
|
|
538
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
539
|
+
width: 24,
|
|
540
|
+
height: 24,
|
|
541
|
+
fill: "none",
|
|
542
|
+
stroke: "currentColor",
|
|
543
|
+
strokeLinecap: "round",
|
|
544
|
+
strokeLinejoin: "round",
|
|
545
|
+
strokeWidth: 2,
|
|
546
|
+
className: "lucide lucide-circle-check-icon lucide-circle-check",
|
|
547
|
+
viewBox: "0 0 24 24"
|
|
548
|
+
}, props), _circle$2 || (_circle$2 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
549
|
+
cx: 12,
|
|
550
|
+
cy: 12,
|
|
551
|
+
r: 10
|
|
552
|
+
})), _path$b || (_path$b = /*#__PURE__*/React__namespace.createElement("path", {
|
|
553
|
+
d: "m9 12 2 2 4-4"
|
|
554
|
+
})));
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const sizeMap = {
|
|
558
|
+
xs: 'size-4',
|
|
559
|
+
sm: 'size-5',
|
|
560
|
+
md: 'size-6',
|
|
561
|
+
lg: 'size-8',
|
|
562
|
+
xl: 'size-10',
|
|
563
|
+
};
|
|
564
|
+
const IconMap = {
|
|
565
|
+
info: SvgInfo,
|
|
566
|
+
error: SvgCircleX,
|
|
567
|
+
success: SvgCircleCheck,
|
|
464
568
|
warning: SvgTriangleAlert,
|
|
465
569
|
};
|
|
466
570
|
const TypeClassMap = {
|
|
@@ -529,6 +633,51 @@ const BodyText = React.forwardRef((props, ref) => {
|
|
|
529
633
|
});
|
|
530
634
|
BodyText.displayName = 'BodyText';
|
|
531
635
|
|
|
636
|
+
function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
|
|
637
|
+
const handleTabClick = (item) => {
|
|
638
|
+
var _a;
|
|
639
|
+
if (item.disabled)
|
|
640
|
+
return;
|
|
641
|
+
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
|
|
642
|
+
onChange(item.id);
|
|
643
|
+
};
|
|
644
|
+
const themeStyles = {
|
|
645
|
+
light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
|
|
646
|
+
dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
|
|
647
|
+
primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
|
|
648
|
+
}[theme];
|
|
649
|
+
return (jsxRuntime.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) => {
|
|
650
|
+
const isActive = item.id === activeId;
|
|
651
|
+
const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
|
|
652
|
+
const activeItemColor = {
|
|
653
|
+
light: 'text-blue-600 dark:text-blue-400 font-bold',
|
|
654
|
+
dark: 'text-white font-bold',
|
|
655
|
+
primary: 'text-white font-bold',
|
|
656
|
+
}[theme];
|
|
657
|
+
const inactiveItemColor = {
|
|
658
|
+
light: 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',
|
|
659
|
+
dark: 'text-gray-400 hover:text-gray-200 font-medium',
|
|
660
|
+
primary: 'text-blue-200 hover:text-white font-medium',
|
|
661
|
+
}[theme];
|
|
662
|
+
const pillActiveStyles = {
|
|
663
|
+
light: 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',
|
|
664
|
+
dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',
|
|
665
|
+
primary: 'bg-white/25 text-white shadow-xs scale-105',
|
|
666
|
+
}[theme];
|
|
667
|
+
const badgeColor = {
|
|
668
|
+
danger: 'bg-red-500 text-white',
|
|
669
|
+
info: 'bg-blue-500 text-white',
|
|
670
|
+
success: 'bg-emerald-500 text-white',
|
|
671
|
+
}[item.badgeVariant || 'danger'];
|
|
672
|
+
return (jsxRuntime.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 && (jsxRuntime.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') })), jsxRuntime.jsxs("div", { className: buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
|
|
673
|
+
? buildClassName('px-4 py-1 rounded-full', isActive
|
|
674
|
+
? pillActiveStyles
|
|
675
|
+
: 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
|
|
676
|
+
: 'px-1 py-0.5'), children: [jsxRuntime.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 && (jsxRuntime.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 && (jsxRuntime.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 && (jsxRuntime.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));
|
|
677
|
+
}) }));
|
|
678
|
+
}
|
|
679
|
+
BottomNavigation.displayName = 'BottomNavigation';
|
|
680
|
+
|
|
532
681
|
var _path$a;
|
|
533
682
|
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); }
|
|
534
683
|
var SvgSlash = function SvgSlash(props) {
|
|
@@ -684,10 +833,10 @@ const ButtonGroup = ({ children, orientation = 'horizontal', theme = 'secondary'
|
|
|
684
833
|
(isVertical
|
|
685
834
|
? resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
686
835
|
? 'border-t border-white/25 dark:border-white/20'
|
|
687
|
-
: 'border-t border-
|
|
836
|
+
: 'border-t border-[var(--ui-border)]'
|
|
688
837
|
: resolvedTheme === 'primary' || resolvedTheme === 'danger'
|
|
689
838
|
? 'border-l border-white/25 dark:border-white/20'
|
|
690
|
-
: 'border-l border-
|
|
839
|
+
: 'border-l border-[var(--ui-border)]'),
|
|
691
840
|
], fullWidth && 'flex-1'),
|
|
692
841
|
});
|
|
693
842
|
}) }));
|
|
@@ -708,27 +857,33 @@ const ASPECT_RATIO_CLASS = {
|
|
|
708
857
|
video: 'aspect-video',
|
|
709
858
|
wide: 'aspect-[21/9]',
|
|
710
859
|
};
|
|
860
|
+
function ChevronRightIcon$1({ className = 'size-4' }) {
|
|
861
|
+
return (jsxRuntime.jsx("svg", { className: className, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }));
|
|
862
|
+
}
|
|
711
863
|
const Card = React.forwardRef(({ as, ...props }, ref) => {
|
|
712
|
-
const { variant = 'outlined', radius = 'xl', hoverable = false, clickable = false, selected = false, bordered = true, compact = false, zeroPadding = false, ...rest } = props;
|
|
864
|
+
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;
|
|
713
865
|
const Component = as || 'div';
|
|
714
866
|
const { className, ...cleanRest } = rest;
|
|
867
|
+
const isClickable = clickable || Boolean(onClick);
|
|
715
868
|
const isOutlined = variant === 'outlined' && bordered;
|
|
716
869
|
const isElevated = variant === 'elevated';
|
|
717
870
|
const isFilled = variant === 'filled';
|
|
718
871
|
const isGhost = variant === 'ghost';
|
|
719
|
-
const classes = buildClassName('block transition-all duration-
|
|
872
|
+
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',
|
|
720
873
|
// Surface variants
|
|
721
874
|
isOutlined && 'bg-white dark:bg-gray-900 border border-[var(--ui-border)]', isElevated &&
|
|
722
|
-
'bg-white dark:bg-gray-900 border border-
|
|
723
|
-
// Hoverable & Clickable states
|
|
724
|
-
hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80',
|
|
725
|
-
|
|
875
|
+
'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',
|
|
876
|
+
// Hoverable & Clickable mobile/web touch states
|
|
877
|
+
hoverable && 'hover:bg-gray-100/80 dark:hover:bg-gray-800/80', isClickable &&
|
|
878
|
+
'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);
|
|
879
|
+
const hasHeaderRow = title || subtitle || leading || trailing || badge || showChevron;
|
|
880
|
+
return (jsxRuntime.jsxs(Component, { ref: ref, className: classes, onClick: onClick, ...cleanRest, children: [hasHeaderRow && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center gap-3 w-full min-w-0', children && 'mb-3'), children: [leading && jsxRuntime.jsx("div", { className: "shrink-0 flex items-center justify-center", children: leading }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 text-left", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [title && (jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white truncate", children: title })), badge] }), subtitle && (jsxRuntime.jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate", children: subtitle }))] }), (trailing || showChevron) && (jsxRuntime.jsxs("div", { className: "shrink-0 flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400", children: [trailing, showChevron && jsxRuntime.jsx(ChevronRightIcon$1, { className: "size-4 text-gray-400" })] }))] })), children] }));
|
|
726
881
|
});
|
|
727
|
-
const CardHeader = ({ className, bordered = false, children, ...props }) => (jsxRuntime.jsx("div", { className: buildClassName('flex items-center justify-between gap-4 mb-4', bordered && 'pb-4 border-b border-
|
|
882
|
+
const CardHeader = ({ className, bordered = false, children, ...props }) => (jsxRuntime.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 }));
|
|
728
883
|
const CardTitle = ({ className, as: Component = 'h3', children, ...props }) => (jsxRuntime.jsx(Component, { className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white tracking-tight', className), ...props, children: children }));
|
|
729
884
|
const CardDescription = ({ className, children, ...props }) => (jsxRuntime.jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal mt-1', className), ...props, children: children }));
|
|
730
885
|
const CardContent = ({ className, children, ...props }) => (jsxRuntime.jsx("div", { className: buildClassName('space-y-3', className), ...props, children: children }));
|
|
731
|
-
const CardFooter = ({ className, bordered = false, children, ...props }) => (jsxRuntime.jsx("div", { className: buildClassName('flex items-center justify-end gap-3 mt-4', bordered && 'pt-4 border-t border-
|
|
886
|
+
const CardFooter = ({ className, bordered = false, children, ...props }) => (jsxRuntime.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 }));
|
|
732
887
|
const CardMedia = ({ className, aspectRatio = 'video', alt = '', ...props }) => (jsxRuntime.jsx("div", { className: buildClassName('overflow-hidden -mx-5 -mt-5 mb-4 sm:-mx-6 sm:-mt-6', className), children: jsxRuntime.jsx("img", { alt: alt, className: buildClassName('w-full object-cover', ASPECT_RATIO_CLASS[aspectRatio] || ASPECT_RATIO_CLASS.video), ...props }) }));
|
|
733
888
|
Card.Header = CardHeader;
|
|
734
889
|
Card.Title = CardTitle;
|
|
@@ -748,19 +903,19 @@ Label.displayName = 'Label';
|
|
|
748
903
|
const sizeStyles = {
|
|
749
904
|
sm: {
|
|
750
905
|
box: 'size-3.5',
|
|
751
|
-
svg: '
|
|
906
|
+
svg: 'size-2.75',
|
|
752
907
|
text: 'text-xs',
|
|
753
908
|
subtext: 'text-[11px]',
|
|
754
909
|
},
|
|
755
910
|
md: {
|
|
756
911
|
box: 'size-4.5',
|
|
757
|
-
svg: '
|
|
912
|
+
svg: 'size-3.5',
|
|
758
913
|
text: 'text-sm',
|
|
759
914
|
subtext: 'text-xs',
|
|
760
915
|
},
|
|
761
916
|
lg: {
|
|
762
917
|
box: 'size-5.5',
|
|
763
|
-
svg: '
|
|
918
|
+
svg: 'size-4.25',
|
|
764
919
|
text: 'text-base',
|
|
765
920
|
subtext: 'text-sm',
|
|
766
921
|
},
|
|
@@ -781,19 +936,19 @@ const Checkbox = React.forwardRef((props, ref) => {
|
|
|
781
936
|
const isCard = variant === 'card';
|
|
782
937
|
return (jsxRuntime.jsxs("div", { className: buildClassName(wrapperClass), children: [jsxRuntime.jsx("div", { className: buildClassName(isCard
|
|
783
938
|
? 'rounded-xl border p-3.5 transition-all duration-150 relative'
|
|
784
|
-
: 'flex items-
|
|
939
|
+
: 'flex items-center', isCard &&
|
|
785
940
|
(disabled
|
|
786
|
-
? 'border-
|
|
941
|
+
? 'border-[var(--ui-border-muted)] bg-gray-50/50 dark:bg-gray-900/40 opacity-70'
|
|
787
942
|
: checked || indeterminate
|
|
788
943
|
? 'border-blue-500/80 bg-blue-50/30 dark:bg-blue-950/20 dark:border-blue-500/60 shadow-xs'
|
|
789
|
-
: 'border-
|
|
790
|
-
? 'border-
|
|
791
|
-
: 'bg-white dark:bg-gray-700 border-
|
|
792
|
-
'!bg-blue-600 !border-blue-600 dark:!bg-blue-600 dark:!border-blue-600', className) }), !indeterminate && (jsxRuntime.jsx("span", { className: buildClassName('absolute text-white pointer-events-none transition-opacity
|
|
944
|
+
: 'border-[var(--ui-border)] bg-white dark:bg-gray-900 hover:border-gray-300 dark:hover:border-gray-700 shadow-2xs'), containerClass), children: jsxRuntime.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: [jsxRuntime.jsxs("div", { className: "relative inline-flex items-center justify-center shrink-0", children: [jsxRuntime.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
|
|
945
|
+
? 'border-[var(--ui-border-muted)] bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
946
|
+
: 'bg-white dark:bg-gray-700 border-[var(--ui-border)] hover:border-gray-400 dark:hover:border-gray-500', indeterminate &&
|
|
947
|
+
'!bg-blue-600 !border-blue-600 dark:!bg-blue-600 dark:!border-blue-600', className) }), !indeterminate && (jsxRuntime.jsx("span", { className: buildClassName('absolute inset-0 flex items-center justify-center text-white pointer-events-none transition-opacity', checked !== undefined
|
|
793
948
|
? checked
|
|
794
949
|
? 'opacity-100'
|
|
795
950
|
: 'opacity-0'
|
|
796
|
-
: 'opacity-0 peer-checked:opacity-100'), children: jsxRuntime.jsx("svg", {
|
|
951
|
+
: 'opacity-0 peer-checked:opacity-100'), children: jsxRuntime.jsx("svg", { className: currentSize.svg, viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.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 && (jsxRuntime.jsx("span", { className: "absolute inset-0 flex items-center justify-center text-white pointer-events-none opacity-100 z-10", children: jsxRuntime.jsx("svg", { className: currentSize.svg, viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M4 10a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1z", clipRule: "evenodd" }) }) }))] }), (label || description) && (jsxRuntime.jsxs("div", { className: "ml-2.5 flex flex-col justify-center min-w-0 flex-1", children: [label && (jsxRuntime.jsx(Label, { htmlFor: checkboxId, className: buildClassName(disabled
|
|
797
952
|
? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
|
|
798
953
|
: 'cursor-pointer text-gray-800 dark:text-gray-200 font-medium', currentSize.text, labelClass), children: label })), description && (jsxRuntime.jsx("span", { className: buildClassName('mt-0.5 text-gray-500 dark:text-gray-400 font-normal leading-normal', currentSize.subtext), children: description }))] }))] }) }), (error || helperText) && (jsxRuntime.jsx("div", { className: "mt-1.5 ml-0.5", children: error ? (jsxRuntime.jsx(TextContent, { error: true, small: true, children: error })) : (jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText })) }))] }));
|
|
799
954
|
});
|
|
@@ -862,7 +1017,7 @@ const CheckboxGroup = (props) => {
|
|
|
862
1017
|
: inline
|
|
863
1018
|
? 'flex flex-wrap gap-3'
|
|
864
1019
|
: 'flex flex-col gap-3';
|
|
865
|
-
return (jsxRuntime.jsxs("div", { className: buildClassName('mb-3 space-y-3', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, children: label }), labelHint && (jsxRuntime.jsx(BodyText, { muted: true, small: true, children: labelHint }))] })), showSelectAll && items.length > 0 && (jsxRuntime.jsx("div", { className: "pb-1 border-b border-
|
|
1020
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('mb-3 space-y-3', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, children: label }), labelHint && (jsxRuntime.jsx(BodyText, { muted: true, small: true, children: labelHint }))] })), showSelectAll && items.length > 0 && (jsxRuntime.jsx("div", { className: "pb-1 border-b border-[var(--ui-border)]", children: jsxRuntime.jsx(Checkbox, { id: `${groupId}-select-all`, label: selectAllLabel, size: size, variant: variant, checked: allSelected, indeterminate: isIndeterminate, disabled: disabled || enabledItems.length === 0, onChange: handleSelectAllChange }) })), jsxRuntime.jsx("div", { className: layoutClass, children: items.map((item, index) => {
|
|
866
1021
|
const key = typeof item.value === 'string' || typeof item.value === 'number' ? item.value : index;
|
|
867
1022
|
return (jsxRuntime.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));
|
|
868
1023
|
}) }), (error || helperText) && (jsxRuntime.jsx("div", { className: "mt-1.5 ml-0.5", children: error ? (jsxRuntime.jsx(TextContent, { error: true, small: true, children: error })) : (jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText })) }))] }));
|
|
@@ -942,27 +1097,8 @@ const usePagination = ({ totalPages, currentPage, siblingCount = 1, // number of
|
|
|
942
1097
|
|
|
943
1098
|
var _path$9;
|
|
944
1099
|
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); }
|
|
945
|
-
var SvgChevronLeft = function SvgChevronLeft(props) {
|
|
946
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$9({
|
|
947
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
948
|
-
width: 24,
|
|
949
|
-
height: 24,
|
|
950
|
-
fill: "none",
|
|
951
|
-
stroke: "currentColor",
|
|
952
|
-
strokeLinecap: "round",
|
|
953
|
-
strokeLinejoin: "round",
|
|
954
|
-
strokeWidth: 2,
|
|
955
|
-
className: "lucide lucide-chevron-left-icon lucide-chevron-left",
|
|
956
|
-
viewBox: "0 0 24 24"
|
|
957
|
-
}, props), _path$9 || (_path$9 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
958
|
-
d: "m15 18-6-6 6-6"
|
|
959
|
-
})));
|
|
960
|
-
};
|
|
961
|
-
|
|
962
|
-
var _path$8;
|
|
963
|
-
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); }
|
|
964
1100
|
var SvgChevronRight = function SvgChevronRight(props) {
|
|
965
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1101
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$9({
|
|
966
1102
|
xmlns: "http://www.w3.org/2000/svg",
|
|
967
1103
|
width: 24,
|
|
968
1104
|
height: 24,
|
|
@@ -973,7 +1109,7 @@ var SvgChevronRight = function SvgChevronRight(props) {
|
|
|
973
1109
|
strokeWidth: 2,
|
|
974
1110
|
className: "lucide lucide-chevron-right-icon lucide-chevron-right",
|
|
975
1111
|
viewBox: "0 0 24 24"
|
|
976
|
-
}, props), _path$
|
|
1112
|
+
}, props), _path$9 || (_path$9 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
977
1113
|
d: "m9 18 6-6-6-6"
|
|
978
1114
|
})));
|
|
979
1115
|
};
|
|
@@ -1095,10 +1231,10 @@ const useRowSelection = ({ items, getKey, selectedRowKeys, defaultSelectedRowKey
|
|
|
1095
1231
|
};
|
|
1096
1232
|
};
|
|
1097
1233
|
|
|
1098
|
-
var _path$
|
|
1099
|
-
function _extends$
|
|
1234
|
+
var _path$8;
|
|
1235
|
+
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); }
|
|
1100
1236
|
var SvgArrowDownWideNarrow = function SvgArrowDownWideNarrow(props) {
|
|
1101
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1237
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$8({
|
|
1102
1238
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1103
1239
|
width: 24,
|
|
1104
1240
|
height: 24,
|
|
@@ -1109,15 +1245,15 @@ var SvgArrowDownWideNarrow = function SvgArrowDownWideNarrow(props) {
|
|
|
1109
1245
|
strokeWidth: 2,
|
|
1110
1246
|
className: "lucide lucide-arrow-down-wide-narrow-icon lucide-arrow-down-wide-narrow",
|
|
1111
1247
|
viewBox: "0 0 24 24"
|
|
1112
|
-
}, props), _path$
|
|
1248
|
+
}, props), _path$8 || (_path$8 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1113
1249
|
d: "m3 16 4 4 4-4M7 20V4M11 4h10M11 8h7M11 12h4"
|
|
1114
1250
|
})));
|
|
1115
1251
|
};
|
|
1116
1252
|
|
|
1117
|
-
var _path$
|
|
1118
|
-
function _extends$
|
|
1253
|
+
var _path$7;
|
|
1254
|
+
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); }
|
|
1119
1255
|
var SvgArrowDownNarrowWide = function SvgArrowDownNarrowWide(props) {
|
|
1120
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1256
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$7({
|
|
1121
1257
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1122
1258
|
width: 24,
|
|
1123
1259
|
height: 24,
|
|
@@ -1128,15 +1264,15 @@ var SvgArrowDownNarrowWide = function SvgArrowDownNarrowWide(props) {
|
|
|
1128
1264
|
strokeWidth: 2,
|
|
1129
1265
|
className: "lucide lucide-arrow-down-narrow-wide-icon lucide-arrow-down-narrow-wide",
|
|
1130
1266
|
viewBox: "0 0 24 24"
|
|
1131
|
-
}, props), _path$
|
|
1267
|
+
}, props), _path$7 || (_path$7 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1132
1268
|
d: "m3 16 4 4 4-4M7 20V4M11 4h4M11 8h7M11 12h10"
|
|
1133
1269
|
})));
|
|
1134
1270
|
};
|
|
1135
1271
|
|
|
1136
|
-
var _path$
|
|
1137
|
-
function _extends$
|
|
1272
|
+
var _path$6;
|
|
1273
|
+
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); }
|
|
1138
1274
|
var SvgArrowDownAz = function SvgArrowDownAz(props) {
|
|
1139
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1275
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$6({
|
|
1140
1276
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1141
1277
|
width: 24,
|
|
1142
1278
|
height: 24,
|
|
@@ -1147,15 +1283,15 @@ var SvgArrowDownAz = function SvgArrowDownAz(props) {
|
|
|
1147
1283
|
strokeWidth: 2,
|
|
1148
1284
|
className: "lucide lucide-arrow-down-az-icon lucide-arrow-down-a-z",
|
|
1149
1285
|
viewBox: "0 0 24 24"
|
|
1150
|
-
}, props), _path$
|
|
1286
|
+
}, props), _path$6 || (_path$6 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1151
1287
|
d: "m3 16 4 4 4-4M7 20V4M20 8h-5M15 10V6.5a2.5 2.5 0 0 1 5 0V10M15 14h5l-5 6h5"
|
|
1152
1288
|
})));
|
|
1153
1289
|
};
|
|
1154
1290
|
|
|
1155
|
-
var _path$
|
|
1156
|
-
function _extends$
|
|
1291
|
+
var _path$5;
|
|
1292
|
+
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); }
|
|
1157
1293
|
var SvgArrowDownZa = function SvgArrowDownZa(props) {
|
|
1158
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1294
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$5({
|
|
1159
1295
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1160
1296
|
width: 24,
|
|
1161
1297
|
height: 24,
|
|
@@ -1166,15 +1302,15 @@ var SvgArrowDownZa = function SvgArrowDownZa(props) {
|
|
|
1166
1302
|
strokeWidth: 2,
|
|
1167
1303
|
className: "lucide lucide-arrow-down-za-icon lucide-arrow-down-z-a",
|
|
1168
1304
|
viewBox: "0 0 24 24"
|
|
1169
|
-
}, props), _path$
|
|
1305
|
+
}, props), _path$5 || (_path$5 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1170
1306
|
d: "m3 16 4 4 4-4M7 4v16M15 4h5l-5 6h5M15 20v-3.5a2.5 2.5 0 0 1 5 0V20M20 18h-5"
|
|
1171
1307
|
})));
|
|
1172
1308
|
};
|
|
1173
1309
|
|
|
1174
|
-
var _path$
|
|
1175
|
-
function _extends$
|
|
1310
|
+
var _path$4;
|
|
1311
|
+
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); }
|
|
1176
1312
|
var SvgArrowUpDown = function SvgArrowUpDown(props) {
|
|
1177
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1313
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$4({
|
|
1178
1314
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1179
1315
|
width: 24,
|
|
1180
1316
|
height: 24,
|
|
@@ -1185,7 +1321,7 @@ var SvgArrowUpDown = function SvgArrowUpDown(props) {
|
|
|
1185
1321
|
strokeWidth: 2,
|
|
1186
1322
|
className: "lucide lucide-arrow-up-down-icon lucide-arrow-up-down",
|
|
1187
1323
|
viewBox: "0 0 24 24"
|
|
1188
|
-
}, props), _path$
|
|
1324
|
+
}, props), _path$4 || (_path$4 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1189
1325
|
d: "m21 16-4 4-4-4M17 20V4M3 8l4-4 4 4M7 4v16"
|
|
1190
1326
|
})));
|
|
1191
1327
|
};
|
|
@@ -1227,7 +1363,7 @@ const autoSortItems = (items, column, sort) => {
|
|
|
1227
1363
|
return 0;
|
|
1228
1364
|
});
|
|
1229
1365
|
};
|
|
1230
|
-
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, }) {
|
|
1366
|
+
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, }) {
|
|
1231
1367
|
const internalSorting = React.useRef({});
|
|
1232
1368
|
const [sortedItems, setSortedItems] = React.useState(items);
|
|
1233
1369
|
React.useEffect(() => {
|
|
@@ -1272,12 +1408,13 @@ function DataTable({ items, columns, sorting = {}, onSort, loading, pagination,
|
|
|
1272
1408
|
});
|
|
1273
1409
|
const densityCellClass = DENSITY_CELL_CLASS$2[density];
|
|
1274
1410
|
const colSize = columns.length + (selectable ? 1 : 0);
|
|
1275
|
-
|
|
1411
|
+
const wrapperHasOverflow = /\boverflow-(x-|y-)?(auto|hidden|scroll|visible|clip)\b/.test(wrapperClass);
|
|
1412
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('w-full rounded-lg relative', containerClass), children: [jsxRuntime.jsx("div", { className: buildClassName(!wrapperHasOverflow && 'overflow-x-auto', 'rounded-lg border border-[var(--ui-border)]', wrapperClass, pagination && 'rounded-b-none border-b-0'), children: jsxRuntime.jsxs(Table, { className: buildClassName('relative w-full max-w-full h-fit', tableClass), layout: layout, children: [jsxRuntime.jsxs(TableHead, { className: headClass, children: [selectable && (jsxRuntime.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: jsxRuntime.jsx(Checkbox, { "aria-label": "Select all rows", checked: allSelected, ref: (el) => {
|
|
1276
1413
|
if (el)
|
|
1277
1414
|
el.indeterminate = someSelected;
|
|
1278
|
-
}, onChange: toggleAll }) })), columns.map((column) => (jsxRuntime.jsx(TableHeaderCell, { align: column.headerAlign, style: { width: column.width || 'auto' }, className: buildClassName('bg-gray-50 dark:bg-gray-800', densityCellClass, column.sticky === 'left' &&
|
|
1279
|
-
'sticky left-0 z-
|
|
1280
|
-
'sticky right-0 z-
|
|
1415
|
+
}, onChange: toggleAll }) })), columns.map((column) => (jsxRuntime.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' &&
|
|
1416
|
+
'sticky left-0 z-30 shadow-[2px_0_6px_rgba(0,0,0,0.06)]', column.sticky === 'right' &&
|
|
1417
|
+
'sticky right-0 z-30 shadow-[-2px_0_6px_rgba(0,0,0,0.06)]', column.headerClass), children: jsxRuntime.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: [jsxRuntime.jsx(TextContent, { className: "shrink-0", children: column.label }), column.sortable ? getSortIcon(sorting[column.name]) : null] }) }, column.name)))] }), jsxRuntime.jsx(TableBody, { loading: loading, colSize: colSize, rowSize: (pagination === null || pagination === void 0 ? void 0 : pagination.limit) || 5, children: !loading && sortedItems.length === 0 ? (jsxRuntime.jsx(EmptyTableRow, { colSpan: colSize, children: emptyMessage })) : (sortedItems.map((item, idx) => {
|
|
1281
1418
|
const key = getKey(item, idx);
|
|
1282
1419
|
const rowSelectable = !isRowSelectable || isRowSelectable(item);
|
|
1283
1420
|
return (jsxRuntime.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 && (jsxRuntime.jsx(TableCell, { className: buildClassName(densityCellClass, striped && idx % 2 === 1 && 'bg-gray-50 dark:bg-gray-800/40'), children: jsxRuntime.jsx("span", { onClick: (e) => e.stopPropagation(), children: jsxRuntime.jsx(Checkbox, { "aria-label": "Select row", checked: isSelected(key), disabled: !rowSelectable, onChange: () => toggleRow(key) }) }) })), columns.map((column) => {
|
|
@@ -1288,7 +1425,7 @@ function DataTable({ items, columns, sorting = {}, onSort, loading, pagination,
|
|
|
1288
1425
|
? column.render(item)
|
|
1289
1426
|
: ((_a = get(item, column.name)) !== null && _a !== void 0 ? _a : 'Not set') }, column.name));
|
|
1290
1427
|
})] }, key));
|
|
1291
|
-
})) }), footerRow && jsxRuntime.jsx(TableFoot, { children: footerRow })] }) }), pagination && (jsxRuntime.jsx(Pagination, { ...pagination, className: buildClassName('rounded-b-lg border
|
|
1428
|
+
})) }), footerRow && jsxRuntime.jsx(TableFoot, { children: footerRow })] }) }), pagination && (jsxRuntime.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 }))] }));
|
|
1292
1429
|
}
|
|
1293
1430
|
DataTable.displayName = 'DataTable';
|
|
1294
1431
|
|
|
@@ -1403,8 +1540,8 @@ const DetailedInformation = React.forwardRef((props, ref) => {
|
|
|
1403
1540
|
const isMultiColumn = columns > 1;
|
|
1404
1541
|
return (jsxRuntime.jsxs("div", { ref: ref, className: buildClassName(isCard
|
|
1405
1542
|
? compact
|
|
1406
|
-
? 'p-3 sm:p-4 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-
|
|
1407
|
-
: 'p-4 sm:p-6 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-
|
|
1543
|
+
? 'p-3 sm:p-4 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-[var(--ui-border)]'
|
|
1544
|
+
: 'p-4 sm:p-6 bg-gray-50/60 dark:bg-gray-800/40 rounded-2xl border border-[var(--ui-border)]'
|
|
1408
1545
|
: isBordered
|
|
1409
1546
|
? compact
|
|
1410
1547
|
? 'p-3 sm:p-4 border border-[var(--ui-border)] rounded-2xl'
|
|
@@ -1422,8 +1559,8 @@ const DetailedInformation = React.forwardRef((props, ref) => {
|
|
|
1422
1559
|
const isVertical = layout === 'vertical' || isMultiColumn;
|
|
1423
1560
|
return (jsxRuntime.jsxs("div", { className: buildClassName(isMultiColumn && isCard
|
|
1424
1561
|
? compact
|
|
1425
|
-
? 'p-3 bg-white dark:bg-gray-900 rounded-xl border border-
|
|
1426
|
-
: 'p-4 bg-white dark:bg-gray-900 rounded-xl border border-
|
|
1562
|
+
? 'p-3 bg-white dark:bg-gray-900 rounded-xl border border-[var(--ui-border)] shadow-2xs flex flex-col gap-1'
|
|
1563
|
+
: 'p-4 bg-white dark:bg-gray-900 rounded-xl border border-[var(--ui-border)] shadow-2xs flex flex-col gap-1'
|
|
1427
1564
|
: isVertical
|
|
1428
1565
|
? 'flex flex-col gap-1 py-2 px-1'
|
|
1429
1566
|
: 'grid grid-cols-3 gap-4 items-center py-2.5 px-1', compact && !isMultiColumn ? 'py-1.5' : ''), children: [jsxRuntime.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 && jsxRuntime.jsx("span", { className: "shrink-0 text-gray-400", children: detail.icon }), jsxRuntime.jsx("span", { children: detail.label }), detail.helpText && (jsxRuntime.jsx("span", { className: "text-xs text-gray-400 font-normal cursor-help", title: detail.helpText, children: "(?)" }))] }), jsxRuntime.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 ? (jsxRuntime.jsx(CopyableValue, { text: copyText, children: displayValue })) : (displayValue) })] }, detail.label || index));
|
|
@@ -1436,41 +1573,6 @@ const Dot = ({ as = 'span', className, ...props }) => React.createElement(as, {
|
|
|
1436
1573
|
...props,
|
|
1437
1574
|
});
|
|
1438
1575
|
|
|
1439
|
-
const alignmentMap = {
|
|
1440
|
-
center: 'items-center justify-center h-full',
|
|
1441
|
-
start: 'justify-start h-full',
|
|
1442
|
-
end: 'justify-end h-full',
|
|
1443
|
-
top: 'items-start justify-center w-full',
|
|
1444
|
-
bottom: 'items-end justify-center h-full',
|
|
1445
|
-
};
|
|
1446
|
-
const panelAlignmentMap = {
|
|
1447
|
-
center: 'data-[closed]:scale-95 rounded-2xl',
|
|
1448
|
-
start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
|
|
1449
|
-
end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
|
|
1450
|
-
top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
|
|
1451
|
-
bottom: 'data-[closed]:translate-y-1/2 rounded-t-2xl md:rounded-t-3xl max-h-[92svh]',
|
|
1452
|
-
};
|
|
1453
|
-
const panelSizeMap = {
|
|
1454
|
-
xs: 'max-w-xs',
|
|
1455
|
-
sm: 'max-w-sm',
|
|
1456
|
-
md: 'max-w-md',
|
|
1457
|
-
lg: 'max-w-lg',
|
|
1458
|
-
xl: 'max-w-xl',
|
|
1459
|
-
'2xl': 'max-w-2xl',
|
|
1460
|
-
full: 'w-full',
|
|
1461
|
-
};
|
|
1462
|
-
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, }) => {
|
|
1463
|
-
const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
|
|
1464
|
-
const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
|
|
1465
|
-
const handleDialogClose = () => {
|
|
1466
|
-
if (closeOnOutsideClick) {
|
|
1467
|
-
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
1468
|
-
}
|
|
1469
|
-
};
|
|
1470
|
-
return (jsxRuntime.jsxs(react.Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: handleDialogClose, transition: true, children: [backdrop && (jsxRuntime.jsx(react.DialogBackdrop, { className: "fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200" })), jsxRuntime.jsx("div", { className: "fixed inset-0 w-screen h-[100svh]", children: jsxRuntime.jsx("div", { className: buildClassName('flex', alignmentMap[align]), children: jsxRuntime.jsxs(react.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 && (jsxRuntime.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 && (jsxRuntime.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: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsxRuntime.jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsxRuntime.jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsxRuntime.jsx(react.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 && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4" }) }))] }), description && (jsxRuntime.jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsxRuntime.jsx("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass), children: children }), footer && (jsxRuntime.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 }))] }) }) })] }));
|
|
1471
|
-
};
|
|
1472
|
-
Drawer.displayName = 'Drawer';
|
|
1473
|
-
|
|
1474
1576
|
const WIDTH_CLASS = {
|
|
1475
1577
|
auto: 'w-auto min-w-[120px]',
|
|
1476
1578
|
sm: 'w-44',
|
|
@@ -1496,7 +1598,7 @@ const Dropdown = ({ triggerButton, renderTriggerButton, className, items, render
|
|
|
1496
1598
|
variant: (_b = triggerButton.props.variant) !== null && _b !== void 0 ? _b : variant,
|
|
1497
1599
|
size: (_c = triggerButton.props.size) !== null && _c !== void 0 ? _c : size,
|
|
1498
1600
|
disabled: (_d = triggerButton.props.disabled) !== null && _d !== void 0 ? _d : disabled,
|
|
1499
|
-
}) })) : (jsxRuntime.jsx(react.MenuButton, { as: React.Fragment, children: triggerButton })), jsxRuntime.jsx(react.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-
|
|
1601
|
+
}) })) : (jsxRuntime.jsx(react.MenuButton, { as: React.Fragment, children: triggerButton })), jsxRuntime.jsx(react.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) => (jsxRuntime.jsxs(React.Fragment, { children: [item.groupTitle && (jsxRuntime.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}`)), jsxRuntime.jsx(react.MenuItem, { as: "li", disabled: item.disabled, children: ({ disabled, active }) => (jsxRuntime.jsx("div", { onClick: () => {
|
|
1500
1602
|
var _a;
|
|
1501
1603
|
if (!disabled) {
|
|
1502
1604
|
(_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item, item);
|
|
@@ -1508,14 +1610,14 @@ const Dropdown = ({ triggerButton, renderTriggerButton, className, items, render
|
|
|
1508
1610
|
: 'hover:bg-rose-50 dark:hover:bg-rose-950/40')
|
|
1509
1611
|
: buildClassName('text-gray-700 dark:text-gray-200', active
|
|
1510
1612
|
? 'bg-gray-100 dark:bg-gray-700/80'
|
|
1511
|
-
: '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)) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [item.icon && (jsxRuntime.jsx("span", { className: buildClassName('shrink-0', item.danger ? 'text-rose-500' : 'text-gray-400 dark:text-gray-500'), children: item.icon })), jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0", children: [item.label && jsxRuntime.jsx("span", { className: "font-medium truncate", children: item.label }), item.description && (jsxRuntime.jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500 font-normal truncate", children: item.description }))] })] }), item.shortcut && (jsxRuntime.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-
|
|
1613
|
+
: '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)) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: [item.icon && (jsxRuntime.jsx("span", { className: buildClassName('shrink-0', item.danger ? 'text-rose-500' : 'text-gray-400 dark:text-gray-500'), children: item.icon })), jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0", children: [item.label && jsxRuntime.jsx("span", { className: "font-medium truncate", children: item.label }), item.description && (jsxRuntime.jsx("span", { className: "text-xs text-gray-400 dark:text-gray-500 font-normal truncate", children: item.description }))] })] }), item.shortcut && (jsxRuntime.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 && (jsxRuntime.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))) })] }));
|
|
1512
1614
|
};
|
|
1513
1615
|
Dropdown.displayName = 'Dropdown';
|
|
1514
1616
|
|
|
1515
|
-
var _path$
|
|
1516
|
-
function _extends$
|
|
1617
|
+
var _path$3;
|
|
1618
|
+
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); }
|
|
1517
1619
|
var SvgFolderPlus = function SvgFolderPlus(props) {
|
|
1518
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$
|
|
1620
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$3({
|
|
1519
1621
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1520
1622
|
width: 24,
|
|
1521
1623
|
height: 24,
|
|
@@ -1526,7 +1628,7 @@ var SvgFolderPlus = function SvgFolderPlus(props) {
|
|
|
1526
1628
|
strokeWidth: 2,
|
|
1527
1629
|
className: "lucide lucide-folder-plus-icon lucide-folder-plus",
|
|
1528
1630
|
viewBox: "0 0 24 24"
|
|
1529
|
-
}, props), _path$
|
|
1631
|
+
}, props), _path$3 || (_path$3 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
1530
1632
|
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"
|
|
1531
1633
|
})));
|
|
1532
1634
|
};
|
|
@@ -1535,16 +1637,402 @@ const EmptyState = ({ title, description, className, action = null, }) => {
|
|
|
1535
1637
|
return (jsxRuntime.jsx("div", { className: buildClassName('w-full flex justify-center px-4 pt-16', className), children: jsxRuntime.jsxs("div", { className: "max-w-md flex flex-col items-center gap-4", children: [jsxRuntime.jsx(SvgFolderPlus, { className: "size-8 text-[var(--ui-text)]" }), jsxRuntime.jsx(HeadingText.SubTitle, { children: title }), description && (jsxRuntime.jsx(BodyText, { as: "p", className: "text-center", muted: true, small: true, children: description })), action] }) }));
|
|
1536
1638
|
};
|
|
1537
1639
|
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1640
|
+
function FloatingActionButton({ icon, activeIcon, label, variant = 'primary', size = 'md', position = 'bottom-right', speedDialActions, isOpen: externalIsOpen, onToggle, disabled = false, onClick, 'aria-label': ariaLabel, containerClass = '', className = '', }) {
|
|
1641
|
+
const [internalIsOpen, setInternalIsOpen] = React.useState(false);
|
|
1642
|
+
const isSpeedDial = Array.isArray(speedDialActions) && speedDialActions.length > 0;
|
|
1643
|
+
const isOpen = externalIsOpen !== undefined ? externalIsOpen : internalIsOpen;
|
|
1644
|
+
const toggleOpen = () => {
|
|
1645
|
+
const nextState = !isOpen;
|
|
1646
|
+
setInternalIsOpen(nextState);
|
|
1647
|
+
onToggle === null || onToggle === void 0 ? void 0 : onToggle(nextState);
|
|
1648
|
+
};
|
|
1649
|
+
const handleMainClick = () => {
|
|
1650
|
+
if (disabled)
|
|
1651
|
+
return;
|
|
1652
|
+
if (isSpeedDial) {
|
|
1653
|
+
toggleOpen();
|
|
1654
|
+
}
|
|
1655
|
+
else {
|
|
1656
|
+
onClick === null || onClick === void 0 ? void 0 : onClick();
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
const handleSubActionClick = (action) => {
|
|
1660
|
+
var _a;
|
|
1661
|
+
if (action.disabled)
|
|
1662
|
+
return;
|
|
1663
|
+
(_a = action.onClick) === null || _a === void 0 ? void 0 : _a.call(action);
|
|
1664
|
+
setInternalIsOpen(false);
|
|
1665
|
+
onToggle === null || onToggle === void 0 ? void 0 : onToggle(false);
|
|
1666
|
+
};
|
|
1667
|
+
const positionClasses = {
|
|
1668
|
+
'bottom-right': 'fixed bottom-6 right-6 z-40',
|
|
1669
|
+
'bottom-left': 'fixed bottom-6 left-6 z-40',
|
|
1670
|
+
'bottom-center': 'fixed bottom-6 left-1/2 -translate-x-1/2 z-40',
|
|
1671
|
+
inline: 'relative inline-flex z-10',
|
|
1672
|
+
}[position];
|
|
1673
|
+
const variantClasses = {
|
|
1674
|
+
primary: 'bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white shadow-lg shadow-blue-600/30',
|
|
1675
|
+
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',
|
|
1676
|
+
danger: 'bg-red-600 hover:bg-red-700 active:bg-red-800 text-white shadow-lg shadow-red-600/30',
|
|
1677
|
+
dark: 'bg-gray-900 hover:bg-black active:bg-black text-white shadow-lg shadow-gray-900/40',
|
|
1678
|
+
}[variant];
|
|
1679
|
+
const sizeClasses = {
|
|
1680
|
+
sm: label ? 'px-3.5 py-2 text-xs gap-2 rounded-full' : 'p-2.5 rounded-full',
|
|
1681
|
+
md: label ? 'px-5 py-3 text-sm gap-2.5 rounded-full' : 'p-3.5 rounded-full',
|
|
1682
|
+
lg: label ? 'px-6 py-4 text-base gap-3 rounded-full' : 'p-4 rounded-full',
|
|
1683
|
+
}[size];
|
|
1684
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName(positionClasses, containerClass), "data-testid": "fab-container", children: [isSpeedDial && isOpen && (jsxRuntime.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 && (jsxRuntime.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'
|
|
1685
|
+
? 'items-start left-0'
|
|
1686
|
+
: position === 'bottom-center'
|
|
1687
|
+
? 'items-center left-1/2 -translate-x-1/2'
|
|
1688
|
+
: 'items-end right-0', isOpen
|
|
1689
|
+
? 'scale-100 opacity-100 pointer-events-auto'
|
|
1690
|
+
: 'scale-90 opacity-0 pointer-events-none'), "data-testid": "fab-speed-dial-menu", children: speedDialActions.map((action) => {
|
|
1691
|
+
const isDanger = action.theme === 'danger';
|
|
1692
|
+
const isPrimary = action.theme === 'primary';
|
|
1693
|
+
return (jsxRuntime.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 &&
|
|
1694
|
+
(isDanger
|
|
1695
|
+
? 'bg-red-600 text-white hover:bg-red-700'
|
|
1696
|
+
: isPrimary
|
|
1697
|
+
? 'bg-blue-600 text-white hover:bg-blue-700'
|
|
1698
|
+
: '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: [jsxRuntime.jsx("span", { className: "text-sm", children: action.icon }), jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: action.label })] }, action.id));
|
|
1699
|
+
}) })), jsxRuntime.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: [jsxRuntime.jsx("span", { className: buildClassName('transition-transform duration-200', isOpen && 'rotate-45'), children: isOpen && activeIcon ? activeIcon : icon }), label && jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: label })] })] }));
|
|
1700
|
+
}
|
|
1701
|
+
FloatingActionButton.displayName = 'FloatingActionButton';
|
|
1702
|
+
|
|
1703
|
+
const GAP_MAP = {
|
|
1704
|
+
none: 'gap-0',
|
|
1705
|
+
xs: 'gap-1',
|
|
1706
|
+
sm: 'gap-2',
|
|
1707
|
+
md: 'gap-4',
|
|
1708
|
+
lg: 'gap-6',
|
|
1709
|
+
xl: 'gap-8',
|
|
1710
|
+
'2xl': 'gap-12',
|
|
1711
|
+
};
|
|
1712
|
+
const GAP_X_MAP = {
|
|
1713
|
+
none: 'gap-x-0',
|
|
1714
|
+
xs: 'gap-x-1',
|
|
1715
|
+
sm: 'gap-x-2',
|
|
1716
|
+
md: 'gap-x-4',
|
|
1717
|
+
lg: 'gap-x-6',
|
|
1718
|
+
xl: 'gap-x-8',
|
|
1719
|
+
'2xl': 'gap-x-12',
|
|
1720
|
+
};
|
|
1721
|
+
const GAP_Y_MAP = {
|
|
1722
|
+
none: 'gap-y-0',
|
|
1723
|
+
xs: 'gap-y-1',
|
|
1724
|
+
sm: 'gap-y-2',
|
|
1725
|
+
md: 'gap-y-4',
|
|
1726
|
+
lg: 'gap-y-6',
|
|
1727
|
+
xl: 'gap-y-8',
|
|
1728
|
+
'2xl': 'gap-y-12',
|
|
1729
|
+
};
|
|
1730
|
+
const ALIGN_MAP = {
|
|
1731
|
+
start: 'items-start',
|
|
1732
|
+
center: 'items-center',
|
|
1733
|
+
end: 'items-end',
|
|
1734
|
+
baseline: 'items-baseline',
|
|
1735
|
+
stretch: 'items-stretch',
|
|
1736
|
+
};
|
|
1737
|
+
const JUSTIFY_MAP = {
|
|
1738
|
+
start: 'justify-start',
|
|
1739
|
+
center: 'justify-center',
|
|
1740
|
+
end: 'justify-end',
|
|
1741
|
+
between: 'justify-between',
|
|
1742
|
+
around: 'justify-around',
|
|
1743
|
+
evenly: 'justify-evenly',
|
|
1744
|
+
};
|
|
1745
|
+
const DIRECTION_MAP = {
|
|
1746
|
+
row: 'flex-row',
|
|
1747
|
+
'row-reverse': 'flex-row-reverse',
|
|
1748
|
+
col: 'flex-col',
|
|
1749
|
+
'col-reverse': 'flex-col-reverse',
|
|
1750
|
+
};
|
|
1751
|
+
const WRAP_MAP = {
|
|
1752
|
+
wrap: 'flex-wrap',
|
|
1753
|
+
nowrap: 'flex-nowrap',
|
|
1754
|
+
'wrap-reverse': 'flex-wrap-reverse',
|
|
1755
|
+
};
|
|
1756
|
+
/**
|
|
1757
|
+
* Resolves the `order` prop to inline styles when it's a raw number.
|
|
1758
|
+
*
|
|
1759
|
+
* `'first'` / `'last'` map to the static `order-first`/`order-last` Tailwind
|
|
1760
|
+
* utilities (safe, since those exact class names are literal elsewhere).
|
|
1761
|
+
* Arbitrary numeric orders can't be expressed as a safe literal class (the
|
|
1762
|
+
* value is unbounded), so they're applied as an inline `order` style instead
|
|
1763
|
+
* — that works regardless of what the consuming app's Tailwind build scans.
|
|
1764
|
+
*/
|
|
1765
|
+
const resolveOrderStyle = (order) => typeof order === 'number' ? { order } : undefined;
|
|
1766
|
+
const resolveOrderClassName = (order) => {
|
|
1767
|
+
if (order === 'first')
|
|
1768
|
+
return '-order-1';
|
|
1769
|
+
if (order === 'last')
|
|
1770
|
+
return 'order-last';
|
|
1771
|
+
return undefined;
|
|
1772
|
+
};
|
|
1773
|
+
/** Width-fraction span classes used by `Flex.Item` (unprefixed / base breakpoint). */
|
|
1774
|
+
const FLEX_SPAN_MAP = {
|
|
1775
|
+
1: 'w-1/12 flex-none',
|
|
1776
|
+
2: 'w-2/12 flex-none',
|
|
1777
|
+
3: 'w-3/12 flex-none',
|
|
1778
|
+
4: 'w-4/12 flex-none',
|
|
1779
|
+
5: 'w-5/12 flex-none',
|
|
1780
|
+
6: 'w-6/12 flex-none',
|
|
1781
|
+
7: 'w-7/12 flex-none',
|
|
1782
|
+
8: 'w-8/12 flex-none',
|
|
1783
|
+
9: 'w-9/12 flex-none',
|
|
1784
|
+
10: 'w-10/12 flex-none',
|
|
1785
|
+
11: 'w-11/12 flex-none',
|
|
1786
|
+
12: 'w-full flex-none',
|
|
1787
|
+
auto: 'w-auto flex-none',
|
|
1788
|
+
full: 'w-full flex-none',
|
|
1789
|
+
};
|
|
1790
|
+
const FLEX_SM_SPAN_MAP = {
|
|
1791
|
+
1: 'sm:w-1/12',
|
|
1792
|
+
2: 'sm:w-2/12',
|
|
1793
|
+
3: 'sm:w-3/12',
|
|
1794
|
+
4: 'sm:w-4/12',
|
|
1795
|
+
5: 'sm:w-5/12',
|
|
1796
|
+
6: 'sm:w-6/12',
|
|
1797
|
+
7: 'sm:w-7/12',
|
|
1798
|
+
8: 'sm:w-8/12',
|
|
1799
|
+
9: 'sm:w-9/12',
|
|
1800
|
+
10: 'sm:w-10/12',
|
|
1801
|
+
11: 'sm:w-11/12',
|
|
1802
|
+
12: 'sm:w-full',
|
|
1803
|
+
auto: 'sm:w-auto',
|
|
1804
|
+
full: 'sm:w-full',
|
|
1805
|
+
};
|
|
1806
|
+
const FLEX_MD_SPAN_MAP = {
|
|
1807
|
+
1: 'md:w-1/12',
|
|
1808
|
+
2: 'md:w-2/12',
|
|
1809
|
+
3: 'md:w-3/12',
|
|
1810
|
+
4: 'md:w-4/12',
|
|
1811
|
+
5: 'md:w-5/12',
|
|
1812
|
+
6: 'md:w-6/12',
|
|
1813
|
+
7: 'md:w-7/12',
|
|
1814
|
+
8: 'md:w-8/12',
|
|
1815
|
+
9: 'md:w-9/12',
|
|
1816
|
+
10: 'md:w-10/12',
|
|
1817
|
+
11: 'md:w-11/12',
|
|
1818
|
+
12: 'md:w-full',
|
|
1819
|
+
auto: 'md:w-auto',
|
|
1820
|
+
full: 'md:w-full',
|
|
1821
|
+
};
|
|
1822
|
+
const FLEX_LG_SPAN_MAP = {
|
|
1823
|
+
1: 'lg:w-1/12',
|
|
1824
|
+
2: 'lg:w-2/12',
|
|
1825
|
+
3: 'lg:w-3/12',
|
|
1826
|
+
4: 'lg:w-4/12',
|
|
1827
|
+
5: 'lg:w-5/12',
|
|
1828
|
+
6: 'lg:w-6/12',
|
|
1829
|
+
7: 'lg:w-7/12',
|
|
1830
|
+
8: 'lg:w-8/12',
|
|
1831
|
+
9: 'lg:w-9/12',
|
|
1832
|
+
10: 'lg:w-10/12',
|
|
1833
|
+
11: 'lg:w-11/12',
|
|
1834
|
+
12: 'lg:w-full',
|
|
1835
|
+
auto: 'lg:w-auto',
|
|
1836
|
+
full: 'lg:w-full',
|
|
1837
|
+
};
|
|
1838
|
+
const FLEX_XL_SPAN_MAP = {
|
|
1839
|
+
1: 'xl:w-1/12',
|
|
1840
|
+
2: 'xl:w-2/12',
|
|
1841
|
+
3: 'xl:w-3/12',
|
|
1842
|
+
4: 'xl:w-4/12',
|
|
1843
|
+
5: 'xl:w-5/12',
|
|
1844
|
+
6: 'xl:w-6/12',
|
|
1845
|
+
7: 'xl:w-7/12',
|
|
1846
|
+
8: 'xl:w-8/12',
|
|
1847
|
+
9: 'xl:w-9/12',
|
|
1848
|
+
10: 'xl:w-10/12',
|
|
1849
|
+
11: 'xl:w-11/12',
|
|
1850
|
+
12: 'xl:w-full',
|
|
1851
|
+
auto: 'xl:w-auto',
|
|
1852
|
+
full: 'xl:w-full',
|
|
1853
|
+
};
|
|
1854
|
+
const FLEX_XXL_SPAN_MAP = {
|
|
1855
|
+
1: '2xl:w-1/12',
|
|
1856
|
+
2: '2xl:w-2/12',
|
|
1857
|
+
3: '2xl:w-3/12',
|
|
1858
|
+
4: '2xl:w-4/12',
|
|
1859
|
+
5: '2xl:w-5/12',
|
|
1860
|
+
6: '2xl:w-6/12',
|
|
1861
|
+
7: '2xl:w-7/12',
|
|
1862
|
+
8: '2xl:w-8/12',
|
|
1863
|
+
9: '2xl:w-9/12',
|
|
1864
|
+
10: '2xl:w-10/12',
|
|
1865
|
+
11: '2xl:w-11/12',
|
|
1866
|
+
12: '2xl:w-full',
|
|
1867
|
+
auto: '2xl:w-auto',
|
|
1868
|
+
full: '2xl:w-full',
|
|
1869
|
+
};
|
|
1870
|
+
/** `col-span-*` classes used by `Grid.Col` (unprefixed / base breakpoint). */
|
|
1871
|
+
const GRID_SPAN_MAP = {
|
|
1872
|
+
1: 'col-span-1',
|
|
1873
|
+
2: 'col-span-2',
|
|
1874
|
+
3: 'col-span-3',
|
|
1875
|
+
4: 'col-span-4',
|
|
1876
|
+
5: 'col-span-5',
|
|
1877
|
+
6: 'col-span-6',
|
|
1878
|
+
7: 'col-span-7',
|
|
1879
|
+
8: 'col-span-8',
|
|
1880
|
+
9: 'col-span-9',
|
|
1881
|
+
10: 'col-span-10',
|
|
1882
|
+
11: 'col-span-11',
|
|
1883
|
+
12: 'col-span-12',
|
|
1884
|
+
auto: 'col-auto',
|
|
1885
|
+
full: 'col-span-full',
|
|
1886
|
+
};
|
|
1887
|
+
const GRID_SM_SPAN_MAP = {
|
|
1888
|
+
1: 'sm:col-span-1',
|
|
1889
|
+
2: 'sm:col-span-2',
|
|
1890
|
+
3: 'sm:col-span-3',
|
|
1891
|
+
4: 'sm:col-span-4',
|
|
1892
|
+
5: 'sm:col-span-5',
|
|
1893
|
+
6: 'sm:col-span-6',
|
|
1894
|
+
7: 'sm:col-span-7',
|
|
1895
|
+
8: 'sm:col-span-8',
|
|
1896
|
+
9: 'sm:col-span-9',
|
|
1897
|
+
10: 'sm:col-span-10',
|
|
1898
|
+
11: 'sm:col-span-11',
|
|
1899
|
+
12: 'sm:col-span-12',
|
|
1900
|
+
auto: 'sm:col-auto',
|
|
1901
|
+
full: 'sm:col-span-full',
|
|
1902
|
+
};
|
|
1903
|
+
const GRID_MD_SPAN_MAP = {
|
|
1904
|
+
1: 'md:col-span-1',
|
|
1905
|
+
2: 'md:col-span-2',
|
|
1906
|
+
3: 'md:col-span-3',
|
|
1907
|
+
4: 'md:col-span-4',
|
|
1908
|
+
5: 'md:col-span-5',
|
|
1909
|
+
6: 'md:col-span-6',
|
|
1910
|
+
7: 'md:col-span-7',
|
|
1911
|
+
8: 'md:col-span-8',
|
|
1912
|
+
9: 'md:col-span-9',
|
|
1913
|
+
10: 'md:col-span-10',
|
|
1914
|
+
11: 'md:col-span-11',
|
|
1915
|
+
12: 'md:col-span-12',
|
|
1916
|
+
auto: 'md:col-auto',
|
|
1917
|
+
full: 'md:col-span-full',
|
|
1918
|
+
};
|
|
1919
|
+
const GRID_LG_SPAN_MAP = {
|
|
1920
|
+
1: 'lg:col-span-1',
|
|
1921
|
+
2: 'lg:col-span-2',
|
|
1922
|
+
3: 'lg:col-span-3',
|
|
1923
|
+
4: 'lg:col-span-4',
|
|
1924
|
+
5: 'lg:col-span-5',
|
|
1925
|
+
6: 'lg:col-span-6',
|
|
1926
|
+
7: 'lg:col-span-7',
|
|
1927
|
+
8: 'lg:col-span-8',
|
|
1928
|
+
9: 'lg:col-span-9',
|
|
1929
|
+
10: 'lg:col-span-10',
|
|
1930
|
+
11: 'lg:col-span-11',
|
|
1931
|
+
12: 'lg:col-span-12',
|
|
1932
|
+
auto: 'lg:col-auto',
|
|
1933
|
+
full: 'lg:col-span-full',
|
|
1934
|
+
};
|
|
1935
|
+
const GRID_XL_SPAN_MAP = {
|
|
1936
|
+
1: 'xl:col-span-1',
|
|
1937
|
+
2: 'xl:col-span-2',
|
|
1938
|
+
3: 'xl:col-span-3',
|
|
1939
|
+
4: 'xl:col-span-4',
|
|
1940
|
+
5: 'xl:col-span-5',
|
|
1941
|
+
6: 'xl:col-span-6',
|
|
1942
|
+
7: 'xl:col-span-7',
|
|
1943
|
+
8: 'xl:col-span-8',
|
|
1944
|
+
9: 'xl:col-span-9',
|
|
1945
|
+
10: 'xl:col-span-10',
|
|
1946
|
+
11: 'xl:col-span-11',
|
|
1947
|
+
12: 'xl:col-span-12',
|
|
1948
|
+
auto: 'xl:col-auto',
|
|
1949
|
+
full: 'xl:col-span-full',
|
|
1950
|
+
};
|
|
1951
|
+
const GRID_XXL_SPAN_MAP = {
|
|
1952
|
+
1: '2xl:col-span-1',
|
|
1953
|
+
2: '2xl:col-span-2',
|
|
1954
|
+
3: '2xl:col-span-3',
|
|
1955
|
+
4: '2xl:col-span-4',
|
|
1956
|
+
5: '2xl:col-span-5',
|
|
1957
|
+
6: '2xl:col-span-6',
|
|
1958
|
+
7: '2xl:col-span-7',
|
|
1959
|
+
8: '2xl:col-span-8',
|
|
1960
|
+
9: '2xl:col-span-9',
|
|
1961
|
+
10: '2xl:col-span-10',
|
|
1962
|
+
11: '2xl:col-span-11',
|
|
1963
|
+
12: '2xl:col-span-12',
|
|
1964
|
+
auto: '2xl:col-auto',
|
|
1965
|
+
full: '2xl:col-span-full',
|
|
1966
|
+
};
|
|
1967
|
+
/**
|
|
1968
|
+
* Preset track-count classes for `Grid`'s `cols` prop. Each preset
|
|
1969
|
+
* progressively reveals more columns at wider breakpoints so a grid is
|
|
1970
|
+
* responsive out of the box without the caller specifying per-item spans.
|
|
1971
|
+
*/
|
|
1972
|
+
const GRID_COLS_MAP = {
|
|
1973
|
+
1: 'grid-cols-1',
|
|
1974
|
+
2: 'grid-cols-1 sm:grid-cols-2',
|
|
1975
|
+
3: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3',
|
|
1976
|
+
4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
|
|
1977
|
+
5: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5',
|
|
1978
|
+
6: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6',
|
|
1979
|
+
7: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-7',
|
|
1980
|
+
8: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-8',
|
|
1981
|
+
9: 'grid-cols-1 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-9',
|
|
1982
|
+
10: 'grid-cols-1 sm:grid-cols-2 md:grid-cols-5 lg:grid-cols-10',
|
|
1983
|
+
11: 'grid-cols-1 sm:grid-cols-3 md:grid-cols-6 lg:grid-cols-11',
|
|
1984
|
+
12: 'grid-cols-12',
|
|
1985
|
+
auto: 'grid-cols-none auto-cols-auto',
|
|
1986
|
+
};
|
|
1987
|
+
|
|
1988
|
+
const FlexItem = React.forwardRef((props, ref) => {
|
|
1989
|
+
const { as: Component = 'div', span, sm, md, lg, xl, xxl, grow, shrink, order, className, style, children, ...restProps } = props;
|
|
1990
|
+
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);
|
|
1991
|
+
return (jsxRuntime.jsx(Component, { ref: ref, className: classes, style: { ...resolveOrderStyle(order), ...style }, ...restProps, children: children }));
|
|
1992
|
+
});
|
|
1993
|
+
FlexItem.displayName = 'Flex.Item';
|
|
1994
|
+
const Flex = React.forwardRef((props, ref) => {
|
|
1995
|
+
const { as: Component = 'div', gap, gapX, gapY, align = 'stretch', justify = 'start', direction = 'row', wrap = 'wrap', inline = false, className, children, ...restProps } = props;
|
|
1996
|
+
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);
|
|
1997
|
+
return (jsxRuntime.jsx(Component, { ref: ref, className: classes, ...restProps, children: children }));
|
|
1998
|
+
});
|
|
1999
|
+
Flex.Item = FlexItem;
|
|
2000
|
+
Flex.Col = FlexItem;
|
|
2001
|
+
Flex.displayName = 'Flex';
|
|
2002
|
+
|
|
2003
|
+
const GridContext = React.createContext({ isAutoFit: false });
|
|
2004
|
+
const GridCol = React.forwardRef((props, ref) => {
|
|
2005
|
+
const { as: Component = 'div', span, sm, md, lg, xl, xxl, grow, shrink, order, className, style, children, ...restProps } = props;
|
|
2006
|
+
const { isAutoFit } = React.useContext(GridContext);
|
|
2007
|
+
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);
|
|
2008
|
+
return (jsxRuntime.jsx(Component, { ref: ref, className: classes, style: { ...resolveOrderStyle(order), ...style }, ...restProps, children: children }));
|
|
2009
|
+
});
|
|
2010
|
+
GridCol.displayName = 'Grid.Col';
|
|
2011
|
+
const Grid = React.forwardRef((props, ref) => {
|
|
2012
|
+
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;
|
|
2013
|
+
const isAutoFit = Boolean(!flex && minColWidth);
|
|
2014
|
+
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 &&
|
|
2015
|
+
!minColWidth &&
|
|
2016
|
+
(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);
|
|
2017
|
+
const gridTemplateColumns = !flex && minColWidth
|
|
2018
|
+
? `repeat(${autoFit ? 'auto-fit' : 'auto-fill'}, minmax(${minColWidth}, 1fr))`
|
|
2019
|
+
: undefined;
|
|
2020
|
+
return (jsxRuntime.jsx(GridContext.Provider, { value: { isAutoFit }, children: jsxRuntime.jsx(Component, { ref: ref, className: classes, style: gridTemplateColumns ? { gridTemplateColumns, ...style } : style, ...restProps, children: children }) }));
|
|
2021
|
+
});
|
|
2022
|
+
Grid.Col = GridCol;
|
|
2023
|
+
Grid.Item = GridCol;
|
|
2024
|
+
Grid.displayName = 'Grid';
|
|
2025
|
+
|
|
2026
|
+
const sizeClasses$4 = {
|
|
2027
|
+
sm: {
|
|
2028
|
+
input: 'px-2.5 py-1.5 text-xs leading-5',
|
|
2029
|
+
group: 'w-8 text-xs',
|
|
2030
|
+
icon: 'size-3.5',
|
|
2031
|
+
text: 'text-xs',
|
|
2032
|
+
},
|
|
2033
|
+
md: {
|
|
2034
|
+
input: 'px-3.5 py-2 text-sm leading-6',
|
|
2035
|
+
group: 'w-10 text-sm',
|
|
1548
2036
|
icon: 'size-4',
|
|
1549
2037
|
text: 'text-sm',
|
|
1550
2038
|
},
|
|
@@ -1559,9 +2047,9 @@ function buildInputClass(className, { isFocusWithin = false, disabled = false, h
|
|
|
1559
2047
|
const currentSize = sizeClasses$4[size] || sizeClasses$4.md;
|
|
1560
2048
|
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
|
|
1561
2049
|
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
1562
|
-
: 'outline-
|
|
1563
|
-
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 dark:text-gray-600 dark:placeholder-gray-600 placeholder-gray-400 outline-
|
|
1564
|
-
: 'bg-white dark:bg-gray-700 dark:text-white outline-
|
|
2050
|
+
: 'outline-[var(--ui-border)]', disabled
|
|
2051
|
+
? '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)]'
|
|
2052
|
+
: 'bg-white dark:bg-gray-700 dark:text-white outline-[var(--ui-border)] dark:placeholder-gray-400 placeholder-gray-400', isFocusWithin
|
|
1565
2053
|
? 'focus-within:outline-[var(--ui-focus-ring)] focus-within:outline-2 focus-within:-outline-offset-2'
|
|
1566
2054
|
: 'focus:outline-[var(--ui-focus-ring)] focus:outline-2 focus:-outline-offset-2', className);
|
|
1567
2055
|
}
|
|
@@ -1599,11 +2087,11 @@ const Input = React.forwardRef((props, ref) => {
|
|
|
1599
2087
|
const actualRightGroup = rightGroup !== null && rightGroup !== void 0 ? rightGroup : (showClearButton ? (jsxRuntime.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: jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: currentSize.icon, children: jsxRuntime.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);
|
|
1600
2088
|
const hasRightGroup = actualRightGroup !== null && actualRightGroup !== undefined;
|
|
1601
2089
|
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
1602
|
-
return (jsxRuntime.jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.jsxs("div", { className: "flex rounded-lg shadow-2xs", children: [prefix && (jsxRuntime.jsx("span", { className: "inline-flex items-center px-3 rounded-l-lg border border-r-0 border-
|
|
2090
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.jsxs("div", { className: "flex rounded-lg shadow-2xs", children: [prefix && (jsxRuntime.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 })), jsxRuntime.jsxs("div", { className: "relative flex-1 min-w-0", children: [hasLeftGroup && (jsxRuntime.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 })), jsxRuntime.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, {
|
|
1603
2091
|
disabled: inputProps.disabled,
|
|
1604
2092
|
hasError,
|
|
1605
2093
|
size,
|
|
1606
|
-
}), 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 && (jsxRuntime.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 && (jsxRuntime.jsx("span", { className: "inline-flex items-center px-3 rounded-r-lg border border-l-0 border-
|
|
2094
|
+
}), 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 && (jsxRuntime.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 && (jsxRuntime.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 ? (jsxRuntime.jsxs("div", { className: "mt-1.5 flex items-center justify-between gap-2 text-xs", children: [jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: showErrorMessage && error ? (jsxRuntime.jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText })) : null }), showCount && (jsxRuntime.jsxs("span", { className: buildClassName('text-[11px] font-medium shrink-0 ml-auto', maxLength && charLength >= maxLength
|
|
1607
2095
|
? 'text-red-500 font-semibold'
|
|
1608
2096
|
: 'text-gray-400 dark:text-gray-500'), children: [charLength, maxLength ? ` / ${maxLength}` : ''] }))] })) : null] }));
|
|
1609
2097
|
});
|
|
@@ -1653,6 +2141,170 @@ const PasswordInput = React.forwardRef((props, ref) => {
|
|
|
1653
2141
|
});
|
|
1654
2142
|
PasswordInput.displayName = 'PasswordInput';
|
|
1655
2143
|
|
|
2144
|
+
function PinInput({ length = 4, value: externalValue, onChange, onComplete, mask = false, size = 'md', type = 'numeric', error, disabled = false, autoFocus = false, containerClass = '', inputClass = '', }) {
|
|
2145
|
+
const [internalValue, setInternalValue] = React.useState('');
|
|
2146
|
+
const inputRefs = React.useRef([]);
|
|
2147
|
+
const pinValue = externalValue !== undefined ? externalValue : internalValue;
|
|
2148
|
+
const digits = Array.from({ length }, (_, i) => pinValue[i] || '');
|
|
2149
|
+
React.useEffect(() => {
|
|
2150
|
+
if (autoFocus && inputRefs.current[0] && !disabled) {
|
|
2151
|
+
inputRefs.current[0].focus();
|
|
2152
|
+
}
|
|
2153
|
+
}, [autoFocus, disabled]);
|
|
2154
|
+
const updatePin = (newDigits) => {
|
|
2155
|
+
const newPin = newDigits.join('').slice(0, length);
|
|
2156
|
+
setInternalValue(newPin);
|
|
2157
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newPin);
|
|
2158
|
+
if (newPin.length === length) {
|
|
2159
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete(newPin);
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
const handleInputChange = (e, index) => {
|
|
2163
|
+
var _a;
|
|
2164
|
+
const char = e.target.value.slice(-1);
|
|
2165
|
+
if (!char)
|
|
2166
|
+
return;
|
|
2167
|
+
const isValid = type === 'numeric' ? /^[0-9]$/.test(char) : /^[a-zA-Z0-9]$/.test(char);
|
|
2168
|
+
if (!isValid)
|
|
2169
|
+
return;
|
|
2170
|
+
const nextDigits = [...digits];
|
|
2171
|
+
nextDigits[index] = char;
|
|
2172
|
+
updatePin(nextDigits);
|
|
2173
|
+
if (index < length - 1 && inputRefs.current[index + 1]) {
|
|
2174
|
+
(_a = inputRefs.current[index + 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
2175
|
+
}
|
|
2176
|
+
};
|
|
2177
|
+
const handleKeyDown = (e, index) => {
|
|
2178
|
+
var _a, _b, _c;
|
|
2179
|
+
if (e.key === 'Backspace') {
|
|
2180
|
+
if (!digits[index] && index > 0 && inputRefs.current[index - 1]) {
|
|
2181
|
+
const nextDigits = [...digits];
|
|
2182
|
+
nextDigits[index - 1] = '';
|
|
2183
|
+
updatePin(nextDigits);
|
|
2184
|
+
(_a = inputRefs.current[index - 1]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
2185
|
+
}
|
|
2186
|
+
else if (digits[index]) {
|
|
2187
|
+
const nextDigits = [...digits];
|
|
2188
|
+
nextDigits[index] = '';
|
|
2189
|
+
updatePin(nextDigits);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
else if (e.key === 'ArrowLeft' && index > 0) {
|
|
2193
|
+
(_b = inputRefs.current[index - 1]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
2194
|
+
}
|
|
2195
|
+
else if (e.key === 'ArrowRight' && index < length - 1) {
|
|
2196
|
+
(_c = inputRefs.current[index + 1]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
const handlePaste = (e) => {
|
|
2200
|
+
e.preventDefault();
|
|
2201
|
+
if (disabled)
|
|
2202
|
+
return;
|
|
2203
|
+
const pastedData = e.clipboardData.getData('text').trim();
|
|
2204
|
+
const regex = type === 'numeric' ? /[0-9]/g : /[a-zA-Z0-9]/g;
|
|
2205
|
+
const matchedChars = pastedData.match(regex) || [];
|
|
2206
|
+
if (matchedChars.length === 0)
|
|
2207
|
+
return;
|
|
2208
|
+
const nextDigits = Array.from({ length }, (_, i) => matchedChars[i] || '');
|
|
2209
|
+
updatePin(nextDigits);
|
|
2210
|
+
const focusIndex = Math.min(matchedChars.length, length) - 1;
|
|
2211
|
+
const targetRef = inputRefs.current[focusIndex >= 0 ? focusIndex : 0];
|
|
2212
|
+
targetRef === null || targetRef === void 0 ? void 0 : targetRef.focus();
|
|
2213
|
+
};
|
|
2214
|
+
const sizeClasses = {
|
|
2215
|
+
sm: 'size-9 text-sm rounded-lg',
|
|
2216
|
+
md: 'size-11 text-base rounded-xl',
|
|
2217
|
+
lg: 'size-14 text-lg rounded-2xl',
|
|
2218
|
+
}[size];
|
|
2219
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('space-y-1.5', containerClass), "data-testid": "pin-input-container", children: [jsxRuntime.jsx("div", { className: "flex items-center gap-2.5 sm:gap-3", children: digits.map((digit, index) => {
|
|
2220
|
+
const isFilled = Boolean(digit);
|
|
2221
|
+
return (jsxRuntime.jsx("input", { ref: (el) => {
|
|
2222
|
+
inputRefs.current[index] = el;
|
|
2223
|
+
}, 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
|
|
2224
|
+
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 text-gray-400 dark:text-gray-600 outline-[var(--ui-border-muted)]'
|
|
2225
|
+
: error
|
|
2226
|
+
? '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'
|
|
2227
|
+
: isFilled
|
|
2228
|
+
? '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'
|
|
2229
|
+
: '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));
|
|
2230
|
+
}) }), typeof error === 'string' && (jsxRuntime.jsx("div", { className: "text-xs text-red-500 dark:text-red-400 font-medium pt-0.5", "data-testid": "pin-input-error", children: error }))] }));
|
|
2231
|
+
}
|
|
2232
|
+
PinInput.displayName = 'PinInput';
|
|
2233
|
+
|
|
2234
|
+
function PullArrowIcon({ progress }) {
|
|
2235
|
+
const rotation = Math.min(180, progress * 180);
|
|
2236
|
+
return (jsxRuntime.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: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M19 14l-7 7m0 0l-7-7m7 7V3" }) }));
|
|
2237
|
+
}
|
|
2238
|
+
function PullToRefresh({ onRefresh, pullThreshold = 70, maxPullDistance = 120, disabled = false, refreshing: externalRefreshing, pullingContent, refreshingContent, children, className = '', contentClass = '', }) {
|
|
2239
|
+
const containerRef = React.useRef(null);
|
|
2240
|
+
const startYRef = React.useRef(0);
|
|
2241
|
+
const isPullingRef = React.useRef(false);
|
|
2242
|
+
const [pullDistance, setPullDistance] = React.useState(0);
|
|
2243
|
+
const [internalRefreshing, setInternalRefreshing] = React.useState(false);
|
|
2244
|
+
const isRefreshing = externalRefreshing !== undefined ? externalRefreshing : internalRefreshing;
|
|
2245
|
+
const handleTouchStart = React.useCallback((e) => {
|
|
2246
|
+
if (disabled || isRefreshing)
|
|
2247
|
+
return;
|
|
2248
|
+
const container = containerRef.current;
|
|
2249
|
+
if (container && container.scrollTop === 0) {
|
|
2250
|
+
startYRef.current = e.touches[0].clientY;
|
|
2251
|
+
isPullingRef.current = true;
|
|
2252
|
+
}
|
|
2253
|
+
}, [disabled, isRefreshing]);
|
|
2254
|
+
const handleTouchMove = React.useCallback((e) => {
|
|
2255
|
+
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2256
|
+
return;
|
|
2257
|
+
const container = containerRef.current;
|
|
2258
|
+
if (!container || container.scrollTop > 0)
|
|
2259
|
+
return;
|
|
2260
|
+
const currentY = e.touches[0].clientY;
|
|
2261
|
+
const rawDistance = currentY - startYRef.current;
|
|
2262
|
+
if (rawDistance > 0) {
|
|
2263
|
+
// Rubber-band resistance formula
|
|
2264
|
+
const dampened = Math.min(maxPullDistance, rawDistance * 0.45);
|
|
2265
|
+
setPullDistance(dampened);
|
|
2266
|
+
if (e.cancelable) {
|
|
2267
|
+
e.preventDefault();
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
else {
|
|
2271
|
+
setPullDistance(0);
|
|
2272
|
+
}
|
|
2273
|
+
}, [disabled, isRefreshing, maxPullDistance]);
|
|
2274
|
+
const handleTouchEnd = React.useCallback(async () => {
|
|
2275
|
+
if (!isPullingRef.current || disabled || isRefreshing)
|
|
2276
|
+
return;
|
|
2277
|
+
isPullingRef.current = false;
|
|
2278
|
+
if (pullDistance >= pullThreshold) {
|
|
2279
|
+
setPullDistance(pullThreshold);
|
|
2280
|
+
setInternalRefreshing(true);
|
|
2281
|
+
try {
|
|
2282
|
+
await onRefresh();
|
|
2283
|
+
}
|
|
2284
|
+
finally {
|
|
2285
|
+
setInternalRefreshing(false);
|
|
2286
|
+
setPullDistance(0);
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
else {
|
|
2290
|
+
setPullDistance(0);
|
|
2291
|
+
}
|
|
2292
|
+
}, [disabled, isRefreshing, onRefresh, pullDistance, pullThreshold]);
|
|
2293
|
+
const progress = Math.min(1, pullDistance / pullThreshold);
|
|
2294
|
+
const isReady = pullDistance >= pullThreshold;
|
|
2295
|
+
return (jsxRuntime.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: [jsxRuntime.jsx("div", { className: "left-0 right-0 top-0 flex items-center justify-center pointer-events-none transition-all duration-150 z-20", style: {
|
|
2296
|
+
height: isRefreshing ? `${pullThreshold}px` : `${pullDistance}px`,
|
|
2297
|
+
opacity: pullDistance > 0 || isRefreshing ? 1 : 0,
|
|
2298
|
+
}, "data-testid": "pull-to-refresh-indicator", children: jsxRuntime.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 || (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Loader, { size: "sm" }), jsxRuntime.jsx("span", { children: "Refreshing..." })] }))) : pullingContent ? (pullingContent) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(PullArrowIcon, { progress: progress }), jsxRuntime.jsx("span", { children: isReady ? 'Release to refresh' : 'Pull down to refresh' })] })) }) }), jsxRuntime.jsx("div", { className: buildClassName('transition-transform duration-150', contentClass), style: {
|
|
2299
|
+
transform: isRefreshing
|
|
2300
|
+
? `translateY(${pullThreshold}px)`
|
|
2301
|
+
: pullDistance > 0
|
|
2302
|
+
? `translateY(${pullDistance}px)`
|
|
2303
|
+
: 'translateY(0px)',
|
|
2304
|
+
}, "data-testid": "pull-to-refresh-content", children: children })] }));
|
|
2305
|
+
}
|
|
2306
|
+
PullToRefresh.displayName = 'PullToRefresh';
|
|
2307
|
+
|
|
1656
2308
|
const SIZE_MAP = {
|
|
1657
2309
|
sm: 'size-4',
|
|
1658
2310
|
md: 'size-4.5',
|
|
@@ -1668,8 +2320,8 @@ const Radio = React.forwardRef((props, ref) => {
|
|
|
1668
2320
|
const generatedId = React.useId();
|
|
1669
2321
|
const radioId = id !== null && id !== void 0 ? id : (name && rest.value ? `${name}-${rest.value}` : generatedId);
|
|
1670
2322
|
return (jsxRuntime.jsxs("div", { className: buildClassName(wrapperClass), children: [jsxRuntime.jsxs("div", { className: buildClassName('flex items-start gap-2.5', containerClass), children: [jsxRuntime.jsx("div", { className: "grid place-items-center shrink-0 pt-0.5", children: jsxRuntime.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
|
|
1671
|
-
? 'border-
|
|
1672
|
-
: 'bg-white dark:bg-gray-700 border-
|
|
2323
|
+
? 'border-[var(--ui-border-muted)] bg-gray-100 dark:bg-gray-800 pointer-events-none'
|
|
2324
|
+
: 'bg-white dark:bg-gray-700 border-[var(--ui-border)] hover:border-gray-400 dark:hover:border-gray-500 cursor-pointer', className) }) }), (label || description) && (jsxRuntime.jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [label && (jsxRuntime.jsx(Label, { htmlFor: radioId, className: buildClassName(disabled
|
|
1673
2325
|
? 'cursor-not-allowed text-gray-400 dark:text-gray-500'
|
|
1674
2326
|
: 'cursor-pointer text-gray-700 dark:text-gray-200 font-medium', labelClass), children: label })), description && (jsxRuntime.jsx("p", { className: buildClassName('text-xs leading-normal', disabled
|
|
1675
2327
|
? 'text-gray-300 dark:text-gray-600'
|
|
@@ -1708,7 +2360,7 @@ const RadioGroup = (props) => {
|
|
|
1708
2360
|
if (isCards) {
|
|
1709
2361
|
return (jsxRuntime.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
|
|
1710
2362
|
? 'border-[var(--ui-primary)] bg-blue-50/40 dark:bg-blue-950/30 ring-2 ring-[var(--ui-primary-ring)]/30'
|
|
1711
|
-
: 'border-
|
|
2363
|
+
: 'border-[var(--ui-border)] bg-white dark:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600', isItemDisabled &&
|
|
1712
2364
|
'opacity-50 cursor-not-allowed pointer-events-none bg-gray-50 dark:bg-gray-800/50'), children: [jsxRuntime.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" }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [item.icon && (jsxRuntime.jsx("span", { className: "shrink-0 text-gray-500 dark:text-gray-400", children: item.icon })), jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white truncate", children: item.label })] }), item.description && (jsxRuntime.jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400 font-normal leading-relaxed", children: item.description }))] })] }, item.value));
|
|
1713
2365
|
}
|
|
1714
2366
|
return (jsxRuntime.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));
|
|
@@ -1803,7 +2455,7 @@ const RadioSwitch = ({ label, items, selected, size = 'md', theme = 'primary', d
|
|
|
1803
2455
|
onChange(getValue(nextItem));
|
|
1804
2456
|
}
|
|
1805
2457
|
};
|
|
1806
|
-
return (jsxRuntime.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-
|
|
2458
|
+
return (jsxRuntime.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: [jsxRuntime.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: {
|
|
1807
2459
|
transform: `translate(${style.left}px, ${style.top}px)`,
|
|
1808
2460
|
width: style.width,
|
|
1809
2461
|
height: style.height,
|
|
@@ -1983,155 +2635,1112 @@ const RangeSlider = ({ label, labelHint, labelClass = '', containerClass = '', c
|
|
|
1983
2635
|
window.addEventListener('pointermove', stablePointerMoveRef.current);
|
|
1984
2636
|
window.addEventListener('pointerup', stablePointerUpRef.current);
|
|
1985
2637
|
};
|
|
1986
|
-
const handleTrackClick = (e) => {
|
|
1987
|
-
if (!trackRef.current)
|
|
2638
|
+
const handleTrackClick = (e) => {
|
|
2639
|
+
if (!trackRef.current)
|
|
2640
|
+
return;
|
|
2641
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
2642
|
+
const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width);
|
|
2643
|
+
const rawVal = min + (x / rect.width) * (max - min);
|
|
2644
|
+
const snappedVal = snapToStep(rawVal);
|
|
2645
|
+
const pxMin = (percent(valueMin) / 100) * rect.width;
|
|
2646
|
+
const pxMax = (percent(valueMax) / 100) * rect.width;
|
|
2647
|
+
if (x <= pxMin) {
|
|
2648
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
2649
|
+
return;
|
|
2650
|
+
}
|
|
2651
|
+
if (x >= pxMax) {
|
|
2652
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
const distMin = Math.abs(snappedVal - valueMin);
|
|
2656
|
+
const distMax = Math.abs(snappedVal - valueMax);
|
|
2657
|
+
if (distMin < distMax) {
|
|
2658
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
2659
|
+
}
|
|
2660
|
+
else {
|
|
2661
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
2662
|
+
}
|
|
2663
|
+
};
|
|
2664
|
+
// Keyboard accessibility handler for thumbs
|
|
2665
|
+
const handleKeyDown = (thumb) => (e) => {
|
|
2666
|
+
let delta = 0;
|
|
2667
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown')
|
|
2668
|
+
delta = -step;
|
|
2669
|
+
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp')
|
|
2670
|
+
delta = step;
|
|
2671
|
+
else if (e.key === 'Home') {
|
|
2672
|
+
if (thumb === 'min')
|
|
2673
|
+
onChange(min, valueMax);
|
|
2674
|
+
else
|
|
2675
|
+
onChange(valueMin, valueMin + step);
|
|
2676
|
+
return;
|
|
2677
|
+
}
|
|
2678
|
+
else if (e.key === 'End') {
|
|
2679
|
+
if (thumb === 'min')
|
|
2680
|
+
onChange(valueMax - step, valueMax);
|
|
2681
|
+
else
|
|
2682
|
+
onChange(valueMin, max);
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
if (delta !== 0) {
|
|
2686
|
+
e.preventDefault();
|
|
2687
|
+
if (thumb === 'min') {
|
|
2688
|
+
const next = snapToStep(valueMin + delta);
|
|
2689
|
+
onChange(Math.min(next, valueMax - step), valueMax);
|
|
2690
|
+
}
|
|
2691
|
+
else {
|
|
2692
|
+
const next = snapToStep(valueMax + delta);
|
|
2693
|
+
onChange(valueMin, Math.max(next, valueMin + step));
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
const markEntries = marks
|
|
2698
|
+
? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))
|
|
2699
|
+
: null;
|
|
2700
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-1", children: [jsxRuntime.jsx(Label, { className: labelClass, children: label }), labelHint] })), jsxRuntime.jsxs("div", { ref: trackRef, onMouseDown: handleTrackClick, className: "relative h-8 select-none w-full flex items-center cursor-pointer", "data-testid": "range-track", children: [jsxRuntime.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) }), jsxRuntime.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: {
|
|
2701
|
+
left: `${percent(valueMin)}%`,
|
|
2702
|
+
width: `${percent(valueMax) - percent(valueMin)}%`,
|
|
2703
|
+
} }), jsxRuntime.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') &&
|
|
2704
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
2705
|
+
left: `calc(${percent(valueMin)}% - ${currentSize.thumbPx / 2}px)`,
|
|
2706
|
+
zIndex: activeThumbState === 'min' ? 50 : 30,
|
|
2707
|
+
}, "data-testid": "thumb-min", children: showTooltips && (activeThumbState === 'min' || hoveringThumb === 'min') && (jsxRuntime.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, jsxRuntime.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" })] })) }), jsxRuntime.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') &&
|
|
2708
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
2709
|
+
left: `calc(${percent(valueMax)}% - ${currentSize.thumbPx / 2}px)`,
|
|
2710
|
+
zIndex: activeThumbState === 'max' ? 50 : 40,
|
|
2711
|
+
}, "data-testid": "thumb-max", children: showTooltips && (activeThumbState === 'max' || hoveringThumb === 'max') && (jsxRuntime.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, jsxRuntime.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 && (jsxRuntime.jsx("div", { className: "relative w-full h-4 mt-1", children: markEntries.map((m) => {
|
|
2712
|
+
const markPercent = percent(m.value);
|
|
2713
|
+
return (jsxRuntime.jsxs("div", { className: "absolute top-0 transform -translate-x-1/2 flex flex-col items-center", style: { left: `${markPercent}%` }, children: [jsxRuntime.jsx("span", { className: "w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full" }), jsxRuntime.jsx("span", { className: "text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5", children: m.label })] }, m.value));
|
|
2714
|
+
}) })), jsxRuntime.jsxs("div", { className: buildClassName('flex justify-between font-medium text-gray-700 dark:text-gray-300', currentSize.text), children: [jsxRuntime.jsxs("span", { children: [Math.round(valueMin), valueSuffix] }), jsxRuntime.jsxs("span", { children: [Math.round(valueMax), valueSuffix] })] }), (showErrorMessage && hasError) || helperText ? (jsxRuntime.jsx("div", { className: "mt-1", children: showErrorMessage && hasError ? (jsxRuntime.jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText })) : null })) : null] }));
|
|
2715
|
+
};
|
|
2716
|
+
RangeSlider.displayName = 'RangeSlider';
|
|
2717
|
+
|
|
2718
|
+
const useDebounce = (value, delay) => {
|
|
2719
|
+
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
2720
|
+
React.useEffect(() => {
|
|
2721
|
+
const handler = setTimeout(() => {
|
|
2722
|
+
setDebouncedValue(value);
|
|
2723
|
+
}, delay);
|
|
2724
|
+
// Cancel the timeout if value or delay changes
|
|
2725
|
+
return () => {
|
|
2726
|
+
clearTimeout(handler);
|
|
2727
|
+
};
|
|
2728
|
+
}, [value, delay]);
|
|
2729
|
+
return debouncedValue;
|
|
2730
|
+
};
|
|
2731
|
+
const useDebounceFn = (fn, ms) => {
|
|
2732
|
+
const timeout = React.useRef(null);
|
|
2733
|
+
React.useEffect(() => {
|
|
2734
|
+
return () => clearTimeout(timeout.current);
|
|
2735
|
+
}, []);
|
|
2736
|
+
return React.useCallback((...args) => {
|
|
2737
|
+
clearTimeout(timeout.current);
|
|
2738
|
+
timeout.current = setTimeout(() => fn(...args), ms);
|
|
2739
|
+
}, [fn, ms]);
|
|
2740
|
+
};
|
|
2741
|
+
|
|
2742
|
+
var _path$2;
|
|
2743
|
+
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); }
|
|
2744
|
+
var SvgCheck = function SvgCheck(props) {
|
|
2745
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$2({
|
|
2746
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2747
|
+
width: 24,
|
|
2748
|
+
height: 24,
|
|
2749
|
+
fill: "none",
|
|
2750
|
+
stroke: "currentColor",
|
|
2751
|
+
strokeLinecap: "round",
|
|
2752
|
+
strokeLinejoin: "round",
|
|
2753
|
+
strokeWidth: 2,
|
|
2754
|
+
className: "lucide lucide-check-icon lucide-check",
|
|
2755
|
+
viewBox: "0 0 24 24"
|
|
2756
|
+
}, props), _path$2 || (_path$2 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
2757
|
+
d: "M20 6 9 17l-5-5"
|
|
2758
|
+
})));
|
|
2759
|
+
};
|
|
2760
|
+
|
|
2761
|
+
var _circle$1, _path$1;
|
|
2762
|
+
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); }
|
|
2763
|
+
var SvgCirclePlus = function SvgCirclePlus(props) {
|
|
2764
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends$1({
|
|
2765
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2766
|
+
width: 24,
|
|
2767
|
+
height: 24,
|
|
2768
|
+
fill: "none",
|
|
2769
|
+
stroke: "currentColor",
|
|
2770
|
+
strokeLinecap: "round",
|
|
2771
|
+
strokeLinejoin: "round",
|
|
2772
|
+
strokeWidth: 2,
|
|
2773
|
+
className: "lucide lucide-circle-plus-icon lucide-circle-plus",
|
|
2774
|
+
viewBox: "0 0 24 24"
|
|
2775
|
+
}, props), _circle$1 || (_circle$1 = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
2776
|
+
cx: 12,
|
|
2777
|
+
cy: 12,
|
|
2778
|
+
r: 10
|
|
2779
|
+
})), _path$1 || (_path$1 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
2780
|
+
d: "M8 12h8M12 8v8"
|
|
2781
|
+
})));
|
|
2782
|
+
};
|
|
2783
|
+
|
|
2784
|
+
var _circle, _path;
|
|
2785
|
+
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); }
|
|
2786
|
+
var SvgSearch = function SvgSearch(props) {
|
|
2787
|
+
return /*#__PURE__*/React__namespace.createElement("svg", _extends({
|
|
2788
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2789
|
+
width: 24,
|
|
2790
|
+
height: 24,
|
|
2791
|
+
fill: "none",
|
|
2792
|
+
stroke: "currentColor",
|
|
2793
|
+
strokeLinecap: "round",
|
|
2794
|
+
strokeLinejoin: "round",
|
|
2795
|
+
strokeWidth: 2,
|
|
2796
|
+
className: "lucide lucide-search-icon lucide-search",
|
|
2797
|
+
viewBox: "0 0 24 24"
|
|
2798
|
+
}, props), _circle || (_circle = /*#__PURE__*/React__namespace.createElement("circle", {
|
|
2799
|
+
cx: 11,
|
|
2800
|
+
cy: 11,
|
|
2801
|
+
r: 8
|
|
2802
|
+
})), _path || (_path = /*#__PURE__*/React__namespace.createElement("path", {
|
|
2803
|
+
d: "m21 21-4.3-4.3"
|
|
2804
|
+
})));
|
|
2805
|
+
};
|
|
2806
|
+
|
|
2807
|
+
const sizeConfigMap = {
|
|
2808
|
+
sm: {
|
|
2809
|
+
input: 'h-8 text-xs px-2.5',
|
|
2810
|
+
icon: 'size-3.5',
|
|
2811
|
+
badgeSize: 'sm',
|
|
2812
|
+
group: 'w-8',
|
|
2813
|
+
},
|
|
2814
|
+
md: {
|
|
2815
|
+
input: 'h-10 text-sm px-3',
|
|
2816
|
+
icon: 'size-4',
|
|
2817
|
+
badgeSize: 'md',
|
|
2818
|
+
group: 'w-10',
|
|
2819
|
+
},
|
|
2820
|
+
lg: {
|
|
2821
|
+
input: 'h-12 text-base px-3.5',
|
|
2822
|
+
icon: 'size-5',
|
|
2823
|
+
badgeSize: 'md',
|
|
2824
|
+
group: 'w-12',
|
|
2825
|
+
},
|
|
2826
|
+
};
|
|
2827
|
+
function MobilePicker(props) {
|
|
2828
|
+
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;
|
|
2829
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
2830
|
+
const [query, setQuery] = React.useState('');
|
|
2831
|
+
const debouncedQuery = useDebounce(query, 400);
|
|
2832
|
+
const [optionsLoading, setOptionsLoading] = React.useState(false);
|
|
2833
|
+
const [draftSelected, setDraftSelected] = React.useState(selected);
|
|
2834
|
+
const [viewportHeight, setViewportHeight] = React.useState(null);
|
|
2835
|
+
React.useEffect(() => {
|
|
2836
|
+
if (!isOpen) {
|
|
2837
|
+
setViewportHeight(null);
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
const updateHeight = () => {
|
|
2841
|
+
if (typeof window !== 'undefined' && window.visualViewport) {
|
|
2842
|
+
setViewportHeight(window.visualViewport.height);
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
updateHeight();
|
|
2846
|
+
const vv = typeof window !== 'undefined' ? window.visualViewport : null;
|
|
2847
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('resize', updateHeight);
|
|
2848
|
+
vv === null || vv === void 0 ? void 0 : vv.addEventListener('scroll', updateHeight);
|
|
2849
|
+
return () => {
|
|
2850
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('resize', updateHeight);
|
|
2851
|
+
vv === null || vv === void 0 ? void 0 : vv.removeEventListener('scroll', updateHeight);
|
|
2852
|
+
};
|
|
2853
|
+
}, [isOpen]);
|
|
2854
|
+
const currentSize = sizeConfigMap[size] || sizeConfigMap.md;
|
|
2855
|
+
const hasError = Boolean(error);
|
|
2856
|
+
const isAsyncLoading = loading || optionsLoading;
|
|
2857
|
+
const baseInputClass = React.useMemo(() => buildInputClass('', { disabled, hasError, size }), [disabled, hasError, size]);
|
|
2858
|
+
const onSearchRef = React.useRef(onSearch);
|
|
2859
|
+
React.useEffect(() => {
|
|
2860
|
+
onSearchRef.current = onSearch;
|
|
2861
|
+
}, [onSearch]);
|
|
2862
|
+
const handleAsyncSearch = React.useCallback(async (searchString) => {
|
|
2863
|
+
var _a;
|
|
2864
|
+
try {
|
|
2865
|
+
setOptionsLoading(true);
|
|
2866
|
+
await ((_a = onSearchRef.current) === null || _a === void 0 ? void 0 : _a.call(onSearchRef, searchString));
|
|
2867
|
+
}
|
|
2868
|
+
catch (err) {
|
|
2869
|
+
console.error('Error loading options:', err);
|
|
2870
|
+
}
|
|
2871
|
+
finally {
|
|
2872
|
+
setOptionsLoading(false);
|
|
2873
|
+
}
|
|
2874
|
+
}, []);
|
|
2875
|
+
React.useEffect(() => {
|
|
2876
|
+
if (isOpen && async) {
|
|
2877
|
+
handleAsyncSearch(debouncedQuery);
|
|
2878
|
+
}
|
|
2879
|
+
}, [isOpen, async, debouncedQuery, handleAsyncSearch]);
|
|
2880
|
+
const getDisplayValue = React.useCallback((opt) => {
|
|
2881
|
+
var _a, _b;
|
|
2882
|
+
if (typeof opt === 'string')
|
|
2883
|
+
return opt;
|
|
2884
|
+
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);
|
|
2885
|
+
}, [labelKey, valueKey]);
|
|
2886
|
+
const getValue = React.useCallback((opt) => {
|
|
2887
|
+
var _a, _b;
|
|
2888
|
+
if (typeof opt === 'string')
|
|
2889
|
+
return opt;
|
|
2890
|
+
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);
|
|
2891
|
+
}, [valueKey, labelKey]);
|
|
2892
|
+
const normalizedSelected = React.useMemo(() => {
|
|
2893
|
+
if (multiple) {
|
|
2894
|
+
if (Array.isArray(selected))
|
|
2895
|
+
return selected;
|
|
2896
|
+
if (selected !== null && selected !== undefined)
|
|
2897
|
+
return [selected];
|
|
2898
|
+
return [];
|
|
2899
|
+
}
|
|
2900
|
+
else {
|
|
2901
|
+
if (Array.isArray(selected))
|
|
2902
|
+
return selected.length > 0 ? selected[0] : null;
|
|
2903
|
+
return selected !== null && selected !== void 0 ? selected : null;
|
|
2904
|
+
}
|
|
2905
|
+
}, [multiple, selected]);
|
|
2906
|
+
const normalizedDraft = React.useMemo(() => {
|
|
2907
|
+
if (multiple) {
|
|
2908
|
+
if (Array.isArray(draftSelected))
|
|
2909
|
+
return draftSelected;
|
|
2910
|
+
if (draftSelected !== null && draftSelected !== undefined)
|
|
2911
|
+
return [draftSelected];
|
|
2912
|
+
return [];
|
|
2913
|
+
}
|
|
2914
|
+
else {
|
|
2915
|
+
if (Array.isArray(draftSelected))
|
|
2916
|
+
return draftSelected.length > 0 ? draftSelected[0] : null;
|
|
2917
|
+
return draftSelected !== null && draftSelected !== void 0 ? draftSelected : null;
|
|
2918
|
+
}
|
|
2919
|
+
}, [multiple, draftSelected]);
|
|
2920
|
+
const rawAllOptions = React.useMemo(() => {
|
|
2921
|
+
if (groups === null || groups === void 0 ? void 0 : groups.length) {
|
|
2922
|
+
return groups.flatMap((g) => g.options);
|
|
2923
|
+
}
|
|
2924
|
+
return options !== null && options !== void 0 ? options : [];
|
|
2925
|
+
}, [groups, options]);
|
|
2926
|
+
const allOptions = React.useMemo(() => {
|
|
2927
|
+
const list = [...rawAllOptions];
|
|
2928
|
+
const selectedList = Array.isArray(normalizedDraft)
|
|
2929
|
+
? normalizedDraft
|
|
2930
|
+
: normalizedDraft
|
|
2931
|
+
? [normalizedDraft]
|
|
2932
|
+
: [];
|
|
2933
|
+
for (const sel of selectedList) {
|
|
2934
|
+
if (sel !== null && sel !== undefined) {
|
|
2935
|
+
const selVal = getValue(sel);
|
|
2936
|
+
const exists = list.some((item) => getValue(item) === selVal);
|
|
2937
|
+
if (!exists) {
|
|
2938
|
+
list.unshift(sel);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
return list;
|
|
2943
|
+
}, [rawAllOptions, normalizedDraft, getValue]);
|
|
2944
|
+
React.useEffect(() => {
|
|
2945
|
+
if (isOpen) {
|
|
2946
|
+
setDraftSelected(normalizedSelected);
|
|
2947
|
+
setQuery('');
|
|
2948
|
+
}
|
|
2949
|
+
}, [isOpen, normalizedSelected]);
|
|
2950
|
+
const defaultFilter = React.useCallback((opt, q) => {
|
|
2951
|
+
var _a;
|
|
2952
|
+
if (!q.trim())
|
|
2953
|
+
return true;
|
|
2954
|
+
const searchTarget = ((_a = getDisplayValue(opt)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
2955
|
+
return searchTarget.includes(q.trim().toLowerCase());
|
|
2956
|
+
}, [getDisplayValue]);
|
|
2957
|
+
const activeFilter = filterOption || defaultFilter;
|
|
2958
|
+
const filteredOptions = React.useMemo(() => {
|
|
2959
|
+
if (async)
|
|
2960
|
+
return allOptions;
|
|
2961
|
+
if (!query.trim())
|
|
2962
|
+
return allOptions;
|
|
2963
|
+
return allOptions.filter((opt) => activeFilter(opt, query));
|
|
2964
|
+
}, [allOptions, query, async, activeFilter]);
|
|
2965
|
+
const filteredGroups = React.useMemo(() => {
|
|
2966
|
+
if (!(groups === null || groups === void 0 ? void 0 : groups.length))
|
|
2967
|
+
return null;
|
|
2968
|
+
if (async)
|
|
2969
|
+
return groups;
|
|
2970
|
+
if (!query.trim())
|
|
2971
|
+
return groups;
|
|
2972
|
+
return groups
|
|
2973
|
+
.map((g) => ({
|
|
2974
|
+
...g,
|
|
2975
|
+
options: g.options.filter((opt) => activeFilter(opt, query)),
|
|
2976
|
+
}))
|
|
2977
|
+
.filter((g) => g.options.length > 0);
|
|
2978
|
+
}, [groups, query, async, activeFilter]);
|
|
2979
|
+
const createFreeTextOption = React.useCallback((text) => {
|
|
2980
|
+
const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected);
|
|
2981
|
+
if (typeof sample === 'string' ||
|
|
2982
|
+
(!sample && typeof labelKey === 'string' && labelKey === 'label')) {
|
|
2983
|
+
return text;
|
|
2984
|
+
}
|
|
2985
|
+
return {
|
|
2986
|
+
[labelKey]: text,
|
|
2987
|
+
[valueKey]: text,
|
|
2988
|
+
};
|
|
2989
|
+
}, [allOptions, selected, labelKey, valueKey]);
|
|
2990
|
+
const handleToggleOption = (option) => {
|
|
2991
|
+
const optVal = getValue(option);
|
|
2992
|
+
if (multiple) {
|
|
2993
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
2994
|
+
const index = current.findIndex((item) => getValue(item) === optVal);
|
|
2995
|
+
if (index > -1) {
|
|
2996
|
+
current.splice(index, 1);
|
|
2997
|
+
setDraftSelected(current);
|
|
2998
|
+
}
|
|
2999
|
+
else {
|
|
3000
|
+
if (maxSelection && current.length >= maxSelection)
|
|
3001
|
+
return;
|
|
3002
|
+
current.push(option);
|
|
3003
|
+
setDraftSelected(current);
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
else {
|
|
3007
|
+
setDraftSelected(option);
|
|
3008
|
+
onChange(option);
|
|
3009
|
+
setIsOpen(false);
|
|
3010
|
+
}
|
|
3011
|
+
};
|
|
3012
|
+
const handleCommitFreeText = (text) => {
|
|
3013
|
+
const trimmed = text.trim();
|
|
3014
|
+
if (!trimmed)
|
|
3015
|
+
return;
|
|
3016
|
+
const existing = allOptions.find((opt) => getDisplayValue(opt).toLowerCase() === trimmed.toLowerCase());
|
|
3017
|
+
const optionToCommit = existing || createFreeTextOption(trimmed);
|
|
3018
|
+
if (multiple) {
|
|
3019
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
3020
|
+
const already = current.some((item) => getDisplayValue(item).toLowerCase() === trimmed.toLowerCase());
|
|
3021
|
+
if (!already) {
|
|
3022
|
+
if (maxSelection && current.length >= maxSelection)
|
|
3023
|
+
return;
|
|
3024
|
+
current.push(optionToCommit);
|
|
3025
|
+
setDraftSelected(current);
|
|
3026
|
+
}
|
|
3027
|
+
setQuery('');
|
|
3028
|
+
}
|
|
3029
|
+
else {
|
|
3030
|
+
setDraftSelected(optionToCommit);
|
|
3031
|
+
onChange(optionToCommit);
|
|
3032
|
+
setIsOpen(false);
|
|
3033
|
+
}
|
|
3034
|
+
};
|
|
3035
|
+
const handleAddAndSelect = async (valueToAdd) => {
|
|
3036
|
+
try {
|
|
3037
|
+
const result = await onAdd(valueToAdd);
|
|
3038
|
+
const optionToCommit = (result || valueToAdd);
|
|
3039
|
+
if (multiple) {
|
|
3040
|
+
const current = Array.isArray(normalizedDraft) ? [...normalizedDraft] : [];
|
|
3041
|
+
current.push(optionToCommit);
|
|
3042
|
+
setDraftSelected(current);
|
|
3043
|
+
setQuery('');
|
|
3044
|
+
}
|
|
3045
|
+
else {
|
|
3046
|
+
setDraftSelected(optionToCommit);
|
|
3047
|
+
onChange(optionToCommit);
|
|
3048
|
+
setIsOpen(false);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
catch (err) {
|
|
3052
|
+
console.error('MobilePicker onAdd error:', err);
|
|
3053
|
+
}
|
|
3054
|
+
};
|
|
3055
|
+
const isAllSelected = React.useMemo(() => {
|
|
3056
|
+
if (!multiple || !Array.isArray(normalizedDraft) || !allOptions.length)
|
|
3057
|
+
return false;
|
|
3058
|
+
return allOptions.length === normalizedDraft.length;
|
|
3059
|
+
}, [multiple, normalizedDraft, allOptions]);
|
|
3060
|
+
const handleToggleSelectAll = () => {
|
|
3061
|
+
if (isAllSelected) {
|
|
3062
|
+
setDraftSelected([]);
|
|
3063
|
+
}
|
|
3064
|
+
else {
|
|
3065
|
+
setDraftSelected(allOptions);
|
|
3066
|
+
}
|
|
3067
|
+
};
|
|
3068
|
+
const handleConfirmMultiSelect = () => {
|
|
3069
|
+
onChange(normalizedDraft);
|
|
3070
|
+
setIsOpen(false);
|
|
3071
|
+
};
|
|
3072
|
+
const handleClearSingleSelect = (e) => {
|
|
3073
|
+
e.preventDefault();
|
|
3074
|
+
e.stopPropagation();
|
|
3075
|
+
setDraftSelected(multiple ? [] : null);
|
|
3076
|
+
onChange(multiple ? [] : null);
|
|
3077
|
+
};
|
|
3078
|
+
const handleTriggerClick = (e) => {
|
|
3079
|
+
if (disabled)
|
|
3080
|
+
return;
|
|
3081
|
+
const isClearClick = e.target.closest('[data-testid="mobile-picker-clear-button"]');
|
|
3082
|
+
if (isClearClick)
|
|
3083
|
+
return;
|
|
3084
|
+
setIsOpen(true);
|
|
3085
|
+
};
|
|
3086
|
+
const isOptionSelected = (option) => {
|
|
3087
|
+
const optVal = getValue(option);
|
|
3088
|
+
if (multiple) {
|
|
3089
|
+
return (Array.isArray(normalizedDraft) && normalizedDraft.some((item) => getValue(item) === optVal));
|
|
3090
|
+
}
|
|
3091
|
+
else {
|
|
3092
|
+
return Boolean(normalizedDraft && getValue(normalizedDraft) === optVal);
|
|
3093
|
+
}
|
|
3094
|
+
};
|
|
3095
|
+
const shouldShowTypeToSearch = async && !query && !isAsyncLoading && allOptions.length === 0;
|
|
3096
|
+
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
3097
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('group space-y-2 w-full', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.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 && (jsxRuntime.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 })), jsxRuntime.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) => (jsxRuntime.jsx(Badge, { theme: "secondary", size: currentSize.badgeSize, children: getDisplayValue(item) }, `${getValue(item)}-${idx}`)))) : (jsxRuntime.jsx("span", { className: "text-gray-400 dark:text-gray-500", children: placeholder }))) : normalizedSelected ? (jsxRuntime.jsx("span", { className: "text-gray-900 dark:text-white font-normal truncate", children: getDisplayValue(normalizedSelected) })) : (jsxRuntime.jsx("span", { className: "text-gray-400 dark:text-gray-500", children: placeholder })) }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [allowClear && !multiple && normalizedSelected && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-3.5 stroke-gray-500 dark:stroke-gray-400" }) })), jsxRuntime.jsx(SvgChevronDown, { className: buildClassName(currentSize.icon, 'stroke-gray-500 shrink-0') })] })] }), showErrorMessage && error && (jsxRuntime.jsx("div", { className: "mt-1", children: jsxRuntime.jsx(TextContent, { error: true, small: true, children: error }) })), !error && helperText && (jsxRuntime.jsx("div", { className: "mt-1", children: jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText }) })), jsxRuntime.jsxs(react.Dialog, { open: isOpen, as: "div", className: "relative z-50 focus:outline-none", onClose: () => setIsOpen(false), transition: true, children: [jsxRuntime.jsx(react.DialogBackdrop, { className: "fixed inset-0 bg-black/50 backdrop-blur-xs transition-opacity duration-200" }), jsxRuntime.jsx("div", { className: "fixed left-0 top-0 w-full flex items-end justify-center pointer-events-none z-50", style: {
|
|
3098
|
+
height: viewportHeight ? `${viewportHeight}px` : '100dvh',
|
|
3099
|
+
}, children: jsxRuntime.jsxs(react.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: {
|
|
3100
|
+
maxHeight: viewportHeight ? `${Math.floor(viewportHeight * 0.9)}px` : undefined,
|
|
3101
|
+
}, "data-testid": "mobile-picker-sheet", children: [jsxRuntime.jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-700 mx-auto my-2.5 shrink-0" }), jsxRuntime.jsxs("div", { className: "px-4 pb-3 border-b border-[var(--ui-border-muted)] flex items-center justify-between gap-3 shrink-0", children: [jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [jsxRuntime.jsx(react.DialogTitle, { as: "h3", className: "text-base md:text-lg font-bold text-gray-900 dark:text-white truncate", children: title || label || 'Select Option' }), description && (jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate mt-0.5", children: description }))] }), jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4" }) })] }), searchable && (jsxRuntime.jsx("div", { className: "p-3 border-b border-[var(--ui-border-muted)] bg-gray-50 dark:bg-gray-800/50 shrink-0", children: jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(SvgSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-gray-400" }), jsxRuntime.jsx("input", { type: "text", value: query, onChange: (e) => setQuery(e.target.value), onKeyDown: (e) => {
|
|
3102
|
+
if (allowFreeText && e.key === 'Enter' && query.trim()) {
|
|
3103
|
+
e.preventDefault();
|
|
3104
|
+
handleCommitFreeText(query);
|
|
3105
|
+
}
|
|
3106
|
+
}, 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" }), jsxRuntime.jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1.5", children: isAsyncLoading ? (jsxRuntime.jsx(Loader, { size: "xs" })) : (query && (jsxRuntime.jsx("button", { type: "button", onClick: () => setQuery(''), className: "p-0.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200", children: jsxRuntime.jsx(SvgX, { className: "size-3.5" }) }))) })] }) })), quickOptions && quickOptions.length > 0 && (jsxRuntime.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: [jsxRuntime.jsx("div", { className: "text-[11px] font-semibold text-gray-400 uppercase tracking-wider mb-1.5 px-1", children: quickOptionsTitle }), jsxRuntime.jsx("div", { className: "flex items-center gap-2 overflow-x-auto no-scrollbar pb-1", children: quickOptions.map((chip, cIdx) => {
|
|
3107
|
+
const isSelected = isOptionSelected(chip);
|
|
3108
|
+
return (jsxRuntime.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
|
|
3109
|
+
? 'bg-blue-600 text-white border-blue-600'
|
|
3110
|
+
: '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));
|
|
3111
|
+
}) })] })), multiple && showSelectAll && allOptions.length > 0 && (jsxRuntime.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: [jsxRuntime.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' }), jsxRuntime.jsxs("span", { className: "text-gray-500 dark:text-gray-400 font-medium", children: [Array.isArray(normalizedDraft) ? normalizedDraft.length : 0, " of", ' ', allOptions.length] })] })), jsxRuntime.jsxs("div", { onScroll: (e) => {
|
|
3112
|
+
const el = e.currentTarget;
|
|
3113
|
+
if (el.scrollTop === 0) {
|
|
3114
|
+
el.scrollTop = 1;
|
|
3115
|
+
}
|
|
3116
|
+
else if (el.scrollTop + el.clientHeight >= el.scrollHeight) {
|
|
3117
|
+
el.scrollTop = el.scrollHeight - el.clientHeight - 1;
|
|
3118
|
+
}
|
|
3119
|
+
}, 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 &&
|
|
3120
|
+
query.trim() &&
|
|
3121
|
+
!allOptions.some((opt) => getDisplayValue(opt).toLowerCase() === query.trim().toLowerCase()) && (jsxRuntime.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: [jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: ["Use \"", query.trim(), "\""] }), jsxRuntime.jsx(SvgChevronDown, { className: "size-4 rotate-[-90deg]" })] })), isAsyncLoading && allOptions.length === 0 ? (jsxRuntime.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: [jsxRuntime.jsx(Loader, { size: "md" }), jsxRuntime.jsx("span", { children: "Loading options..." })] })) : shouldShowTypeToSearch ? (jsxRuntime.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) => (jsxRuntime.jsxs("div", { className: "pt-2", children: [jsxRuntime.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 }), jsxRuntime.jsx("div", { className: "space-y-1", children: grp.options.map((option) => {
|
|
3122
|
+
const optVal = getValue(option);
|
|
3123
|
+
const isSelected = isOptionSelected(option);
|
|
3124
|
+
const optDisabled = option.disabled;
|
|
3125
|
+
const optDesc = typeof option === 'object'
|
|
3126
|
+
? (option === null || option === void 0 ? void 0 : option.description) || (option === null || option === void 0 ? void 0 : option.subtitle)
|
|
3127
|
+
: null;
|
|
3128
|
+
return (jsxRuntime.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
|
|
3129
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3130
|
+
: 'text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800/70', optDisabled && 'opacity-50 pointer-events-none'), children: [jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 pr-3", children: [jsxRuntime.jsx("div", { className: "text-sm/6 truncate", children: renderOption
|
|
3131
|
+
? renderOption(option, isSelected)
|
|
3132
|
+
: getDisplayValue(option) }), optDesc && (jsxRuntime.jsx("div", { className: "text-xs text-gray-400 font-normal truncate mt-0.5", children: optDesc }))] }), isSelected && (jsxRuntime.jsx(SvgCheck, { className: "size-5 stroke-blue-600 dark:stroke-blue-400 shrink-0" }))] }, optVal));
|
|
3133
|
+
}) })] }, gIdx)))) : filteredOptions.length > 0 ? (filteredOptions.map((option) => {
|
|
3134
|
+
const optVal = getValue(option);
|
|
3135
|
+
const isSelected = isOptionSelected(option);
|
|
3136
|
+
const optDisabled = option.disabled;
|
|
3137
|
+
const optDesc = typeof option === 'object' ? (option === null || option === void 0 ? void 0 : option.description) || (option === null || option === void 0 ? void 0 : option.subtitle) : null;
|
|
3138
|
+
return (jsxRuntime.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
|
|
3139
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3140
|
+
: 'text-gray-800 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800/70', optDisabled && 'opacity-50 pointer-events-none'), children: [jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 pr-3", children: [jsxRuntime.jsx("div", { className: "text-sm/6 truncate", children: renderOption
|
|
3141
|
+
? renderOption(option, isSelected)
|
|
3142
|
+
: getDisplayValue(option) }), optDesc && (jsxRuntime.jsx("div", { className: "text-xs text-gray-400 font-normal truncate mt-0.5", children: optDesc }))] }), isSelected && (jsxRuntime.jsx(SvgCheck, { className: "size-5 stroke-blue-600 dark:stroke-blue-400 shrink-0" }))] }, optVal));
|
|
3143
|
+
})) : (!allowFreeText &&
|
|
3144
|
+
!(allowAdd && query.trim()) && (jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-gray-500 dark:text-gray-400 select-none", children: query
|
|
3145
|
+
? noOptionsText !== 'No options available'
|
|
3146
|
+
? noOptionsText
|
|
3147
|
+
: `No results found for "${query}"`
|
|
3148
|
+
: noOptionsText }))), !allowFreeText && allowAdd && Boolean(query.trim()) && (jsxRuntime.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: [jsxRuntime.jsx(SvgCirclePlus, { className: "size-5 text-blue-600 dark:text-blue-400" }), jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: [addNewText, " \"", query.trim(), "\""] })] }))] }), multiple && (jsxRuntime.jsx("div", { className: "p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-900 shrink-0", children: jsxRuntime.jsxs(Button, { fullWidth: true, theme: "primary", size: "md", onClick: handleConfirmMultiSelect, "data-testid": "mobile-picker-confirm-button", children: [confirmText, ' ', Array.isArray(normalizedDraft) && normalizedDraft.length > 0
|
|
3149
|
+
? `(${normalizedDraft.length})`
|
|
3150
|
+
: ''] }) }))] }) })] })] }));
|
|
3151
|
+
}
|
|
3152
|
+
MobilePicker.displayName = 'MobilePicker';
|
|
3153
|
+
|
|
3154
|
+
function SingleWheelColumn({ column, itemHeight, height, disabled, onValueChange, }) {
|
|
3155
|
+
var _a;
|
|
3156
|
+
const containerRef = React.useRef(null);
|
|
3157
|
+
const [selectedValue, setSelectedValue] = React.useState(column.value !== undefined
|
|
3158
|
+
? column.value
|
|
3159
|
+
: column.defaultValue !== undefined
|
|
3160
|
+
? column.defaultValue
|
|
3161
|
+
: (_a = column.options[0]) === null || _a === void 0 ? void 0 : _a.value);
|
|
3162
|
+
const isControlled = column.value !== undefined;
|
|
3163
|
+
const currentValue = isControlled ? column.value : selectedValue;
|
|
3164
|
+
const selectedIndex = Math.max(0, column.options.findIndex((opt) => opt.value === currentValue));
|
|
3165
|
+
const paddingY = (height - itemHeight) / 2;
|
|
3166
|
+
// Sync scroll position when active value changes externally
|
|
3167
|
+
React.useEffect(() => {
|
|
3168
|
+
if (containerRef.current) {
|
|
3169
|
+
const targetScrollTop = selectedIndex * itemHeight;
|
|
3170
|
+
if (Math.abs(containerRef.current.scrollTop - targetScrollTop) > 2) {
|
|
3171
|
+
containerRef.current.scrollTop = targetScrollTop;
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
}, [selectedIndex, itemHeight]);
|
|
3175
|
+
const handleScroll = () => {
|
|
3176
|
+
var _a;
|
|
3177
|
+
if (!containerRef.current || disabled)
|
|
3178
|
+
return;
|
|
3179
|
+
const scrollTop = containerRef.current.scrollTop;
|
|
3180
|
+
const index = Math.round(scrollTop / itemHeight);
|
|
3181
|
+
const targetOption = column.options[index];
|
|
3182
|
+
if (targetOption && targetOption.value !== currentValue && !targetOption.disabled) {
|
|
3183
|
+
if (!isControlled) {
|
|
3184
|
+
setSelectedValue(targetOption.value);
|
|
3185
|
+
}
|
|
3186
|
+
(_a = column.onChange) === null || _a === void 0 ? void 0 : _a.call(column, targetOption.value);
|
|
3187
|
+
onValueChange(targetOption.value);
|
|
3188
|
+
}
|
|
3189
|
+
};
|
|
3190
|
+
return (jsxRuntime.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: {
|
|
3191
|
+
paddingTop: `${paddingY}px`,
|
|
3192
|
+
paddingBottom: `${paddingY}px`,
|
|
3193
|
+
scrollSnapType: 'y mandatory',
|
|
3194
|
+
}, "data-testid": `wheel-column-${column.id}`, children: column.options.map((opt, index) => {
|
|
3195
|
+
const isSelected = opt.value === currentValue;
|
|
3196
|
+
return (jsxRuntime.jsx("div", { onClick: () => {
|
|
3197
|
+
if (disabled || opt.disabled || !containerRef.current)
|
|
3198
|
+
return;
|
|
3199
|
+
const targetTop = index * itemHeight;
|
|
3200
|
+
if (typeof containerRef.current.scrollTo === 'function') {
|
|
3201
|
+
containerRef.current.scrollTo({
|
|
3202
|
+
top: targetTop,
|
|
3203
|
+
behavior: 'smooth',
|
|
3204
|
+
});
|
|
3205
|
+
}
|
|
3206
|
+
else {
|
|
3207
|
+
containerRef.current.scrollTop = targetTop;
|
|
3208
|
+
}
|
|
3209
|
+
}, 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
|
|
3210
|
+
? 'text-blue-600 dark:text-blue-400 text-sm font-bold scale-105'
|
|
3211
|
+
: '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}`));
|
|
3212
|
+
}) }));
|
|
3213
|
+
}
|
|
3214
|
+
function WheelPicker({ columns, height = 200, itemHeight = 40, onChange, disabled = false, containerClass = '', }) {
|
|
3215
|
+
const valuesRef = React.useRef({});
|
|
3216
|
+
const handleColumnChange = (columnId, value) => {
|
|
3217
|
+
valuesRef.current[columnId] = value;
|
|
3218
|
+
onChange === null || onChange === void 0 ? void 0 : onChange({ ...valuesRef.current });
|
|
3219
|
+
};
|
|
3220
|
+
const highlightTop = (height - itemHeight) / 2;
|
|
3221
|
+
return (jsxRuntime.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: [jsxRuntime.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: {
|
|
3222
|
+
height: `${itemHeight}px`,
|
|
3223
|
+
top: `${highlightTop}px`,
|
|
3224
|
+
}, "data-testid": "wheel-highlight-window" }), jsxRuntime.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` } }), jsxRuntime.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` } }), jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-around relative z-10 px-2", children: columns.map((col) => (jsxRuntime.jsx(SingleWheelColumn, { column: col, itemHeight: itemHeight, height: height, disabled: disabled, onValueChange: (val) => handleColumnChange(col.id, val) }, col.id))) })] }));
|
|
3225
|
+
}
|
|
3226
|
+
WheelPicker.displayName = 'WheelPicker';
|
|
3227
|
+
|
|
3228
|
+
function ChevronLeftIcon$1() {
|
|
3229
|
+
return (jsxRuntime.jsx("svg", { className: "size-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M15 19l-7-7 7-7" }) }));
|
|
3230
|
+
}
|
|
3231
|
+
function SearchIcon$1() {
|
|
3232
|
+
return (jsxRuntime.jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3233
|
+
}
|
|
3234
|
+
function ClearIcon() {
|
|
3235
|
+
return (jsxRuntime.jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }));
|
|
3236
|
+
}
|
|
3237
|
+
function MobileHeader({ title, subtitle, titleAlign = 'center', onBack, backLabel = 'Back', leading, actions, searchable = false, searchValue: externalSearchValue, onSearchChange, searchPlaceholder = 'Search...', sticky = true, transparent = false, bottomSlot, className = '', }) {
|
|
3238
|
+
const [isSearchActive, setIsSearchActive] = React.useState(false);
|
|
3239
|
+
const [internalSearchValue, setInternalSearchValue] = React.useState('');
|
|
3240
|
+
const searchValue = externalSearchValue !== undefined ? externalSearchValue : internalSearchValue;
|
|
3241
|
+
const handleSearchInput = (e) => {
|
|
3242
|
+
const val = e.target.value;
|
|
3243
|
+
setInternalSearchValue(val);
|
|
3244
|
+
onSearchChange === null || onSearchChange === void 0 ? void 0 : onSearchChange(val);
|
|
3245
|
+
};
|
|
3246
|
+
const handleClearSearch = () => {
|
|
3247
|
+
setInternalSearchValue('');
|
|
3248
|
+
onSearchChange === null || onSearchChange === void 0 ? void 0 : onSearchChange('');
|
|
3249
|
+
};
|
|
3250
|
+
return (jsxRuntime.jsxs("header", { className: buildClassName('w-full transition-colors select-none z-30', sticky && 'sticky top-0', transparent
|
|
3251
|
+
? 'bg-white/80 dark:bg-gray-900/80 backdrop-blur-md border-b border-[var(--ui-border-muted)]'
|
|
3252
|
+
: '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: [jsxRuntime.jsx("div", { className: "h-14 px-3.5 flex items-center justify-between gap-3 relative", children: searchable && isSearchActive ? (jsxRuntime.jsxs("div", { className: "flex-1 flex items-center gap-2", "data-testid": "mobile-header-search-container", children: [jsxRuntime.jsxs("div", { className: "relative flex-1 flex items-center", children: [jsxRuntime.jsx("span", { className: "absolute left-3 pointer-events-none", children: jsxRuntime.jsx(SearchIcon$1, {}) }), jsxRuntime.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 && (jsxRuntime.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: jsxRuntime.jsx(ClearIcon, {}) }))] }), jsxRuntime.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" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 z-10", children: onBack ? (jsxRuntime.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: [jsxRuntime.jsx(ChevronLeftIcon$1, {}), jsxRuntime.jsx("span", { className: "text-xs font-semibold hidden sm:inline", children: backLabel })] })) : (leading) }), jsxRuntime.jsxs("div", { className: buildClassName('flex-1 min-w-0 px-2', titleAlign === 'center'
|
|
3253
|
+
? 'absolute inset-x-12 text-center pointer-events-none flex flex-col items-center justify-center'
|
|
3254
|
+
: 'text-left'), children: [title && (jsxRuntime.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 && (jsxRuntime.jsx("div", { className: "text-[11px] text-gray-500 dark:text-gray-400 truncate pointer-events-auto", "data-testid": "mobile-header-subtitle", children: subtitle }))] }), jsxRuntime.jsxs("div", { className: "flex items-center gap-1 min-w-[40px] shrink-0 justify-end z-10", children: [searchable && (jsxRuntime.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: jsxRuntime.jsx(SearchIcon$1, {}) })), actions === null || actions === void 0 ? void 0 : actions.map((action) => {
|
|
3255
|
+
const badgeColor = {
|
|
3256
|
+
danger: 'bg-red-500 text-white',
|
|
3257
|
+
info: 'bg-blue-500 text-white',
|
|
3258
|
+
success: 'bg-emerald-500 text-white',
|
|
3259
|
+
}[action.badgeVariant || 'danger'];
|
|
3260
|
+
return (jsxRuntime.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: [jsxRuntime.jsx("span", { className: "text-base", children: action.icon }), action.badge !== undefined && action.badge !== null && (jsxRuntime.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));
|
|
3261
|
+
})] })] })) }), bottomSlot && (jsxRuntime.jsx("div", { className: "px-3 py-2 border-t border-[var(--ui-border-muted)]", "data-testid": "mobile-header-bottom-slot", children: bottomSlot }))] }));
|
|
3262
|
+
}
|
|
3263
|
+
MobileHeader.displayName = 'MobileHeader';
|
|
3264
|
+
|
|
3265
|
+
function ChevronLeftIcon() {
|
|
3266
|
+
return (jsxRuntime.jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M15 19l-7-7 7-7" }) }));
|
|
3267
|
+
}
|
|
3268
|
+
function ChevronRightIcon() {
|
|
3269
|
+
return (jsxRuntime.jsx("svg", { className: "size-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M9 5l7 7-7 7" }) }));
|
|
3270
|
+
}
|
|
3271
|
+
function MobileStepper({ steps, activeStep, variant = 'dots', onBack, onNext, backLabel = 'Back', nextLabel = 'Next', stepTitle, nextDisabled = false, backDisabled = false, nextLoading = false, className = '', }) {
|
|
3272
|
+
const isFirstStep = activeStep <= 0;
|
|
3273
|
+
const isLastStep = activeStep >= steps - 1;
|
|
3274
|
+
const progressPercent = Math.min(Math.max(((activeStep + 1) / steps) * 100, 0), 100);
|
|
3275
|
+
return (jsxRuntime.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 && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-1", children: [jsxRuntime.jsx("span", { className: "text-xs font-bold text-gray-900 dark:text-white truncate", "data-testid": "mobile-stepper-title", children: stepTitle }), jsxRuntime.jsxs("span", { className: "text-[11px] font-medium text-gray-500 dark:text-gray-400 shrink-0 ml-2", children: [activeStep + 1, " / ", steps] })] })), jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [jsxRuntime.jsx(Button, { size: "xs", variant: "plain", theme: "secondary", disabled: disabledBack(isFirstStep, backDisabled), onClick: onBack, "aria-label": "Previous step", leftIcon: jsxRuntime.jsx(ChevronLeftIcon, {}), "data-testid": "mobile-stepper-back-btn", children: backLabel }), jsxRuntime.jsxs("div", { className: "flex items-center justify-center flex-1", "data-testid": "mobile-stepper-indicator", children: [variant === 'dots' && (jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", "data-testid": "mobile-stepper-dots", children: Array.from({ length: steps }).map((_, index) => {
|
|
3276
|
+
const isActive = index === activeStep;
|
|
3277
|
+
const isCompleted = index < activeStep;
|
|
3278
|
+
return (jsxRuntime.jsx("span", { className: buildClassName('h-2 transition-all duration-300 rounded-full', isActive
|
|
3279
|
+
? 'w-5 bg-blue-600 dark:bg-blue-400'
|
|
3280
|
+
: isCompleted
|
|
3281
|
+
? 'w-2 bg-blue-300 dark:bg-blue-800'
|
|
3282
|
+
: 'w-2 bg-gray-200 dark:bg-gray-700'), "data-testid": `mobile-stepper-dot-${index}` }, index));
|
|
3283
|
+
}) })), variant === 'progress' && (jsxRuntime.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: jsxRuntime.jsx("div", { className: "bg-blue-600 dark:bg-blue-400 h-full transition-all duration-300 rounded-full", style: { width: `${progressPercent}%` } }) })), variant === 'text' && (jsxRuntime.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] }))] }), jsxRuntime.jsx(Button, { size: "xs", variant: "default", theme: "primary", disabled: nextDisabled, loading: nextLoading, onClick: onNext, "aria-label": "Next step", rightIcon: !isLastStep ? jsxRuntime.jsx(ChevronRightIcon, {}) : undefined, "data-testid": "mobile-stepper-next-btn", children: nextLabel })] })] }));
|
|
3284
|
+
}
|
|
3285
|
+
function disabledBack(isFirstStep, backDisabled) {
|
|
3286
|
+
return isFirstStep || backDisabled;
|
|
3287
|
+
}
|
|
3288
|
+
MobileStepper.displayName = 'MobileStepper';
|
|
3289
|
+
|
|
3290
|
+
const themeClasses = {
|
|
3291
|
+
danger: 'bg-red-600 text-white hover:bg-red-700 active:bg-red-800',
|
|
3292
|
+
primary: 'bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800',
|
|
3293
|
+
success: 'bg-emerald-600 text-white hover:bg-emerald-700 active:bg-emerald-800',
|
|
3294
|
+
warning: 'bg-amber-500 text-white hover:bg-amber-600 active:bg-amber-700',
|
|
3295
|
+
info: 'bg-cyan-600 text-white hover:bg-cyan-700 active:bg-cyan-800',
|
|
3296
|
+
secondary: 'bg-gray-600 text-white hover:bg-gray-700 active:bg-gray-800',
|
|
3297
|
+
gray: 'bg-gray-500 text-white hover:bg-gray-600 active:bg-gray-700',
|
|
3298
|
+
};
|
|
3299
|
+
const SwipeableRow = ({ children, leftActions = [], rightActions = [], actionWidth = 76, threshold = 40, fullSwipeToExecute = false, fullSwipeThreshold = 180, disabled = false, className = '', contentClassName = '', onOpen, onClose, }) => {
|
|
3300
|
+
const [offset, setOffset] = React.useState(0);
|
|
3301
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
3302
|
+
const containerRef = React.useRef(null);
|
|
3303
|
+
const startXRef = React.useRef(0);
|
|
3304
|
+
const startYRef = React.useRef(0);
|
|
3305
|
+
const initialOffsetRef = React.useRef(0);
|
|
3306
|
+
const isHorizontalSwipeRef = React.useRef(null);
|
|
3307
|
+
const maxLeftWidth = React.useMemo(() => leftActions.length * actionWidth, [leftActions, actionWidth]);
|
|
3308
|
+
const maxRightWidth = React.useMemo(() => rightActions.length * actionWidth, [rightActions, actionWidth]);
|
|
3309
|
+
const handleClose = React.useCallback(() => {
|
|
3310
|
+
setOffset(0);
|
|
3311
|
+
onClose === null || onClose === void 0 ? void 0 : onClose();
|
|
3312
|
+
}, [onClose]);
|
|
3313
|
+
const handleOpenLeft = React.useCallback(() => {
|
|
3314
|
+
if (maxLeftWidth > 0) {
|
|
3315
|
+
setOffset(maxLeftWidth);
|
|
3316
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen('left');
|
|
3317
|
+
}
|
|
3318
|
+
else {
|
|
3319
|
+
handleClose();
|
|
3320
|
+
}
|
|
3321
|
+
}, [maxLeftWidth, onOpen, handleClose]);
|
|
3322
|
+
const handleOpenRight = React.useCallback(() => {
|
|
3323
|
+
if (maxRightWidth > 0) {
|
|
3324
|
+
setOffset(-maxRightWidth);
|
|
3325
|
+
onOpen === null || onOpen === void 0 ? void 0 : onOpen('right');
|
|
3326
|
+
}
|
|
3327
|
+
else {
|
|
3328
|
+
handleClose();
|
|
3329
|
+
}
|
|
3330
|
+
}, [maxRightWidth, onOpen, handleClose]);
|
|
3331
|
+
const handleDragStart = (clientX, clientY) => {
|
|
3332
|
+
if (disabled)
|
|
1988
3333
|
return;
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
3334
|
+
setIsDragging(true);
|
|
3335
|
+
startXRef.current = clientX;
|
|
3336
|
+
startYRef.current = clientY;
|
|
3337
|
+
initialOffsetRef.current = offset;
|
|
3338
|
+
isHorizontalSwipeRef.current = null;
|
|
3339
|
+
};
|
|
3340
|
+
const handleDragMove = (clientX, clientY) => {
|
|
3341
|
+
if (!isDragging || disabled)
|
|
1997
3342
|
return;
|
|
3343
|
+
const deltaX = clientX - startXRef.current;
|
|
3344
|
+
const deltaY = clientY - startYRef.current;
|
|
3345
|
+
// Lock direction once initial movement surpasses 5px
|
|
3346
|
+
if (isHorizontalSwipeRef.current === null) {
|
|
3347
|
+
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
|
|
3348
|
+
isHorizontalSwipeRef.current = Math.abs(deltaX) > Math.abs(deltaY);
|
|
3349
|
+
}
|
|
1998
3350
|
}
|
|
1999
|
-
if (
|
|
2000
|
-
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
3351
|
+
if (isHorizontalSwipeRef.current === false) {
|
|
2001
3352
|
return;
|
|
2002
3353
|
}
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
if (
|
|
2006
|
-
|
|
3354
|
+
let nextOffset = initialOffsetRef.current + deltaX;
|
|
3355
|
+
// Limit drag range with resistance overscroll
|
|
3356
|
+
if (nextOffset > 0) {
|
|
3357
|
+
if (!leftActions.length) {
|
|
3358
|
+
nextOffset = 0;
|
|
3359
|
+
}
|
|
3360
|
+
else if (nextOffset > maxLeftWidth && !fullSwipeToExecute) {
|
|
3361
|
+
const overflow = nextOffset - maxLeftWidth;
|
|
3362
|
+
nextOffset = maxLeftWidth + overflow * 0.2;
|
|
3363
|
+
}
|
|
2007
3364
|
}
|
|
2008
|
-
else {
|
|
2009
|
-
|
|
3365
|
+
else if (nextOffset < 0) {
|
|
3366
|
+
if (!rightActions.length) {
|
|
3367
|
+
nextOffset = 0;
|
|
3368
|
+
}
|
|
3369
|
+
else if (Math.abs(nextOffset) > maxRightWidth && !fullSwipeToExecute) {
|
|
3370
|
+
const overflow = Math.abs(nextOffset) - maxRightWidth;
|
|
3371
|
+
nextOffset = -(maxRightWidth + overflow * 0.2);
|
|
3372
|
+
}
|
|
2010
3373
|
}
|
|
3374
|
+
setOffset(nextOffset);
|
|
2011
3375
|
};
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
let delta = 0;
|
|
2015
|
-
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown')
|
|
2016
|
-
delta = -step;
|
|
2017
|
-
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp')
|
|
2018
|
-
delta = step;
|
|
2019
|
-
else if (e.key === 'Home') {
|
|
2020
|
-
if (thumb === 'min')
|
|
2021
|
-
onChange(min, valueMax);
|
|
2022
|
-
else
|
|
2023
|
-
onChange(valueMin, valueMin + step);
|
|
3376
|
+
const handleDragEnd = () => {
|
|
3377
|
+
if (!isDragging)
|
|
2024
3378
|
return;
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
if (thumb === 'min')
|
|
2028
|
-
onChange(valueMax - step, valueMax);
|
|
2029
|
-
else
|
|
2030
|
-
onChange(valueMin, max);
|
|
3379
|
+
setIsDragging(false);
|
|
3380
|
+
if (isHorizontalSwipeRef.current === false) {
|
|
2031
3381
|
return;
|
|
2032
3382
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
if (
|
|
2036
|
-
|
|
2037
|
-
|
|
3383
|
+
// Check full swipe auto-execution
|
|
3384
|
+
if (fullSwipeToExecute) {
|
|
3385
|
+
if (offset > fullSwipeThreshold && leftActions.length > 0) {
|
|
3386
|
+
leftActions[0].onClick();
|
|
3387
|
+
handleClose();
|
|
3388
|
+
return;
|
|
3389
|
+
}
|
|
3390
|
+
if (offset < -fullSwipeThreshold && rightActions.length > 0) {
|
|
3391
|
+
rightActions[0].onClick();
|
|
3392
|
+
handleClose();
|
|
3393
|
+
return;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
// Snap logic
|
|
3397
|
+
if (offset > 0) {
|
|
3398
|
+
if (offset > threshold) {
|
|
3399
|
+
handleOpenLeft();
|
|
2038
3400
|
}
|
|
2039
3401
|
else {
|
|
2040
|
-
|
|
2041
|
-
|
|
3402
|
+
handleClose();
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
else if (offset < 0) {
|
|
3406
|
+
if (Math.abs(offset) > threshold) {
|
|
3407
|
+
handleOpenRight();
|
|
3408
|
+
}
|
|
3409
|
+
else {
|
|
3410
|
+
handleClose();
|
|
2042
3411
|
}
|
|
2043
3412
|
}
|
|
2044
3413
|
};
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
3414
|
+
// Touch Handlers
|
|
3415
|
+
const handleTouchStart = (e) => {
|
|
3416
|
+
const touch = e.touches[0];
|
|
3417
|
+
handleDragStart(touch.clientX, touch.clientY);
|
|
3418
|
+
};
|
|
3419
|
+
const handleTouchMove = (e) => {
|
|
3420
|
+
const touch = e.touches[0];
|
|
3421
|
+
handleDragMove(touch.clientX, touch.clientY);
|
|
3422
|
+
};
|
|
3423
|
+
const handleTouchEnd = () => {
|
|
3424
|
+
handleDragEnd();
|
|
3425
|
+
};
|
|
3426
|
+
// Pointer/Mouse Handlers
|
|
3427
|
+
const handlePointerDown = (e) => {
|
|
3428
|
+
if (e.pointerType === 'mouse' && e.button !== 0)
|
|
3429
|
+
return;
|
|
3430
|
+
handleDragStart(e.clientX, e.clientY);
|
|
3431
|
+
};
|
|
3432
|
+
const handlePointerMove = (e) => {
|
|
3433
|
+
if (!isDragging)
|
|
3434
|
+
return;
|
|
3435
|
+
handleDragMove(e.clientX, e.clientY);
|
|
3436
|
+
};
|
|
3437
|
+
const handlePointerUp = () => {
|
|
3438
|
+
handleDragEnd();
|
|
3439
|
+
};
|
|
3440
|
+
// Close row on click outside if swiped open
|
|
2068
3441
|
React.useEffect(() => {
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
3442
|
+
if (offset === 0)
|
|
3443
|
+
return;
|
|
3444
|
+
const handleClickOutside = (e) => {
|
|
3445
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
3446
|
+
handleClose();
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
document.addEventListener('click', handleClickOutside);
|
|
2073
3450
|
return () => {
|
|
2074
|
-
|
|
3451
|
+
document.removeEventListener('click', handleClickOutside);
|
|
2075
3452
|
};
|
|
2076
|
-
}, [
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
};
|
|
2089
|
-
|
|
2090
|
-
var _path$1;
|
|
2091
|
-
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); }
|
|
2092
|
-
var SvgCheck = function SvgCheck(props) {
|
|
2093
|
-
return /*#__PURE__*/React__namespace.createElement("svg", _extends$1({
|
|
2094
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
2095
|
-
width: 24,
|
|
2096
|
-
height: 24,
|
|
2097
|
-
fill: "none",
|
|
2098
|
-
stroke: "currentColor",
|
|
2099
|
-
strokeLinecap: "round",
|
|
2100
|
-
strokeLinejoin: "round",
|
|
2101
|
-
strokeWidth: 2,
|
|
2102
|
-
className: "lucide lucide-check-icon lucide-check",
|
|
2103
|
-
viewBox: "0 0 24 24"
|
|
2104
|
-
}, props), _path$1 || (_path$1 = /*#__PURE__*/React__namespace.createElement("path", {
|
|
2105
|
-
d: "M20 6 9 17l-5-5"
|
|
2106
|
-
})));
|
|
3453
|
+
}, [offset, handleClose]);
|
|
3454
|
+
const renderActionButton = (action) => {
|
|
3455
|
+
const themeStyle = themeClasses[action.theme || 'primary'];
|
|
3456
|
+
return (jsxRuntime.jsxs("button", { type: "button", style: { width: `${actionWidth}px` }, onClick: (e) => {
|
|
3457
|
+
e.stopPropagation();
|
|
3458
|
+
action.onClick();
|
|
3459
|
+
handleClose();
|
|
3460
|
+
}, 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 && jsxRuntime.jsx("span", { className: "shrink-0", children: action.icon }), action.label && jsxRuntime.jsx("span", { className: "truncate max-w-full", children: action.label })] }, action.id));
|
|
3461
|
+
};
|
|
3462
|
+
return (jsxRuntime.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 && (jsxRuntime.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 && (jsxRuntime.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) })), jsxRuntime.jsx("div", { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: handlePointerUp, onPointerCancel: handlePointerUp, style: {
|
|
3463
|
+
transform: `translateX(${offset}px)`,
|
|
3464
|
+
transition: isDragging ? 'none' : 'transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1)',
|
|
3465
|
+
}, 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 })] }));
|
|
2107
3466
|
};
|
|
3467
|
+
SwipeableRow.displayName = 'SwipeableRow';
|
|
2108
3468
|
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
fill: "none",
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
strokeLinejoin: "round",
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
d: "M8 12h8M12 8v8"
|
|
2129
|
-
})));
|
|
3469
|
+
function SearchIcon() {
|
|
3470
|
+
return (jsxRuntime.jsx("svg", { className: "size-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }));
|
|
3471
|
+
}
|
|
3472
|
+
function FilterIcon() {
|
|
3473
|
+
return (jsxRuntime.jsx("svg", { className: "size-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.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" }) }));
|
|
3474
|
+
}
|
|
3475
|
+
function SortIcon() {
|
|
3476
|
+
return (jsxRuntime.jsx("svg", { className: "size-3.5 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4" }) }));
|
|
3477
|
+
}
|
|
3478
|
+
function CheckIcon() {
|
|
3479
|
+
return (jsxRuntime.jsx("svg", { className: "size-4 text-blue-600 dark:text-blue-400 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M5 13l4 4L19 7" }) }));
|
|
3480
|
+
}
|
|
3481
|
+
const parseNumericValue = (val) => {
|
|
3482
|
+
if (typeof val === 'number')
|
|
3483
|
+
return val;
|
|
3484
|
+
if (val === null || val === undefined)
|
|
3485
|
+
return NaN;
|
|
3486
|
+
const cleaned = String(val).replace(/[^0-9.-]/g, '');
|
|
3487
|
+
return cleaned !== '' ? Number(cleaned) : NaN;
|
|
2130
3488
|
};
|
|
3489
|
+
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 = '', }) {
|
|
3490
|
+
// Internal Search State
|
|
3491
|
+
const [internalSearchQuery, setInternalSearchQuery] = React.useState('');
|
|
3492
|
+
const searchQuery = externalSearchQuery !== undefined ? externalSearchQuery : internalSearchQuery;
|
|
3493
|
+
const handleSearchInput = (query) => {
|
|
3494
|
+
onSearchChange ? onSearchChange(query) : setInternalSearchQuery(query);
|
|
3495
|
+
};
|
|
3496
|
+
// Internal Filter State
|
|
3497
|
+
const [internalFilters, setInternalFilters] = React.useState({});
|
|
3498
|
+
const selectedFilters = externalFilters !== undefined ? externalFilters : internalFilters;
|
|
3499
|
+
// Mobile Bottom Sheet Filter Drawer State
|
|
3500
|
+
const [isFilterSheetOpen, setIsFilterSheetOpen] = React.useState(false);
|
|
3501
|
+
const [draftFilters, setDraftFilters] = React.useState({});
|
|
3502
|
+
// Mobile Bottom Sheet Sort Drawer State
|
|
3503
|
+
const [isSortSheetOpen, setIsSortSheetOpen] = React.useState(false);
|
|
3504
|
+
// Active Filter Count Calculation
|
|
3505
|
+
const activeFilterCount = React.useMemo(() => {
|
|
3506
|
+
let count = 0;
|
|
3507
|
+
Object.values(selectedFilters).forEach((val) => {
|
|
3508
|
+
if (Array.isArray(val)) {
|
|
3509
|
+
count += val.length;
|
|
3510
|
+
}
|
|
3511
|
+
else if (val !== '' && val !== null && val !== undefined && val !== 'all') {
|
|
3512
|
+
count += 1;
|
|
3513
|
+
}
|
|
3514
|
+
});
|
|
3515
|
+
return count;
|
|
3516
|
+
}, [selectedFilters]);
|
|
3517
|
+
// Internal Sort State
|
|
3518
|
+
const [internalSort, setInternalSort] = React.useState(() => {
|
|
3519
|
+
if (externalSorting && Object.keys(externalSorting).length > 0) {
|
|
3520
|
+
const field = Object.keys(externalSorting)[0];
|
|
3521
|
+
return { field, dir: externalSorting[field] };
|
|
3522
|
+
}
|
|
3523
|
+
return null;
|
|
3524
|
+
});
|
|
3525
|
+
React.useEffect(() => {
|
|
3526
|
+
if (externalSorting !== undefined) {
|
|
3527
|
+
if (Object.keys(externalSorting).length > 0) {
|
|
3528
|
+
const field = Object.keys(externalSorting)[0];
|
|
3529
|
+
setInternalSort({ field, dir: externalSorting[field] });
|
|
3530
|
+
}
|
|
3531
|
+
else {
|
|
3532
|
+
setInternalSort(null);
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
}, [externalSorting]);
|
|
3536
|
+
const activeSort = internalSort;
|
|
3537
|
+
const sortableColumns = React.useMemo(() => (columns === null || columns === void 0 ? void 0 : columns.filter((c) => c.sortable)) || [], [columns]);
|
|
3538
|
+
const sortOptions = React.useMemo(() => {
|
|
3539
|
+
const opts = [{ label: 'Default Order', value: '' }];
|
|
3540
|
+
sortableColumns.forEach((col) => {
|
|
3541
|
+
const isNum = col.type === 'number';
|
|
3542
|
+
const isDate = col.type === 'date';
|
|
3543
|
+
const lowHigh = isNum
|
|
3544
|
+
? `${col.label} (Low to High)`
|
|
3545
|
+
: isDate
|
|
3546
|
+
? `${col.label} (Oldest First)`
|
|
3547
|
+
: `${col.label} (A to Z)`;
|
|
3548
|
+
const highLow = isNum
|
|
3549
|
+
? `${col.label} (High to Low)`
|
|
3550
|
+
: isDate
|
|
3551
|
+
? `${col.label} (Newest First)`
|
|
3552
|
+
: `${col.label} (Z to A)`;
|
|
3553
|
+
opts.push({ label: lowHigh, value: `${col.name}:asc` });
|
|
3554
|
+
opts.push({ label: highLow, value: `${col.name}:desc` });
|
|
3555
|
+
});
|
|
3556
|
+
return opts;
|
|
3557
|
+
}, [sortableColumns]);
|
|
3558
|
+
const handleSortSelect = (val) => {
|
|
3559
|
+
if (!val) {
|
|
3560
|
+
setInternalSort(null);
|
|
3561
|
+
onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange({});
|
|
3562
|
+
return;
|
|
3563
|
+
}
|
|
3564
|
+
const [field, dir] = val.split(':');
|
|
3565
|
+
const sortObj = { [field]: dir };
|
|
3566
|
+
setInternalSort({ field, dir: dir });
|
|
3567
|
+
onSortChange === null || onSortChange === void 0 ? void 0 : onSortChange(sortObj);
|
|
3568
|
+
};
|
|
3569
|
+
const activeSortLabel = React.useMemo(() => {
|
|
3570
|
+
if (!activeSort)
|
|
3571
|
+
return 'Sort';
|
|
3572
|
+
const currVal = `${activeSort.field}:${activeSort.dir}`;
|
|
3573
|
+
const match = sortOptions.find((o) => o.value === currVal);
|
|
3574
|
+
if (!match || !match.value)
|
|
3575
|
+
return 'Sort';
|
|
3576
|
+
return `Sort: ${match.label}`;
|
|
3577
|
+
}, [activeSort, sortOptions]);
|
|
3578
|
+
// Processed Items (Filter + Search + Sort)
|
|
3579
|
+
const processedItems = React.useMemo(() => {
|
|
3580
|
+
let result = [...items];
|
|
3581
|
+
// 1. Apply Search
|
|
3582
|
+
if (searchQuery.trim()) {
|
|
3583
|
+
const q = searchQuery.toLowerCase().trim();
|
|
3584
|
+
const fieldsToSearch = searchFields || (columns === null || columns === void 0 ? void 0 : columns.map((c) => c.name)) || ['id', 'name', 'title'];
|
|
3585
|
+
result = result.filter((item) => fieldsToSearch.some((field) => {
|
|
3586
|
+
const val = get(item, field);
|
|
3587
|
+
return val !== null && val !== undefined && String(val).toLowerCase().includes(q);
|
|
3588
|
+
}));
|
|
3589
|
+
}
|
|
3590
|
+
// 2. Apply Filters (supporting array checkboxes or single values)
|
|
3591
|
+
const filterKeys = Object.keys(selectedFilters);
|
|
3592
|
+
if (filterKeys.length > 0) {
|
|
3593
|
+
result = result.filter((item) => filterKeys.every((key) => {
|
|
3594
|
+
const filterVal = selectedFilters[key];
|
|
3595
|
+
if (filterVal === undefined || filterVal === null || filterVal === '')
|
|
3596
|
+
return true;
|
|
3597
|
+
const actual = String(get(item, key));
|
|
3598
|
+
if (Array.isArray(filterVal)) {
|
|
3599
|
+
if (filterVal.length === 0)
|
|
3600
|
+
return true;
|
|
3601
|
+
return filterVal.map(String).includes(actual);
|
|
3602
|
+
}
|
|
3603
|
+
return actual === String(filterVal);
|
|
3604
|
+
}));
|
|
3605
|
+
}
|
|
3606
|
+
// 3. Apply Auto Sorting
|
|
3607
|
+
if (activeSort) {
|
|
3608
|
+
const { field, dir } = activeSort;
|
|
3609
|
+
const colDef = columns === null || columns === void 0 ? void 0 : columns.find((c) => c.name === field);
|
|
3610
|
+
const isAsc = dir === 'asc' || dir === '1';
|
|
3611
|
+
result.sort((a, b) => {
|
|
3612
|
+
const valA = get(a, field);
|
|
3613
|
+
const valB = get(b, field);
|
|
3614
|
+
const numA = parseNumericValue(valA);
|
|
3615
|
+
const numB = parseNumericValue(valB);
|
|
3616
|
+
if ((colDef === null || colDef === void 0 ? void 0 : colDef.type) === 'number' || (!isNaN(numA) && !isNaN(numB))) {
|
|
3617
|
+
return isAsc ? numA - numB : numB - numA;
|
|
3618
|
+
}
|
|
3619
|
+
if ((colDef === null || colDef === void 0 ? void 0 : colDef.type) === 'date') {
|
|
3620
|
+
const dA = new Date(valA).getTime();
|
|
3621
|
+
const dB = new Date(valB).getTime();
|
|
3622
|
+
if (!isNaN(dA) && !isNaN(dB)) {
|
|
3623
|
+
return isAsc ? dA - dB : dB - dA;
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
const strA = String(valA !== null && valA !== void 0 ? valA : '');
|
|
3627
|
+
const strB = String(valB !== null && valB !== void 0 ? valB : '');
|
|
3628
|
+
return isAsc
|
|
3629
|
+
? strA.localeCompare(strB, undefined, { numeric: true })
|
|
3630
|
+
: strB.localeCompare(strA, undefined, { numeric: true });
|
|
3631
|
+
});
|
|
3632
|
+
}
|
|
3633
|
+
return result;
|
|
3634
|
+
}, [items, searchQuery, searchFields, columns, selectedFilters, activeSort]);
|
|
3635
|
+
// Draft Filters Matching Count
|
|
3636
|
+
const draftMatchingCount = React.useMemo(() => {
|
|
3637
|
+
let result = [...items];
|
|
3638
|
+
const filterKeys = Object.keys(draftFilters);
|
|
3639
|
+
if (filterKeys.length > 0) {
|
|
3640
|
+
result = result.filter((item) => filterKeys.every((key) => {
|
|
3641
|
+
const filterVal = draftFilters[key];
|
|
3642
|
+
if (filterVal === undefined || filterVal === null || filterVal === '')
|
|
3643
|
+
return true;
|
|
3644
|
+
const actual = String(get(item, key));
|
|
3645
|
+
if (Array.isArray(filterVal)) {
|
|
3646
|
+
if (filterVal.length === 0)
|
|
3647
|
+
return true;
|
|
3648
|
+
return filterVal.map(String).includes(actual);
|
|
3649
|
+
}
|
|
3650
|
+
return actual === String(filterVal);
|
|
3651
|
+
}));
|
|
3652
|
+
}
|
|
3653
|
+
return result.length;
|
|
3654
|
+
}, [items, draftFilters]);
|
|
3655
|
+
const getKey = (item, idx) => {
|
|
3656
|
+
var _a;
|
|
3657
|
+
if (typeof rowKey === 'function')
|
|
3658
|
+
return rowKey(item);
|
|
3659
|
+
return (_a = item[rowKey]) !== null && _a !== void 0 ? _a : idx;
|
|
3660
|
+
};
|
|
3661
|
+
const isSelected = (key) => selectedKeys.includes(key);
|
|
3662
|
+
const toggleSelectAll = () => {
|
|
3663
|
+
if (selectedKeys.length === processedItems.length) {
|
|
3664
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange([], []);
|
|
3665
|
+
}
|
|
3666
|
+
else {
|
|
3667
|
+
const allKeys = processedItems.map(getKey);
|
|
3668
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(allKeys, processedItems);
|
|
3669
|
+
}
|
|
3670
|
+
};
|
|
3671
|
+
const toggleItemSelect = (key, item) => {
|
|
3672
|
+
const nextKeys = isSelected(key)
|
|
3673
|
+
? selectedKeys.filter((k) => k !== key)
|
|
3674
|
+
: [...selectedKeys, key];
|
|
3675
|
+
const nextItems = processedItems.filter((it, idx) => nextKeys.includes(getKey(it, idx)));
|
|
3676
|
+
onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(nextKeys, nextItems);
|
|
3677
|
+
};
|
|
3678
|
+
const getItemClassStr = (item, idx) => {
|
|
3679
|
+
if (typeof itemClass === 'function')
|
|
3680
|
+
return itemClass(item, idx);
|
|
3681
|
+
return itemClass;
|
|
3682
|
+
};
|
|
3683
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('w-full space-y-3', containerClass), "data-testid": "data-list", children: [(searchable || (filterFields && filterFields.length > 0) || sortableColumns.length > 0) && (jsxRuntime.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 && (jsxRuntime.jsx(Input, { value: searchQuery, onChange: (e) => handleSearchInput(e.target.value), placeholder: "Search items...", leftGroup: jsxRuntime.jsx(SearchIcon, {}), clearable: true, onClear: () => handleSearchInput(''), className: "w-full text-xs", size: "sm" })), ((filterFields && filterFields.length > 0) || sortableColumns.length > 0) && (jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [filterFields && filterFields.length > 0 && (jsxRuntime.jsxs(Button, { theme: "secondary", size: "sm", onClick: () => {
|
|
3684
|
+
setDraftFilters(selectedFilters);
|
|
3685
|
+
setIsFilterSheetOpen(true);
|
|
3686
|
+
}, className: "flex items-center gap-1.5 text-xs font-semibold flex-1 justify-center", "data-testid": "data-list-filter-btn", children: [jsxRuntime.jsx(FilterIcon, {}), jsxRuntime.jsx("span", { children: "Filters" }), activeFilterCount > 0 && (jsxRuntime.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 && (jsxRuntime.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: [jsxRuntime.jsx(SortIcon, {}), jsxRuntime.jsx("span", { children: activeSortLabel })] }))] }))] })), filterFields && filterFields.length > 0 && (jsxRuntime.jsx(Drawer, { isOpen: isFilterSheetOpen, onClose: () => setIsFilterSheetOpen(false), align: "bottom", title: "Filter Items", dragHandle: true, panelClass: "max-h-[85vh] rounded-t-2xl", footer: jsxRuntime.jsxs("div", { className: "flex items-center gap-3 w-full", children: [jsxRuntime.jsx(Button, { theme: "secondary", size: "md", onClick: () => setDraftFilters({}), className: "flex-1 text-xs", children: "Clear All" }), jsxRuntime.jsxs(Button, { theme: "primary", size: "md", onClick: () => {
|
|
3687
|
+
onFilterChange ? onFilterChange(draftFilters) : setInternalFilters(draftFilters);
|
|
3688
|
+
setIsFilterSheetOpen(false);
|
|
3689
|
+
}, className: "flex-1 text-xs font-semibold", "data-testid": "data-list-apply-filters-btn", children: ["Apply Filters (", draftMatchingCount, ")"] })] }), footerSticky: true, children: jsxRuntime.jsx("div", { className: "space-y-6 py-2", children: filterFields.map((field) => {
|
|
3690
|
+
const selectedArray = Array.isArray(draftFilters[field.name])
|
|
3691
|
+
? draftFilters[field.name]
|
|
3692
|
+
: draftFilters[field.name] !== undefined && draftFilters[field.name] !== ''
|
|
3693
|
+
? [draftFilters[field.name]]
|
|
3694
|
+
: [];
|
|
3695
|
+
return (jsxRuntime.jsxs("div", { className: "space-y-2.5", children: [jsxRuntime.jsx("h4", { className: "text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400 px-1", children: field.label }), jsxRuntime.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) => {
|
|
3696
|
+
const checked = selectedArray.includes(opt.value);
|
|
3697
|
+
return (jsxRuntime.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: [jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-800 dark:text-gray-200", children: opt.label }), jsxRuntime.jsx(Checkbox, { checked: checked, onChange: () => {
|
|
3698
|
+
const next = checked
|
|
3699
|
+
? selectedArray.filter((v) => v !== opt.value)
|
|
3700
|
+
: [...selectedArray, opt.value];
|
|
3701
|
+
setDraftFilters((prev) => ({
|
|
3702
|
+
...prev,
|
|
3703
|
+
[field.name]: next,
|
|
3704
|
+
}));
|
|
3705
|
+
} })] }, String(opt.value)));
|
|
3706
|
+
}) })] }, field.name));
|
|
3707
|
+
}) }) })), sortableColumns.length > 0 && (jsxRuntime.jsx(Drawer, { isOpen: isSortSheetOpen, onClose: () => setIsSortSheetOpen(false), align: "bottom", title: "Sort Items By", dragHandle: true, panelClass: "max-h-[70vh] rounded-t-2xl", children: jsxRuntime.jsx("div", { className: "space-y-1 py-2", children: sortOptions.map((opt) => {
|
|
3708
|
+
const isSelected = (activeSort ? `${activeSort.field}:${activeSort.dir}` : '') === opt.value;
|
|
3709
|
+
return (jsxRuntime.jsxs("button", { type: "button", onClick: () => {
|
|
3710
|
+
handleSortSelect(opt.value);
|
|
3711
|
+
setIsSortSheetOpen(false);
|
|
3712
|
+
}, className: buildClassName('w-full flex items-center justify-between p-3.5 rounded-xl text-left transition-colors cursor-pointer', isSelected
|
|
3713
|
+
? 'bg-blue-50 dark:bg-blue-950/40 text-blue-600 dark:text-blue-400 font-semibold'
|
|
3714
|
+
: '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: [jsxRuntime.jsx("span", { className: "text-sm", children: opt.label }), isSelected && jsxRuntime.jsx(CheckIcon, {})] }, opt.value));
|
|
3715
|
+
}) }) })), selectable && processedItems.length > 0 && (jsxRuntime.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: [jsxRuntime.jsxs("label", { className: "flex items-center gap-2 font-medium text-gray-700 dark:text-gray-300 cursor-pointer", children: [jsxRuntime.jsx(Checkbox, { checked: processedItems.length > 0 && selectedKeys.length === processedItems.length, onChange: toggleSelectAll }), jsxRuntime.jsx("span", { children: "Select All Items" })] }), jsxRuntime.jsxs("span", { className: "text-gray-400 font-semibold", children: [selectedKeys.length, " of ", processedItems.length] })] })), jsxRuntime.jsx("div", { className: "space-y-3", children: loading ? (jsxRuntime.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 ? (jsxRuntime.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) => {
|
|
3716
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
3717
|
+
const key = getKey(item, idx);
|
|
3718
|
+
const selected = isSelected(key);
|
|
3719
|
+
const actions = swipeableActions === null || swipeableActions === void 0 ? void 0 : swipeableActions(item);
|
|
3720
|
+
const customClass = getItemClassStr(item, idx);
|
|
3721
|
+
const contentNode = renderItem ? (renderItem(item, idx)) : (jsxRuntime.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: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 border-b border-[var(--ui-border-muted)] pb-2.5", children: [jsxRuntime.jsx("div", { className: "flex items-center gap-2.5 min-w-0 flex-1", children: selectable ? (jsxRuntime.jsx(Checkbox, { checked: selected, onChange: () => toggleItemSelect(key), "aria-label": `Select item ${key}`, label: jsxRuntime.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)
|
|
3722
|
+
? columns[0].render(item)
|
|
3723
|
+
: 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 : '') }) })) : (jsxRuntime.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)
|
|
3724
|
+
? columns[0].render(item)
|
|
3725
|
+
: 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] && (jsxRuntime.jsx("div", { className: "shrink-0 text-xs", children: columns[1].render
|
|
3726
|
+
? columns[1].render(item)
|
|
3727
|
+
: String((_j = get(item, columns[1].name)) !== null && _j !== void 0 ? _j : '') }))] }), columns && columns.length > 2 && (jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 text-xs pt-1", children: columns.slice(2).map((col) => {
|
|
3728
|
+
const val = col.render ? col.render(item) : get(item, col.name);
|
|
3729
|
+
if (val === null || val === undefined || val === '')
|
|
3730
|
+
return null;
|
|
3731
|
+
return (jsxRuntime.jsxs("div", { className: "min-w-0", children: [jsxRuntime.jsx("span", { className: "text-gray-400 dark:text-gray-500 font-medium block truncate", children: col.label }), jsxRuntime.jsx("span", { className: "text-gray-800 dark:text-gray-200 font-semibold block truncate mt-0.5", children: val })] }, String(col.name)));
|
|
3732
|
+
}) }))] }));
|
|
3733
|
+
if (actions && (((_k = actions.leftActions) === null || _k === void 0 ? void 0 : _k.length) || ((_l = actions.rightActions) === null || _l === void 0 ? void 0 : _l.length))) {
|
|
3734
|
+
return (jsxRuntime.jsx(SwipeableRow, { leftActions: actions.leftActions, rightActions: actions.rightActions, children: contentNode }, key));
|
|
3735
|
+
}
|
|
3736
|
+
return jsxRuntime.jsx("div", { children: contentNode }, key);
|
|
3737
|
+
})) }), pagination && pagination.total > 0 && (jsxRuntime.jsx("div", { className: "pt-2 flex justify-center", children: jsxRuntime.jsx(Pagination, { ...pagination, onChange: (newPag) => setPagination === null || setPagination === void 0 ? void 0 : setPagination(newPag) }) }))] }));
|
|
3738
|
+
}
|
|
3739
|
+
DataList.displayName = 'DataList';
|
|
2131
3740
|
|
|
2132
3741
|
const sizeClasses$1 = {
|
|
2133
3742
|
sm: {
|
|
2134
|
-
input: 'px-2.5 py-1 text-xs leading-5 min-h-[
|
|
3743
|
+
input: 'px-2.5 py-1.5 text-xs leading-5 min-h-[32px]',
|
|
2135
3744
|
group: 'w-8 text-xs',
|
|
2136
3745
|
icon: 'size-3.5',
|
|
2137
3746
|
badgeSize: 'sm',
|
|
@@ -2150,7 +3759,10 @@ const sizeClasses$1 = {
|
|
|
2150
3759
|
},
|
|
2151
3760
|
};
|
|
2152
3761
|
const SelectBox = React.forwardRef((props, forwardedRef) => {
|
|
2153
|
-
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;
|
|
3762
|
+
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;
|
|
3763
|
+
if (props.asBottomSheet || props.mobileMode === 'sheet') {
|
|
3764
|
+
return jsxRuntime.jsx(MobilePicker, { ...props });
|
|
3765
|
+
}
|
|
2154
3766
|
const hasError = Boolean(error);
|
|
2155
3767
|
const [query, setQuery] = React.useState('');
|
|
2156
3768
|
const debouncedQuery = useDebounce(query, 500);
|
|
@@ -2198,6 +3810,49 @@ const SelectBox = React.forwardRef((props, forwardedRef) => {
|
|
|
2198
3810
|
const getValue = React.useCallback((opt) => {
|
|
2199
3811
|
return typeof opt === 'string' ? opt : opt[valueKey];
|
|
2200
3812
|
}, [valueKey]);
|
|
3813
|
+
const createFreeTextOption = React.useCallback((text) => {
|
|
3814
|
+
const sample = allOptions[0] || (Array.isArray(selected) ? selected[0] : selected);
|
|
3815
|
+
if (typeof sample === 'string' ||
|
|
3816
|
+
(!sample && typeof labelKey === 'string' && labelKey === 'label')) {
|
|
3817
|
+
return text;
|
|
3818
|
+
}
|
|
3819
|
+
return {
|
|
3820
|
+
[labelKey]: text,
|
|
3821
|
+
[valueKey]: text,
|
|
3822
|
+
};
|
|
3823
|
+
}, [allOptions, selected, labelKey, valueKey]);
|
|
3824
|
+
const handleFreeTextCommit = React.useCallback((queryText) => {
|
|
3825
|
+
const trimmed = queryText.trim();
|
|
3826
|
+
if (!trimmed)
|
|
3827
|
+
return;
|
|
3828
|
+
const existing = allOptions.find((opt) => {
|
|
3829
|
+
const display = getDisplayValue(opt);
|
|
3830
|
+
return (display === null || display === void 0 ? void 0 : display.toLowerCase()) === trimmed.toLowerCase();
|
|
3831
|
+
});
|
|
3832
|
+
const valueToCommit = existing || createFreeTextOption(trimmed);
|
|
3833
|
+
if (multiple) {
|
|
3834
|
+
const current = isArray(selected) ? selected : [];
|
|
3835
|
+
const alreadySelected = current.some((item) => { var _a; return ((_a = getDisplayValue(item)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === trimmed.toLowerCase(); });
|
|
3836
|
+
if (!alreadySelected) {
|
|
3837
|
+
if (maxSelection && current.length >= maxSelection)
|
|
3838
|
+
return;
|
|
3839
|
+
onChange([...current, valueToCommit]);
|
|
3840
|
+
}
|
|
3841
|
+
setQuery('');
|
|
3842
|
+
}
|
|
3843
|
+
else {
|
|
3844
|
+
onChange(valueToCommit);
|
|
3845
|
+
setQuery('');
|
|
3846
|
+
}
|
|
3847
|
+
}, [
|
|
3848
|
+
allOptions,
|
|
3849
|
+
getDisplayValue,
|
|
3850
|
+
createFreeTextOption,
|
|
3851
|
+
multiple,
|
|
3852
|
+
selected,
|
|
3853
|
+
maxSelection,
|
|
3854
|
+
onChange,
|
|
3855
|
+
]);
|
|
2201
3856
|
const removeSelection = (idx) => {
|
|
2202
3857
|
var _a;
|
|
2203
3858
|
if (!isArray(selected))
|
|
@@ -2270,11 +3925,25 @@ const SelectBox = React.forwardRef((props, forwardedRef) => {
|
|
|
2270
3925
|
if (async && debouncedQuery)
|
|
2271
3926
|
handleSearch(debouncedQuery);
|
|
2272
3927
|
}, [debouncedQuery, async, handleSearch]);
|
|
3928
|
+
const normalizedSelected = React.useMemo(() => {
|
|
3929
|
+
if (multiple) {
|
|
3930
|
+
if (Array.isArray(selected))
|
|
3931
|
+
return selected;
|
|
3932
|
+
if (selected !== null && selected !== undefined)
|
|
3933
|
+
return [selected];
|
|
3934
|
+
return [];
|
|
3935
|
+
}
|
|
3936
|
+
else {
|
|
3937
|
+
if (Array.isArray(selected))
|
|
3938
|
+
return selected.length > 0 ? selected[0] : null;
|
|
3939
|
+
return selected !== null && selected !== void 0 ? selected : null;
|
|
3940
|
+
}
|
|
3941
|
+
}, [multiple, selected]);
|
|
2273
3942
|
const isAllSelected = React.useMemo(() => {
|
|
2274
|
-
if (!multiple || !Array.isArray(
|
|
3943
|
+
if (!multiple || !Array.isArray(normalizedSelected) || !allOptions.length)
|
|
2275
3944
|
return false;
|
|
2276
|
-
return allOptions.length ===
|
|
2277
|
-
}, [multiple,
|
|
3945
|
+
return allOptions.length === normalizedSelected.length;
|
|
3946
|
+
}, [multiple, normalizedSelected, allOptions]);
|
|
2278
3947
|
const handleToggleSelectAll = () => {
|
|
2279
3948
|
if (isAllSelected) {
|
|
2280
3949
|
onChange([]);
|
|
@@ -2284,30 +3953,69 @@ const SelectBox = React.forwardRef((props, forwardedRef) => {
|
|
|
2284
3953
|
}
|
|
2285
3954
|
};
|
|
2286
3955
|
const hasLeftGroup = leftGroup != null && leftGroup !== undefined;
|
|
2287
|
-
return (jsxRuntime.jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), ref: containerRef, children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.jsxs(react.Combobox, { multiple: multiple, immediate: immediate, name: name, value:
|
|
2288
|
-
(
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
3956
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), ref: containerRef, children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, "aria-required": required, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.jsxs(react.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 ? (jsxRuntime.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 && (jsxRuntime.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) &&
|
|
3957
|
+
(normalizedSelected === null || normalizedSelected === void 0 ? void 0 : normalizedSelected.length) > 0 &&
|
|
3958
|
+
normalizedSelected.map((option, idx) => (jsxRuntime.jsx(Badge, { theme: "secondary", size: currentSize.badgeSize, removable: !disabled, onRemove: () => removeSelection(idx), children: getDisplayValue(option) }, `${getValue(option)}-${idx}`))), jsxRuntime.jsx(react.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) => {
|
|
3959
|
+
const val = e.target.value;
|
|
3960
|
+
if (allowFreeText && multiple && val.includes(',')) {
|
|
3961
|
+
const parts = val.split(',');
|
|
3962
|
+
parts.forEach((p) => {
|
|
3963
|
+
if (p.trim())
|
|
3964
|
+
handleFreeTextCommit(p.trim());
|
|
3965
|
+
});
|
|
3966
|
+
setQuery('');
|
|
3967
|
+
}
|
|
3968
|
+
else {
|
|
3969
|
+
setQuery(val);
|
|
3970
|
+
}
|
|
3971
|
+
}, id: id, ref: inputRef, onKeyDown: (e) => {
|
|
3972
|
+
if (allowFreeText && (e.key === 'Enter' || e.key === ',') && query.trim()) {
|
|
3973
|
+
e.preventDefault();
|
|
3974
|
+
handleFreeTextCommit(query.replace(/,/g, ''));
|
|
3975
|
+
}
|
|
3976
|
+
else if (multiple && e.key === 'Backspace' && !query) {
|
|
3977
|
+
if (Array.isArray(normalizedSelected) && normalizedSelected.length > 0) {
|
|
3978
|
+
removeSelection(normalizedSelected.length - 1);
|
|
2293
3979
|
}
|
|
2294
3980
|
}
|
|
2295
|
-
},
|
|
3981
|
+
}, onBlur: () => {
|
|
3982
|
+
if (allowFreeText && query.trim()) {
|
|
3983
|
+
handleFreeTextCommit(query.replace(/,/g, ''));
|
|
3984
|
+
}
|
|
3985
|
+
}, "data-testid": "combobox-input" }), jsxRuntime.jsx(react.ComboboxButton, { className: "group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center", "data-testid": "combobox-button", children: jsxRuntime.jsx(SvgChevronDown, { className: chevronIconClass }) })] })) : (jsxRuntime.jsxs("div", { className: "relative", ref: forwardedRef, children: [hasLeftGroup && (jsxRuntime.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 })), jsxRuntime.jsx(react.ComboboxInput, { "aria-label": name, displayValue: (option) => (option ? getDisplayValue(option) : null), autoComplete: "off", placeholder: placeholder, onChange: (event) => setQuery(event.target.value), onKeyDown: (e) => {
|
|
3986
|
+
if (allowFreeText && e.key === 'Enter' && query.trim()) {
|
|
3987
|
+
e.preventDefault();
|
|
3988
|
+
handleFreeTextCommit(query);
|
|
3989
|
+
}
|
|
3990
|
+
}, onBlur: () => {
|
|
3991
|
+
if (allowFreeText && query.trim()) {
|
|
3992
|
+
handleFreeTextCommit(query);
|
|
3993
|
+
}
|
|
3994
|
+
}, onFocus: () => {
|
|
3995
|
+
setQuery('');
|
|
3996
|
+
}, 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) && (jsxRuntime.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: jsxRuntime.jsx(SvgX, { className: "size-4 stroke-gray-500 dark:stroke-gray-300" }) })), jsxRuntime.jsx(react.ComboboxButton, { className: "group absolute inset-y-0 right-0 px-2.5 flex items-center justify-center", "data-testid": "combobox-button", children: jsxRuntime.jsx(SvgChevronDown, { className: chevronIconClass }) })] })), jsxRuntime.jsxs(react.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 && (jsxRuntime.jsxs("div", { className: "pb-1 mb-1 border-b border-[var(--ui-border-muted)] px-3 pt-1 flex items-center justify-between", children: [jsxRuntime.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' }), jsxRuntime.jsxs("span", { className: "text-[11px] font-medium text-gray-400", children: [Array.isArray(normalizedSelected) ? normalizedSelected.length : 0, " of", ' ', allOptions.length] })] })), optionsLoading ? (jsxRuntime.jsx(BodyText, { "data-testid": "options-loading", className: "flex items-center justify-center py-2 px-3 select-none", children: jsxRuntime.jsx(Loader, { size: "sm" }) })) : shouldShowTypeToSearch ? (jsxRuntime.jsx(BodyText, { className: "flex items-center justify-between py-2 px-3 select-none", children: "Type to search..." })) : (jsxRuntime.jsxs("div", { children: [allowFreeText &&
|
|
3997
|
+
query.trim() &&
|
|
3998
|
+
!allOptions.some((opt) => { var _a; return ((_a = getDisplayValue(opt)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === query.trim().toLowerCase(); }) && (jsxRuntime.jsx(react.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: jsxRuntime.jsxs("span", { children: ["Use \"", query.trim(), "\""] }) }, `freetext-${query.trim()}`)), filteredGroups
|
|
2296
3999
|
? filteredGroups.map((grp, gIdx) => (jsxRuntime.jsxs("div", { children: [jsxRuntime.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) => {
|
|
2297
4000
|
const optVal = getValue(option);
|
|
2298
4001
|
const isOptSelected = multiple
|
|
2299
|
-
? isArray(
|
|
2300
|
-
|
|
2301
|
-
|
|
4002
|
+
? isArray(normalizedSelected) &&
|
|
4003
|
+
normalizedSelected.some((s) => getValue(s) === optVal)
|
|
4004
|
+
: normalizedSelected && getValue(normalizedSelected) === optVal;
|
|
4005
|
+
return (jsxRuntime.jsx(react.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))) : (jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600", children: [jsxRuntime.jsx("span", { className: "text-sm/6", children: getDisplayValue(option) }), jsxRuntime.jsx(SvgCheck, { className: "invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible" })] })) }, optVal));
|
|
2302
4006
|
})] }, gIdx)))
|
|
2303
4007
|
: /* Render Standard Flat Options */
|
|
2304
4008
|
filteredOptions.map((option) => {
|
|
2305
4009
|
const optVal = getValue(option);
|
|
2306
4010
|
const isOptSelected = multiple
|
|
2307
|
-
? isArray(
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
4011
|
+
? isArray(normalizedSelected) &&
|
|
4012
|
+
normalizedSelected.some((s) => getValue(s) === optVal)
|
|
4013
|
+
: normalizedSelected && getValue(normalizedSelected) === optVal;
|
|
4014
|
+
return (jsxRuntime.jsx(react.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))) : (jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 text-gray-900 dark:text-white group-data-[selected]:text-blue-600", children: [jsxRuntime.jsx("span", { className: "text-sm/6", children: getDisplayValue(option) }), jsxRuntime.jsx(SvgCheck, { className: "invisible size-5 dark:stroke-gray-300 group-data-[selected]:visible" })] })) }, optVal));
|
|
4015
|
+
}), filteredOptions.length === 0 &&
|
|
4016
|
+
!(filteredGroups === null || filteredGroups === void 0 ? void 0 : filteredGroups.length) &&
|
|
4017
|
+
!allowFreeText &&
|
|
4018
|
+
!(allowAdd && query.trim()) && (jsxRuntime.jsxs("div", { "data-testid": "no-result-found", className: "flex items-center gap-2 py-1.5 px-3 select-none", children: [jsxRuntime.jsx(TextContent, { muted: true, small: true, children: noOptionsText }), jsxRuntime.jsx(TextContent, { strong: true, small: true, children: query })] })), !allowFreeText && allowAdd && Boolean(query.trim()) && (jsxRuntime.jsx(react.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: jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntime.jsx(SvgCirclePlus, { className: "size-4.5" }), jsxRuntime.jsxs(TextContent, { children: [addNewText, " \"", query, "\""] })] }) }, `add-${query.trim()}`))] }))] })] }), showErrorMessage && error && (jsxRuntime.jsx("div", { className: "mt-1", children: jsxRuntime.jsx(TextContent, { error: true, small: true, children: error }) })), !error && helperText && (jsxRuntime.jsx("div", { className: "mt-1", children: jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText }) }))] }));
|
|
2311
4019
|
});
|
|
2312
4020
|
SelectBox.displayName = 'SelectBox';
|
|
2313
4021
|
|
|
@@ -2341,10 +4049,15 @@ Skeleton.displayName = 'Skeleton';
|
|
|
2341
4049
|
|
|
2342
4050
|
const MinusIcon = ({ className }) => (jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: jsxRuntime.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) }));
|
|
2343
4051
|
const PlusIcon = ({ className }) => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, "aria-hidden": "true", children: [jsxRuntime.jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), jsxRuntime.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }));
|
|
4052
|
+
const CONTAINER_SIZE_CLASS = {
|
|
4053
|
+
sm: 'h-8 text-xs',
|
|
4054
|
+
md: 'h-10 text-sm',
|
|
4055
|
+
lg: 'h-12 text-base',
|
|
4056
|
+
};
|
|
2344
4057
|
const BUTTON_SIZE_CLASS = {
|
|
2345
|
-
sm: '
|
|
2346
|
-
md: '
|
|
2347
|
-
lg: '
|
|
4058
|
+
sm: 'w-7.5 h-full',
|
|
4059
|
+
md: 'w-9.5 h-full',
|
|
4060
|
+
lg: 'w-11 h-full',
|
|
2348
4061
|
};
|
|
2349
4062
|
const ICON_SIZE_CLASS = {
|
|
2350
4063
|
sm: 'size-3.5',
|
|
@@ -2352,12 +4065,15 @@ const ICON_SIZE_CLASS = {
|
|
|
2352
4065
|
lg: 'size-4.5',
|
|
2353
4066
|
};
|
|
2354
4067
|
const INPUT_TEXT_CLASS = {
|
|
2355
|
-
sm: 'w-12 text-xs
|
|
2356
|
-
md: 'w-16 text-sm
|
|
2357
|
-
lg: 'w-20 text-base
|
|
4068
|
+
sm: 'w-12 text-xs',
|
|
4069
|
+
md: 'w-16 text-sm',
|
|
4070
|
+
lg: 'w-20 text-base',
|
|
2358
4071
|
};
|
|
2359
4072
|
const QuantityStepper = React.forwardRef((props, ref) => {
|
|
2360
|
-
const { value, onChange, min = 0, max = 99999, step = 1, label, size = 'md', prefix, suffix, disabled = false, className, onFocus, ...restProps } = props;
|
|
4073
|
+
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;
|
|
4074
|
+
const autoId = React.useId();
|
|
4075
|
+
const stepperId = customId || `stepper-${autoId}`;
|
|
4076
|
+
const hasError = Boolean(error);
|
|
2361
4077
|
const handleDecrement = () => {
|
|
2362
4078
|
if (disabled)
|
|
2363
4079
|
return;
|
|
@@ -2383,10 +4099,18 @@ const QuantityStepper = React.forwardRef((props, ref) => {
|
|
|
2383
4099
|
};
|
|
2384
4100
|
const isAtMin = disabled || value <= min;
|
|
2385
4101
|
const isAtMax = disabled || value >= max;
|
|
2386
|
-
return (jsxRuntime.jsxs("div", { className: buildClassName('flex flex-col gap-1 inline-flex', className), children: [label && (jsxRuntime.
|
|
4102
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('flex flex-col gap-1 inline-flex', className), children: [label && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [jsxRuntime.jsx(Label, { htmlFor: stepperId, className: disabled ? 'opacity-70 cursor-not-allowed' : '', children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.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
|
|
4103
|
+
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
4104
|
+
: 'outline-[var(--ui-border)]', disabled
|
|
4105
|
+
? 'pointer-events-none bg-gray-100 dark:bg-gray-800 outline-[var(--ui-border-muted)]'
|
|
4106
|
+
: '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: [jsxRuntime.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
|
|
4107
|
+
? 'opacity-30 hover:bg-transparent cursor-not-allowed'
|
|
4108
|
+
: 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60'), "data-testid": "stepper-decrement", children: jsxRuntime.jsx(MinusIcon, { className: ICON_SIZE_CLASS[size] }) }), prefix && (jsxRuntime.jsx("span", { className: "pl-1 text-gray-400 dark:text-gray-400 select-none text-xs shrink-0", children: prefix })), jsxRuntime.jsx("input", { ref: ref, id: stepperId, type: "number", min: min, max: max, step: step, value: value === 0 ? '' : value, placeholder: "0", disabled: disabled, onFocus: (e) => {
|
|
2387
4109
|
e.target.select();
|
|
2388
4110
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
|
|
2389
|
-
}, 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 && jsxRuntime.jsx("span", { className: "pr-1 text-
|
|
4111
|
+
}, 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 && (jsxRuntime.jsx("span", { className: "pr-1 text-gray-500 dark:text-gray-400 select-none text-xs shrink-0", children: suffix })), jsxRuntime.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
|
|
4112
|
+
? 'opacity-30 hover:bg-transparent cursor-not-allowed'
|
|
4113
|
+
: 'cursor-pointer hover:bg-gray-100/80 dark:hover:bg-gray-600/60'), "data-testid": "stepper-increment", children: jsxRuntime.jsx(PlusIcon, { className: ICON_SIZE_CLASS[size] }) })] }), (showErrorMessage && error) || helperText ? (jsxRuntime.jsx("div", { className: "flex items-center justify-between gap-2 mt-0.5", children: showErrorMessage && error ? (jsxRuntime.jsx(TextContent, { xsmall: true, className: "text-red-500 dark:text-red-400 font-medium", children: error })) : helperText ? (jsxRuntime.jsx(TextContent, { xsmall: true, muted: true, children: helperText })) : null })) : null] }));
|
|
2390
4114
|
});
|
|
2391
4115
|
QuantityStepper.displayName = 'QuantityStepper';
|
|
2392
4116
|
|
|
@@ -2432,7 +4156,7 @@ const SegmentedControl = React.forwardRef((props, ref) => {
|
|
|
2432
4156
|
onChange(enabledOptions[enabledOptions.length - 1].value);
|
|
2433
4157
|
}
|
|
2434
4158
|
};
|
|
2435
|
-
return (jsxRuntime.jsx("div", { ref: ref, role: "tablist", "aria-orientation": "horizontal", className: buildClassName('inline-flex items-center border border-
|
|
4159
|
+
return (jsxRuntime.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) => {
|
|
2436
4160
|
const isSelected = value === option.value;
|
|
2437
4161
|
const isOptionDisabled = disabled || option.disabled;
|
|
2438
4162
|
return (jsxRuntime.jsxs("button", { type: "button", role: "tab", "aria-selected": isSelected, "aria-disabled": isOptionDisabled, tabIndex: isSelected && !isOptionDisabled ? 0 : -1, disabled: isOptionDisabled, title: option.title, onClick: () => {
|
|
@@ -2493,7 +4217,7 @@ const StickyActionBar = React.forwardRef((props, ref) => {
|
|
|
2493
4217
|
: position === 'sticky'
|
|
2494
4218
|
? 'sticky bottom-0 z-30'
|
|
2495
4219
|
: 'relative z-10';
|
|
2496
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { ref: ref, className: buildClassName(positionClass, 'border-t border-
|
|
4220
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.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: jsxRuntime.jsxs("div", { className: buildClassName('mx-auto flex items-center justify-between gap-3', containerMaxWidth), children: [summaryContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: drawerContent ? (jsxRuntime.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: [jsxRuntime.jsx("div", { children: summaryContent }), jsxRuntime.jsx(ChevronUpIcon, { className: "size-4 text-[var(--ui-primary)] dark:text-blue-400 shrink-0" })] })) : (jsxRuntime.jsx("div", { children: summaryContent })) })), actionsContent && (jsxRuntime.jsx("div", { className: "flex items-center gap-2 shrink-0 ml-auto", "data-testid": "actions-stack", children: actionsContent }))] }) }), drawerContent && (jsxRuntime.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 }))] }));
|
|
2497
4221
|
});
|
|
2498
4222
|
StickyActionBar.displayName = 'StickyActionBar';
|
|
2499
4223
|
|
|
@@ -2523,7 +4247,7 @@ function buildTabClass({ selected, variant, stretch, isVertical, tabClass, }) {
|
|
|
2523
4247
|
variantClass = isVertical
|
|
2524
4248
|
? buildClassName('px-3 py-2 w-full text-left border-l-2', selected
|
|
2525
4249
|
? 'border-[var(--ui-primary)] text-gray-900 dark:text-white'
|
|
2526
|
-
: 'border-transparent text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:border-
|
|
4250
|
+
: 'border-transparent text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:border-[var(--ui-border)]')
|
|
2527
4251
|
: buildClassName('px-3 py-1.5 relative text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white', selected &&
|
|
2528
4252
|
'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)]');
|
|
2529
4253
|
break;
|
|
@@ -2541,6 +4265,89 @@ function buildTabClass({ selected, variant, stretch, isVertical, tabClass, }) {
|
|
|
2541
4265
|
return buildClassName(base, variantClass, tabClass);
|
|
2542
4266
|
}
|
|
2543
4267
|
|
|
4268
|
+
function SwipeableTabs({ items, activeId: externalActiveId, defaultActiveId, onChange, swipeable = true, threshold = 50, headerVariant = 'default', containerClass = '', headerClass = '', contentClass = '', }) {
|
|
4269
|
+
var _a;
|
|
4270
|
+
const [internalActiveId, setInternalActiveId] = React.useState(defaultActiveId || ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.id) || '');
|
|
4271
|
+
const activeId = externalActiveId !== undefined ? externalActiveId : internalActiveId;
|
|
4272
|
+
const activeIndex = Math.max(0, items.findIndex((item) => item.id === activeId));
|
|
4273
|
+
const touchStartX = React.useRef(0);
|
|
4274
|
+
const touchStartY = React.useRef(0);
|
|
4275
|
+
const touchDeltaX = React.useRef(0);
|
|
4276
|
+
const isSwipingHorizontal = React.useRef(null);
|
|
4277
|
+
const handleTabChange = (item) => {
|
|
4278
|
+
if (item.disabled)
|
|
4279
|
+
return;
|
|
4280
|
+
setInternalActiveId(item.id);
|
|
4281
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(item.id);
|
|
4282
|
+
};
|
|
4283
|
+
const handleTouchStart = (e) => {
|
|
4284
|
+
if (!swipeable)
|
|
4285
|
+
return;
|
|
4286
|
+
touchStartX.current = e.touches[0].clientX;
|
|
4287
|
+
touchStartY.current = e.touches[0].clientY;
|
|
4288
|
+
touchDeltaX.current = 0;
|
|
4289
|
+
isSwipingHorizontal.current = null;
|
|
4290
|
+
};
|
|
4291
|
+
const handleTouchMove = (e) => {
|
|
4292
|
+
if (!swipeable)
|
|
4293
|
+
return;
|
|
4294
|
+
const currentX = e.touches[0].clientX;
|
|
4295
|
+
const currentY = e.touches[0].clientY;
|
|
4296
|
+
const deltaX = currentX - touchStartX.current;
|
|
4297
|
+
const deltaY = currentY - touchStartY.current;
|
|
4298
|
+
if (isSwipingHorizontal.current === null) {
|
|
4299
|
+
if (Math.abs(deltaX) > 8 || Math.abs(deltaY) > 8) {
|
|
4300
|
+
isSwipingHorizontal.current = Math.abs(deltaX) > Math.abs(deltaY);
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
if (isSwipingHorizontal.current) {
|
|
4304
|
+
touchDeltaX.current = deltaX;
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
const handleTouchEnd = () => {
|
|
4308
|
+
if (!swipeable || !isSwipingHorizontal.current)
|
|
4309
|
+
return;
|
|
4310
|
+
const deltaX = touchDeltaX.current;
|
|
4311
|
+
if (Math.abs(deltaX) >= threshold) {
|
|
4312
|
+
if (deltaX < 0 && activeIndex < items.length - 1) {
|
|
4313
|
+
// Swiped Left -> Go to Next Tab
|
|
4314
|
+
const nextItem = items[activeIndex + 1];
|
|
4315
|
+
if (nextItem && !nextItem.disabled) {
|
|
4316
|
+
handleTabChange(nextItem);
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
else if (deltaX > 0 && activeIndex > 0) {
|
|
4320
|
+
// Swiped Right -> Go to Previous Tab
|
|
4321
|
+
const prevItem = items[activeIndex - 1];
|
|
4322
|
+
if (prevItem && !prevItem.disabled) {
|
|
4323
|
+
handleTabChange(prevItem);
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4327
|
+
touchDeltaX.current = 0;
|
|
4328
|
+
isSwipingHorizontal.current = null;
|
|
4329
|
+
};
|
|
4330
|
+
return (jsxRuntime.jsxs("div", { className: buildClassName('w-full flex flex-col', containerClass), "data-testid": "swipeable-tabs", children: [jsxRuntime.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' &&
|
|
4331
|
+
'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) => {
|
|
4332
|
+
const isActive = item.id === activeId;
|
|
4333
|
+
if (headerVariant === 'segmented') {
|
|
4334
|
+
return (jsxRuntime.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
|
|
4335
|
+
? 'bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow-xs'
|
|
4336
|
+
: '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 && jsxRuntime.jsx("span", { className: "text-sm", children: item.icon }), jsxRuntime.jsx("span", { children: item.label }), item.badge !== undefined && (jsxRuntime.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));
|
|
4337
|
+
}
|
|
4338
|
+
if (headerVariant === 'pills') {
|
|
4339
|
+
return (jsxRuntime.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
|
|
4340
|
+
? 'bg-blue-600 text-white shadow-xs'
|
|
4341
|
+
: '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 && jsxRuntime.jsx("span", { className: "text-sm", children: item.icon }), jsxRuntime.jsx("span", { children: item.label }), item.badge !== undefined && (jsxRuntime.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));
|
|
4342
|
+
}
|
|
4343
|
+
// Default Underline Tab Header
|
|
4344
|
+
return (jsxRuntime.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
|
|
4345
|
+
? 'border-blue-600 dark:border-blue-400 text-blue-600 dark:text-blue-400'
|
|
4346
|
+
: '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 && jsxRuntime.jsx("span", { className: "text-sm", children: item.icon }), jsxRuntime.jsx("span", { children: item.label }), item.badge !== undefined && (jsxRuntime.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));
|
|
4347
|
+
}) }), jsxRuntime.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: jsxRuntime.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) => (jsxRuntime.jsx("div", { className: "w-full shrink-0 min-w-full", "data-testid": `swipeable-tab-panel-${item.id}`, children: item.content }, item.id))) }) })] }));
|
|
4348
|
+
}
|
|
4349
|
+
SwipeableTabs.displayName = 'SwipeableTabs';
|
|
4350
|
+
|
|
2544
4351
|
const sizeClasses = {
|
|
2545
4352
|
sm: {
|
|
2546
4353
|
textarea: 'px-2.5 py-1.5 text-xs leading-5 min-h-[60px]',
|
|
@@ -2588,7 +4395,7 @@ const Textarea = React.forwardRef((props, ref) => {
|
|
|
2588
4395
|
const currentSize = sizeClasses[size] || sizeClasses.md;
|
|
2589
4396
|
return (jsxRuntime.jsxs("div", { className: buildClassName('group', hasError && 'has-error', containerClass), children: [label && (jsxRuntime.jsxs("div", { className: buildClassName('flex items-center justify-between mb-1.5', labelWrapperClass), children: [jsxRuntime.jsx(Label, { className: labelClass, htmlFor: id, children: label }), labelHint && jsxRuntime.jsx(TextContent, { xsmall: true, children: labelHint })] })), jsxRuntime.jsxs("div", { className: "relative", children: [hasLeftGroup && (jsxRuntime.jsx("span", { className: "absolute top-2.5 left-3 flex items-center justify-center text-gray-400 dark:text-gray-500", children: leftGroup })), jsxRuntime.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
|
|
2590
4397
|
? '!outline-red-500 !ring-1 !ring-red-500/50 dark:!outline-red-500'
|
|
2591
|
-
: 'outline-
|
|
4398
|
+
: '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 && (jsxRuntime.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 ? (jsxRuntime.jsxs("div", { className: "mt-1.5 flex items-center justify-between gap-2 text-xs", children: [jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: showErrorMessage && error ? (jsxRuntime.jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsxRuntime.jsx(TextContent, { muted: true, small: true, children: helperText })) : null }), showCount && (jsxRuntime.jsxs("span", { className: buildClassName('text-[11px] font-medium shrink-0 ml-auto', maxLength && charLength >= maxLength
|
|
2592
4399
|
? 'text-red-500 font-semibold'
|
|
2593
4400
|
: 'text-gray-400 dark:text-gray-500'), children: [charLength, maxLength ? ` / ${maxLength}` : ''] }))] })) : null] }));
|
|
2594
4401
|
});
|
|
@@ -2623,10 +4430,10 @@ const progressBarColorMap = {
|
|
|
2623
4430
|
};
|
|
2624
4431
|
const variantStyleMap = {
|
|
2625
4432
|
accent: {
|
|
2626
|
-
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-
|
|
2627
|
-
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-
|
|
2628
|
-
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-
|
|
2629
|
-
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-
|
|
4433
|
+
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)]',
|
|
4434
|
+
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)]',
|
|
4435
|
+
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)]',
|
|
4436
|
+
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)]',
|
|
2630
4437
|
},
|
|
2631
4438
|
filled: {
|
|
2632
4439
|
success: 'bg-[var(--ui-success)] text-white shadow-lg',
|
|
@@ -2966,7 +4773,10 @@ const useIsMobile = () => {
|
|
|
2966
4773
|
React.useEffect(() => {
|
|
2967
4774
|
const detect = () => {
|
|
2968
4775
|
const width = window.innerWidth;
|
|
2969
|
-
const isTouch = navigator.maxTouchPoints > 1 ||
|
|
4776
|
+
const isTouch = (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1) ||
|
|
4777
|
+
(typeof window !== 'undefined' &&
|
|
4778
|
+
typeof window.matchMedia === 'function' &&
|
|
4779
|
+
window.matchMedia('(pointer: coarse)').matches);
|
|
2970
4780
|
setIsMobile(width < 600 && isTouch);
|
|
2971
4781
|
};
|
|
2972
4782
|
detect();
|
|
@@ -2998,10 +4808,12 @@ const useIsTabletOrMobile = () => {
|
|
|
2998
4808
|
};
|
|
2999
4809
|
|
|
3000
4810
|
exports.Accordion = Accordion;
|
|
4811
|
+
exports.ActionSheet = ActionSheet;
|
|
3001
4812
|
exports.Alert = Alert;
|
|
3002
4813
|
exports.Badge = Badge;
|
|
3003
4814
|
exports.Banner = Banner;
|
|
3004
4815
|
exports.BodyText = BodyText;
|
|
4816
|
+
exports.BottomNavigation = BottomNavigation;
|
|
3005
4817
|
exports.Breadcrumb = Breadcrumb;
|
|
3006
4818
|
exports.Button = Button;
|
|
3007
4819
|
exports.ButtonGroup = ButtonGroup;
|
|
@@ -3015,6 +4827,7 @@ exports.CardTitle = CardTitle;
|
|
|
3015
4827
|
exports.Checkbox = Checkbox;
|
|
3016
4828
|
exports.CheckboxGroup = CheckboxGroup;
|
|
3017
4829
|
exports.DOTS = DOTS;
|
|
4830
|
+
exports.DataList = DataList;
|
|
3018
4831
|
exports.DataTable = DataTable;
|
|
3019
4832
|
exports.DetailedInformation = DetailedInformation;
|
|
3020
4833
|
exports.Dot = Dot;
|
|
@@ -3022,14 +4835,24 @@ exports.Drawer = Drawer;
|
|
|
3022
4835
|
exports.Dropdown = Dropdown;
|
|
3023
4836
|
exports.EmptyState = EmptyState;
|
|
3024
4837
|
exports.EmptyTableRow = EmptyTableRow;
|
|
4838
|
+
exports.Flex = Flex;
|
|
4839
|
+
exports.FlexItem = FlexItem;
|
|
4840
|
+
exports.FloatingActionButton = FloatingActionButton;
|
|
4841
|
+
exports.Grid = Grid;
|
|
4842
|
+
exports.GridCol = GridCol;
|
|
3025
4843
|
exports.HeadingText = HeadingText;
|
|
3026
4844
|
exports.Input = Input;
|
|
3027
4845
|
exports.Label = Label;
|
|
3028
4846
|
exports.Loader = Loader;
|
|
4847
|
+
exports.MobileHeader = MobileHeader;
|
|
4848
|
+
exports.MobilePicker = MobilePicker;
|
|
4849
|
+
exports.MobileStepper = MobileStepper;
|
|
3029
4850
|
exports.PASSWORD_PLACEHOLDER = PASSWORD_PLACEHOLDER;
|
|
3030
4851
|
exports.PASSWORD_TYPE = PASSWORD_TYPE;
|
|
3031
4852
|
exports.Pagination = Pagination;
|
|
3032
4853
|
exports.PasswordInput = PasswordInput;
|
|
4854
|
+
exports.PinInput = PinInput;
|
|
4855
|
+
exports.PullToRefresh = PullToRefresh;
|
|
3033
4856
|
exports.QuantityStepper = QuantityStepper;
|
|
3034
4857
|
exports.Radio = Radio;
|
|
3035
4858
|
exports.RadioGroup = RadioGroup;
|
|
@@ -3042,6 +4865,8 @@ exports.Skeleton = Skeleton;
|
|
|
3042
4865
|
exports.SortIconMap = SortIconMap;
|
|
3043
4866
|
exports.StatusPill = StatusPill;
|
|
3044
4867
|
exports.StickyActionBar = StickyActionBar;
|
|
4868
|
+
exports.SwipeableRow = SwipeableRow;
|
|
4869
|
+
exports.SwipeableTabs = SwipeableTabs;
|
|
3045
4870
|
exports.Table = Table;
|
|
3046
4871
|
exports.TableBody = TableBody;
|
|
3047
4872
|
exports.TableCell = TableCell;
|
|
@@ -3055,6 +4880,7 @@ exports.Textarea = Textarea;
|
|
|
3055
4880
|
exports.Toast = Toast;
|
|
3056
4881
|
exports.ToastProvider = ToastProvider;
|
|
3057
4882
|
exports.VirtualizedDataTable = VirtualizedDataTable;
|
|
4883
|
+
exports.WheelPicker = WheelPicker;
|
|
3058
4884
|
exports.buildClassName = buildClassName;
|
|
3059
4885
|
exports.buildInputClass = buildInputClass;
|
|
3060
4886
|
exports.evaluatePasswordStrength = evaluatePasswordStrength;
|