@pk-design/react-tailwind 1.5.4 → 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 +3596 -630
- package/dist/react-tailwind.cjs.js.map +1 -1
- package/dist/react-tailwind.es.js +3561 -623
- 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/BodyText/BodyText.d.ts +1 -1
- package/dist/types/components/BodyText/BodyText.types.d.ts +47 -8
- 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/Breadcrumb/Breadcrumb.d.ts +2 -3
- package/dist/types/components/Breadcrumb/Breadcrumb.types.d.ts +43 -10
- package/dist/types/components/Button/Button.types.d.ts +17 -63
- package/dist/types/components/ButtonGroup/ButtonGroup.types.d.ts +16 -0
- package/dist/types/components/Card/Card.d.ts +7 -1
- package/dist/types/components/Card/Card.types.d.ts +73 -42
- package/dist/types/components/Checkbox/Checkbox.types.d.ts +28 -1
- package/dist/types/components/CheckboxGroup/CheckboxGroup.types.d.ts +53 -1
- 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/DetailedInformation/DetailedInformation.d.ts +1 -1
- package/dist/types/components/DetailedInformation/DetailedInformation.types.d.ts +47 -3
- package/dist/types/components/Drawer/Drawer.types.d.ts +37 -13
- package/dist/types/components/Dropdown/Dropdown.types.d.ts +17 -1
- 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/HeadingText/HeadingText.d.ts +7 -7
- package/dist/types/components/HeadingText/HeadingText.test.d.ts +1 -0
- package/dist/types/components/HeadingText/HeadingText.types.d.ts +56 -3
- package/dist/types/components/Input/Input.d.ts +4 -2
- package/dist/types/components/Input/Input.types.d.ts +36 -3
- package/dist/types/components/Loader/index.d.ts +1 -1
- 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/PasswordInput/PasswordInput.d.ts +8 -4
- package/dist/types/components/PasswordInput/PasswordInput.types.d.ts +8 -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.d.ts +3 -0
- package/dist/types/components/QuantityStepper/QuantityStepper.test.d.ts +1 -0
- package/dist/types/components/QuantityStepper/QuantityStepper.types.d.ts +66 -0
- package/dist/types/components/QuantityStepper/index.d.ts +2 -0
- package/dist/types/components/Radio/Radio.d.ts +1 -1
- package/dist/types/components/Radio/Radio.types.d.ts +12 -2
- package/dist/types/components/RadioGroup/RadioGroup.d.ts +1 -1
- package/dist/types/components/RadioGroup/RadioGroup.types.d.ts +41 -13
- package/dist/types/components/RadioSwitch/RadioSwitch.d.ts +0 -4
- package/dist/types/components/RadioSwitch/RadioSwitch.types.d.ts +6 -31
- package/dist/types/components/RangeInput/RangeInput.d.ts +1 -1
- package/dist/types/components/RangeInput/RangeInput.types.d.ts +14 -1
- package/dist/types/components/RangeSlider/RangeSlider.d.ts +1 -1
- package/dist/types/components/RangeSlider/RangeSlider.types.d.ts +28 -13
- package/dist/types/components/SegmentedControl/SegmentedControl.d.ts +3 -0
- package/dist/types/components/SegmentedControl/SegmentedControl.test.d.ts +1 -0
- package/dist/types/components/SegmentedControl/SegmentedControl.types.d.ts +53 -0
- package/dist/types/components/SegmentedControl/index.d.ts +2 -0
- package/dist/types/components/SelectBox/SelectBox.types.d.ts +32 -14
- package/dist/types/components/Skeleton/Skeleton.d.ts +2 -0
- package/dist/types/components/Skeleton/Skeleton.test.d.ts +1 -0
- package/dist/types/components/Skeleton/Skeleton.types.d.ts +38 -0
- package/dist/types/components/Skeleton/index.d.ts +2 -0
- package/dist/types/components/StatusPill/StatusPill.d.ts +2 -0
- package/dist/types/components/StatusPill/StatusPill.test.d.ts +1 -0
- package/dist/types/components/StatusPill/StatusPill.types.d.ts +29 -0
- package/dist/types/components/StatusPill/index.d.ts +2 -0
- package/dist/types/components/StickyActionBar/StickyActionBar.d.ts +2 -0
- package/dist/types/components/StickyActionBar/StickyActionBar.test.d.ts +1 -0
- package/dist/types/components/StickyActionBar/StickyActionBar.types.d.ts +30 -0
- package/dist/types/components/StickyActionBar/index.d.ts +2 -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/TextContent/TextContent.d.ts +2 -2
- package/dist/types/components/TextContent/TextContent.types.d.ts +47 -7
- package/dist/types/components/Textarea/Textarea.types.d.ts +37 -3
- package/dist/types/components/Toast/Toast.d.ts +1 -1
- package/dist/types/components/Toast/Toast.types.d.ts +117 -43
- package/dist/types/components/Toast/ToastProvider.d.ts +3 -6
- 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 +19 -0
- package/package.json +11 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioGroup.js","sources":["../../../../../src/components/RadioGroup/RadioGroup.tsx"],"sourcesContent":["import React, { useMemo } from 'react'\nimport { Radio } from '../Radio'\nimport { Label } from '../Label'\nimport { buildClassName } from '../../utils/build-classname'\nimport { TextContent } from '../TextContent'\nimport type { RadioGroupProps, RadionGroupItem } from './RadioGroup.types'\n\nconst COLUMN_GRID_MAP: Record<number, string> = {\n 1: 'grid-cols-1',\n 2: 'grid-cols-1 md:grid-cols-2',\n 3: 'grid-cols-1 md:grid-cols-3',\n 4: 'grid-cols-1 md:grid-cols-4',\n}\n\nexport const RadioGroup: React.FC<RadioGroupProps> = (props) => {\n const {\n name,\n variant = 'default',\n size = 'md',\n theme = 'primary',\n label,\n labelClass,\n labelWrapperClass,\n labelHint,\n containerClass,\n options,\n value,\n columns,\n disabled = false,\n row,\n error,\n showErrorMessage = true,\n onChange,\n } = props\n\n const items = useMemo(\n () =>\n options?.map((option) =>\n typeof option === 'string'\n ? {\n label: option,\n value: option,\n description: undefined,\n icon: undefined,\n disabled: undefined,\n }\n : option,\n ) ?? [],\n [options],\n )\n\n const isCards = variant === 'cards'\n\n return (\n <div className={buildClassName(containerClass)}>\n {label && (\n <div\n className={buildClassName('flex items-center justify-between mb-3', labelWrapperClass)}\n >\n <Label className={labelClass}>{label}</Label>\n {labelHint}\n </div>\n )}\n\n <div\n className={buildClassName(\n columns\n ? buildClassName('grid gap-3', COLUMN_GRID_MAP[columns])\n : row || isCards\n ? 'flex flex-wrap gap-3'\n : 'flex flex-col gap-3',\n )}\n >\n {items.map((item) => {\n const isSelected = value === item.value\n const isItemDisabled = disabled || Boolean(item.disabled)\n\n if (isCards) {\n return (\n <label\n key={item.value}\n htmlFor={`${name}-${item.value}`}\n className={buildClassName(\n 'relative flex items-start gap-3 p-4 rounded-xl border transition-all cursor-pointer select-none min-w-[200px] flex-1',\n isSelected\n ? 'border-[var(--ui-primary)] bg-blue-50/40 dark:bg-blue-950/30 ring-2 ring-[var(--ui-primary-ring)]/30'\n : 'border-[var(--ui-border)] bg-white dark:bg-gray-800 hover:border-gray-300 dark:hover:border-gray-600',\n isItemDisabled &&\n 'opacity-50 cursor-not-allowed pointer-events-none bg-gray-50 dark:bg-gray-800/50',\n )}\n >\n <Radio\n name={name}\n id={`${name}-${item.value}`}\n value={item.value}\n aria-label={item.label}\n size={size}\n theme={theme}\n checked={isSelected}\n disabled={isItemDisabled}\n onChange={onChange}\n containerClass=\"pt-0.5\"\n />\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {item.icon && (\n <span className=\"shrink-0 text-gray-500 dark:text-gray-400\">{item.icon}</span>\n )}\n <span className=\"text-sm font-semibold text-gray-900 dark:text-white truncate\">\n {item.label}\n </span>\n </div>\n {item.description && (\n <p className=\"mt-1 text-xs text-gray-500 dark:text-gray-400 font-normal leading-relaxed\">\n {item.description}\n </p>\n )}\n </div>\n </label>\n )\n }\n\n return (\n <Radio\n key={item.value}\n name={name}\n id={`${name}-${item.value}`}\n label={item.label}\n description={item.description}\n value={item.value}\n size={size}\n theme={theme}\n checked={isSelected}\n disabled={isItemDisabled}\n onChange={onChange}\n />\n )\n })}\n </div>\n\n {showErrorMessage && error && (\n <div className=\"mt-1.5\">\n <TextContent error small>\n {error}\n </TextContent>\n </div>\n )}\n </div>\n )\n}\n\nRadioGroup.displayName = 'RadioGroup'\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;AAOA,MAAM,eAAe,GAA2B;AAC9C,IAAA,CAAC,EAAE,aAAa;AAChB,IAAA,CAAC,EAAE,4BAA4B;AAC/B,IAAA,CAAC,EAAE,4BAA4B;AAC/B,IAAA,CAAC,EAAE,4BAA4B;CAChC;AAEM,MAAM,UAAU,GAA8B,CAAC,KAAK,KAAI;IAC7D,MAAM,EACJ,IAAI,EACJ,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,KAAK,GAAG,SAAS,EACjB,KAAK,EACL,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,cAAc,EACd,OAAO,EACP,KAAK,EACL,OAAO,EACP,QAAQ,GAAG,KAAK,EAChB,GAAG,EACH,KAAK,EACL,gBAAgB,GAAG,IAAI,EACvB,QAAQ,GACT,GAAG,KAAK;AAET,IAAA,MAAM,KAAK,GAAG,OAAO,CACnB,MAAK;;AACH,QAAA,OAAA,MAAA,OAAO,KAAA,IAAA,IAAP,OAAO,KAAA,MAAA,GAAA,MAAA,GAAP,OAAO,CAAE,GAAG,CAAC,CAAC,MAAM,KAClB,OAAO,MAAM,KAAK;AAChB,cAAE;AACE,gBAAA,KAAK,EAAE,MAAM;AACb,gBAAA,KAAK,EAAE,MAAM;AACb,gBAAA,WAAW,EAAE,SAAS;AACtB,gBAAA,IAAI,EAAE,SAAS;AACf,gBAAA,QAAQ,EAAE,SAAS;AACpB;AACH,cAAE,MAAM,CACX,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,EAAE;AAAA,IAAA,CAAA,EACT,CAAC,OAAO,CAAC,CACV;AAED,IAAA,MAAM,OAAO,GAAG,OAAO,KAAK,OAAO;AAEnC,IAAA,QACEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,cAAc,CAAC,cAAc,CAAC,EAAA,QAAA,EAAA,CAC3C,KAAK,KACJA,IAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,cAAc,CAAC,wCAAwC,EAAE,iBAAiB,CAAC,EAAA,QAAA,EAAA,CAEtFC,IAAC,KAAK,EAAA,EAAC,SAAS,EAAE,UAAU,YAAG,KAAK,EAAA,CAAS,EAC5C,SAAS,CAAA,EAAA,CACN,CACP,EAEDA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,cAAc,CACvB;sBACI,cAAc,CAAC,YAAY,EAAE,eAAe,CAAC,OAAO,CAAC;sBACrD,GAAG,IAAI;AACP,0BAAE;0BACA,qBAAqB,CAC5B,EAAA,QAAA,EAEA,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAClB,oBAAA,MAAM,UAAU,GAAG,KAAK,KAAK,IAAI,CAAC,KAAK;oBACvC,MAAM,cAAc,GAAG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;oBAEzD,IAAI,OAAO,EAAE;AACX,wBAAA,QACED,IAAA,CAAA,OAAA,EAAA,EAEE,OAAO,EAAE,CAAA,EAAG,IAAI,IAAI,IAAI,CAAC,KAAK,CAAA,CAAE,EAChC,SAAS,EAAE,cAAc,CACvB,sHAAsH,EACtH;AACE,kCAAE;kCACA,sGAAsG,EAC1G,cAAc;gCACZ,kFAAkF,CACrF,EAAA,QAAA,EAAA,CAEDC,GAAA,CAAC,KAAK,EAAA,EACJ,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,CAAC,KAAK,CAAA,CAAE,EAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,EAAA,YAAA,EACL,IAAI,CAAC,KAAK,EACtB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAC,QAAQ,EAAA,CACvB,EAEFD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,gBAAgB,EAAA,QAAA,EAAA,CAC7BA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,aACrC,IAAI,CAAC,IAAI,KACRC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,2CAA2C,EAAA,QAAA,EAAE,IAAI,CAAC,IAAI,EAAA,CAAQ,CAC/E,EACDA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,8DAA8D,EAAA,QAAA,EAC3E,IAAI,CAAC,KAAK,EAAA,CACN,CAAA,EAAA,CACH,EACL,IAAI,CAAC,WAAW,KACfA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,2EAA2E,YACrF,IAAI,CAAC,WAAW,EAAA,CACf,CACL,CAAA,EAAA,CACG,CAAA,EAAA,EAtCD,IAAI,CAAC,KAAK,CAuCT;oBAEZ;AAEA,oBAAA,QACEA,GAAA,CAAC,KAAK,EAAA,EAEJ,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,CAAC,KAAK,CAAA,CAAE,EAC3B,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,WAAW,EAAE,IAAI,CAAC,WAAW,EAC7B,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,QAAQ,EAAA,EAVb,IAAI,CAAC,KAAK,CAWf;gBAEN,CAAC,CAAC,EAAA,CACE,EAEL,gBAAgB,IAAI,KAAK,KACxBA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,QAAQ,EAAA,QAAA,EACrBA,IAAC,WAAW,EAAA,EAAC,KAAK,EAAA,IAAA,EAAC,KAAK,EAAA,IAAA,EAAA,QAAA,EACrB,KAAK,EAAA,CACM,EAAA,CACV,CACP,CAAA,EAAA,CACG;AAEV;AAEA,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useState, useLayoutEffect } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
|
|
5
|
+
const SIZE_CONTAINER_CLASS = {
|
|
6
|
+
sm: 'p-1.5 gap-1 rounded-lg text-xs',
|
|
7
|
+
md: 'p-2 gap-1.5 rounded-xl text-sm',
|
|
8
|
+
lg: 'p-2 gap-2 rounded-2xl text-base',
|
|
9
|
+
};
|
|
10
|
+
const SIZE_ITEM_CLASS = {
|
|
11
|
+
sm: 'px-4 py-2 text-xs rounded-md min-w-[64px]',
|
|
12
|
+
md: 'px-5 py-2.5 text-sm rounded-lg min-w-[76px]',
|
|
13
|
+
lg: 'px-7 py-3 text-base rounded-xl min-w-[92px]',
|
|
14
|
+
};
|
|
15
|
+
const SIZE_ITEM_DESC_CLASS = {
|
|
16
|
+
sm: 'px-4 py-2.5 text-xs rounded-md min-w-[80px]',
|
|
17
|
+
md: 'px-5 py-3 text-sm rounded-lg min-w-[96px]',
|
|
18
|
+
lg: 'px-7 py-3.5 text-base rounded-xl min-w-[112px]',
|
|
19
|
+
};
|
|
20
|
+
const THEME_SWITCH_CLASS = {
|
|
21
|
+
primary: 'bg-[var(--ui-primary)] text-white shadow-xs',
|
|
22
|
+
secondary: 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-xs',
|
|
23
|
+
dark: 'bg-gray-900 dark:bg-black text-white shadow-xs',
|
|
24
|
+
};
|
|
25
|
+
const RadioSwitch = ({ label, items, selected, size = 'md', theme = 'primary', disabled = false, onChange, wrapperClass, switchClass, contentClass, descriptionClass, }) => {
|
|
26
|
+
const containerRef = useRef(null);
|
|
27
|
+
const [style, setStyle] = useState({ left: 0, top: 0, width: 0, height: 0, ready: false });
|
|
28
|
+
const getLabel = (i) => (typeof i === 'string' ? i : i.label);
|
|
29
|
+
const getValue = (i) => (typeof i === 'string' ? i : i.value);
|
|
30
|
+
const getDescription = (i) => { var _a; return typeof i === 'string' ? '' : ((_a = i.description) !== null && _a !== void 0 ? _a : ''); };
|
|
31
|
+
const isItemDisabled = (i) => disabled || (typeof i === 'string' ? false : Boolean(i.disabled));
|
|
32
|
+
const hasDescription = items.some((i) => typeof i !== 'string' && Boolean(i.description));
|
|
33
|
+
// Position calculation for GPU sliding highlight
|
|
34
|
+
useLayoutEffect(() => {
|
|
35
|
+
if (!containerRef.current)
|
|
36
|
+
return;
|
|
37
|
+
const updatePosition = () => {
|
|
38
|
+
if (!containerRef.current)
|
|
39
|
+
return;
|
|
40
|
+
const activeEl = containerRef.current.querySelector('[data-selected="true"]');
|
|
41
|
+
if (!activeEl)
|
|
42
|
+
return;
|
|
43
|
+
const parentRect = containerRef.current.getBoundingClientRect();
|
|
44
|
+
const rect = activeEl.getBoundingClientRect();
|
|
45
|
+
const left = activeEl.offsetLeft || rect.left - parentRect.left;
|
|
46
|
+
const top = activeEl.offsetTop || rect.top - parentRect.top;
|
|
47
|
+
const width = activeEl.offsetWidth || rect.width;
|
|
48
|
+
const height = activeEl.offsetHeight || rect.height;
|
|
49
|
+
setStyle({
|
|
50
|
+
left,
|
|
51
|
+
top,
|
|
52
|
+
width,
|
|
53
|
+
height,
|
|
54
|
+
ready: true,
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
updatePosition();
|
|
58
|
+
const resizeObserver = new ResizeObserver(updatePosition);
|
|
59
|
+
resizeObserver.observe(containerRef.current);
|
|
60
|
+
return () => resizeObserver.disconnect();
|
|
61
|
+
}, [selected, items, size]);
|
|
62
|
+
// ARIA Keyboard navigation handler
|
|
63
|
+
const handleGroupKeyDown = (e) => {
|
|
64
|
+
const enabledItems = items.filter((it) => !isItemDisabled(it));
|
|
65
|
+
if (enabledItems.length === 0)
|
|
66
|
+
return;
|
|
67
|
+
const currentVal = selected;
|
|
68
|
+
const currentEnabledIndex = enabledItems.findIndex((it) => getValue(it) === currentVal);
|
|
69
|
+
let nextItem = null;
|
|
70
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
const nextIdx = (currentEnabledIndex + 1) % enabledItems.length;
|
|
73
|
+
nextItem = enabledItems[nextIdx];
|
|
74
|
+
}
|
|
75
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
const prevIdx = (currentEnabledIndex - 1 + enabledItems.length) % enabledItems.length;
|
|
78
|
+
nextItem = enabledItems[prevIdx];
|
|
79
|
+
}
|
|
80
|
+
else if (e.key === 'Home') {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
nextItem = enabledItems[0];
|
|
83
|
+
}
|
|
84
|
+
else if (e.key === 'End') {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
nextItem = enabledItems[enabledItems.length - 1];
|
|
87
|
+
}
|
|
88
|
+
if (nextItem) {
|
|
89
|
+
onChange(getValue(nextItem));
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
return (jsxs("div", { ref: containerRef, role: "radiogroup", tabIndex: 0, "aria-label": label, onKeyDown: handleGroupKeyDown, className: buildClassName('relative inline-grid grid-flow-col auto-cols-fr items-stretch bg-gray-100 dark:bg-gray-800/80 border border-[var(--ui-border)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]', SIZE_CONTAINER_CLASS[size], disabled && 'opacity-60 pointer-events-none', wrapperClass), children: [jsx("div", { className: buildClassName('absolute transition-all duration-200 ease-[cubic-bezier(.25,.8,.25,1)] pointer-events-none', THEME_SWITCH_CLASS[theme], size === 'sm' ? 'rounded-md' : 'rounded-lg', style.ready ? 'opacity-100' : 'opacity-0', switchClass), style: {
|
|
93
|
+
transform: `translate(${style.left}px, ${style.top}px)`,
|
|
94
|
+
width: style.width,
|
|
95
|
+
height: style.height,
|
|
96
|
+
} }), items.map((item) => {
|
|
97
|
+
const itemVal = getValue(item);
|
|
98
|
+
const isSelected = selected === itemVal;
|
|
99
|
+
const disabledState = isItemDisabled(item);
|
|
100
|
+
return (jsx("button", { type: "button", role: "radio", "aria-checked": isSelected, "aria-disabled": disabledState, tabIndex: isSelected && !disabledState ? 0 : -1, disabled: disabledState, "data-radio-item": true, "data-value": itemVal, "data-selected": isSelected ? 'true' : undefined, onClick: () => {
|
|
101
|
+
if (!disabledState) {
|
|
102
|
+
onChange(itemVal);
|
|
103
|
+
}
|
|
104
|
+
}, className: buildClassName('relative z-10 appearance-none m-0 select-none group transition-colors flex flex-col items-center justify-center w-full text-center font-semibold focus:outline-none', hasDescription ? SIZE_ITEM_DESC_CLASS[size] : SIZE_ITEM_CLASS[size], disabledState ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', isSelected
|
|
105
|
+
? theme === 'secondary'
|
|
106
|
+
? 'text-gray-900 dark:text-white'
|
|
107
|
+
: 'text-white'
|
|
108
|
+
: buildClassName('text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white', !disabledState && 'hover:bg-black/[0.04] dark:hover:bg-white/[0.06]')), children: getDescription(item) ? (jsxs("div", { className: buildClassName('flex flex-col items-center justify-center gap-1', contentClass), children: [jsx("span", { className: "font-semibold leading-tight text-center truncate", children: getLabel(item) }), jsx("span", { className: buildClassName('text-[12px] leading-tight opacity-80 font-normal text-center truncate', descriptionClass), children: getDescription(item) })] })) : (jsx("span", { className: buildClassName('truncate leading-tight text-center', contentClass), children: getLabel(item) })) }, itemVal));
|
|
109
|
+
})] }));
|
|
110
|
+
};
|
|
111
|
+
RadioSwitch.displayName = 'RadioSwitch';
|
|
112
|
+
|
|
113
|
+
export { RadioSwitch };
|
|
114
|
+
//# sourceMappingURL=RadioSwitch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioSwitch.js","sources":["../../../../../src/components/RadioSwitch/RadioSwitch.tsx"],"sourcesContent":["import React, { useLayoutEffect, useRef, useState } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport type {\n RadioSwitchItem,\n RadioSwitchProps,\n RadioSwitchSize,\n RadioSwitchTheme,\n} from './RadioSwitch.types'\n\nconst SIZE_CONTAINER_CLASS: Record<RadioSwitchSize, string> = {\n sm: 'p-1.5 gap-1 rounded-lg text-xs',\n md: 'p-2 gap-1.5 rounded-xl text-sm',\n lg: 'p-2 gap-2 rounded-2xl text-base',\n}\n\nconst SIZE_ITEM_CLASS: Record<RadioSwitchSize, string> = {\n sm: 'px-4 py-2 text-xs rounded-md min-w-[64px]',\n md: 'px-5 py-2.5 text-sm rounded-lg min-w-[76px]',\n lg: 'px-7 py-3 text-base rounded-xl min-w-[92px]',\n}\n\nconst SIZE_ITEM_DESC_CLASS: Record<RadioSwitchSize, string> = {\n sm: 'px-4 py-2.5 text-xs rounded-md min-w-[80px]',\n md: 'px-5 py-3 text-sm rounded-lg min-w-[96px]',\n lg: 'px-7 py-3.5 text-base rounded-xl min-w-[112px]',\n}\n\nconst THEME_SWITCH_CLASS: Record<RadioSwitchTheme, string> = {\n primary: 'bg-[var(--ui-primary)] text-white shadow-xs',\n secondary: 'bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-xs',\n dark: 'bg-gray-900 dark:bg-black text-white shadow-xs',\n}\n\nexport const RadioSwitch: React.FC<RadioSwitchProps> = ({\n label,\n items,\n selected,\n size = 'md',\n theme = 'primary',\n disabled = false,\n onChange,\n wrapperClass,\n switchClass,\n contentClass,\n descriptionClass,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [style, setStyle] = useState({ left: 0, top: 0, width: 0, height: 0, ready: false })\n\n const getLabel = (i: RadioSwitchItem) => (typeof i === 'string' ? i : i.label)\n const getValue = (i: RadioSwitchItem) => (typeof i === 'string' ? i : i.value)\n const getDescription = (i: RadioSwitchItem) =>\n typeof i === 'string' ? '' : (i.description ?? '')\n const isItemDisabled = (i: RadioSwitchItem) =>\n disabled || (typeof i === 'string' ? false : Boolean(i.disabled))\n\n const hasDescription = items.some((i) => typeof i !== 'string' && Boolean(i.description))\n\n // Position calculation for GPU sliding highlight\n useLayoutEffect(() => {\n if (!containerRef.current) return\n\n const updatePosition = () => {\n if (!containerRef.current) return\n\n const activeEl = containerRef.current.querySelector(\n '[data-selected=\"true\"]',\n ) as HTMLElement | null\n\n if (!activeEl) return\n\n const parentRect = containerRef.current.getBoundingClientRect()\n const rect = activeEl.getBoundingClientRect()\n\n const left = activeEl.offsetLeft || rect.left - parentRect.left\n const top = activeEl.offsetTop || rect.top - parentRect.top\n const width = activeEl.offsetWidth || rect.width\n const height = activeEl.offsetHeight || rect.height\n\n setStyle({\n left,\n top,\n width,\n height,\n ready: true,\n })\n }\n\n updatePosition()\n\n const resizeObserver = new ResizeObserver(updatePosition)\n resizeObserver.observe(containerRef.current)\n\n return () => resizeObserver.disconnect()\n }, [selected, items, size])\n\n // ARIA Keyboard navigation handler\n const handleGroupKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const enabledItems = items.filter((it) => !isItemDisabled(it))\n if (enabledItems.length === 0) return\n\n const currentVal = selected\n const currentEnabledIndex = enabledItems.findIndex((it) => getValue(it) === currentVal)\n\n let nextItem: RadioSwitchItem | null = null\n\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n const nextIdx = (currentEnabledIndex + 1) % enabledItems.length\n nextItem = enabledItems[nextIdx]\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n const prevIdx = (currentEnabledIndex - 1 + enabledItems.length) % enabledItems.length\n nextItem = enabledItems[prevIdx]\n } else if (e.key === 'Home') {\n e.preventDefault()\n nextItem = enabledItems[0]\n } else if (e.key === 'End') {\n e.preventDefault()\n nextItem = enabledItems[enabledItems.length - 1]\n }\n\n if (nextItem) {\n onChange(getValue(nextItem))\n }\n }\n\n return (\n <div\n ref={containerRef}\n role=\"radiogroup\"\n tabIndex={0}\n aria-label={label}\n onKeyDown={handleGroupKeyDown}\n className={buildClassName(\n '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)]',\n SIZE_CONTAINER_CLASS[size],\n disabled && 'opacity-60 pointer-events-none',\n wrapperClass,\n )}\n >\n {/* GPU Sliding highlight background */}\n <div\n className={buildClassName(\n 'absolute transition-all duration-200 ease-[cubic-bezier(.25,.8,.25,1)] pointer-events-none',\n THEME_SWITCH_CLASS[theme],\n size === 'sm' ? 'rounded-md' : 'rounded-lg',\n style.ready ? 'opacity-100' : 'opacity-0',\n switchClass,\n )}\n style={{\n transform: `translate(${style.left}px, ${style.top}px)`,\n width: style.width,\n height: style.height,\n }}\n />\n\n {/* Item Buttons */}\n {items.map((item) => {\n const itemVal = getValue(item)\n const isSelected = selected === itemVal\n const disabledState = isItemDisabled(item)\n\n return (\n <button\n key={itemVal}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n aria-disabled={disabledState}\n tabIndex={isSelected && !disabledState ? 0 : -1}\n disabled={disabledState}\n data-radio-item\n data-value={itemVal}\n data-selected={isSelected ? 'true' : undefined}\n onClick={() => {\n if (!disabledState) {\n onChange(itemVal)\n }\n }}\n className={buildClassName(\n 'relative z-10 appearance-none m-0 select-none group transition-colors flex flex-col items-center justify-center w-full text-center font-semibold focus:outline-none',\n hasDescription ? SIZE_ITEM_DESC_CLASS[size] : SIZE_ITEM_CLASS[size],\n disabledState ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',\n isSelected\n ? theme === 'secondary'\n ? 'text-gray-900 dark:text-white'\n : 'text-white'\n : buildClassName(\n 'text-gray-600 hover:text-gray-900 dark:text-gray-300 dark:hover:text-white',\n !disabledState && 'hover:bg-black/[0.04] dark:hover:bg-white/[0.06]',\n ),\n )}\n >\n {getDescription(item) ? (\n <div\n className={buildClassName(\n 'flex flex-col items-center justify-center gap-1',\n contentClass,\n )}\n >\n <span className=\"font-semibold leading-tight text-center truncate\">\n {getLabel(item)}\n </span>\n <span\n className={buildClassName(\n 'text-[12px] leading-tight opacity-80 font-normal text-center truncate',\n descriptionClass,\n )}\n >\n {getDescription(item)}\n </span>\n </div>\n ) : (\n <span className={buildClassName('truncate leading-tight text-center', contentClass)}>\n {getLabel(item)}\n </span>\n )}\n </button>\n )\n })}\n </div>\n )\n}\n\nRadioSwitch.displayName = 'RadioSwitch'\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef, useState } from 'react';
|
|
3
|
+
import { Label } from '../Label/Label.js';
|
|
4
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
5
|
+
import { isEmpty } from '../../utils/is-empty.js';
|
|
6
|
+
import { TextContent } from '../TextContent/TextContent.js';
|
|
7
|
+
|
|
8
|
+
const sizeClasses = {
|
|
9
|
+
sm: {
|
|
10
|
+
track: 'h-1.5',
|
|
11
|
+
thumb: '[&::-webkit-slider-thumb]:h-3.5 [&::-webkit-slider-thumb]:w-3.5 [&::-moz-range-thumb]:h-3.5 [&::-moz-range-thumb]:w-3.5',
|
|
12
|
+
text: 'text-xs',
|
|
13
|
+
},
|
|
14
|
+
md: {
|
|
15
|
+
track: 'h-2',
|
|
16
|
+
thumb: '[&::-webkit-slider-thumb]:h-4.5 [&::-webkit-slider-thumb]:w-4.5 [&::-moz-range-thumb]:h-4.5 [&::-moz-range-thumb]:w-4.5',
|
|
17
|
+
text: 'text-sm',
|
|
18
|
+
},
|
|
19
|
+
lg: {
|
|
20
|
+
track: 'h-3',
|
|
21
|
+
thumb: '[&::-webkit-slider-thumb]:h-6 [&::-webkit-slider-thumb]:w-6 [&::-moz-range-thumb]:h-6 [&::-moz-range-thumb]:w-6',
|
|
22
|
+
text: 'text-base',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
const RangeInput = forwardRef((props, ref) => {
|
|
26
|
+
const { label, labelClass = '', labelHint = null, containerClass = '', className = '', size = 'md', showValue = true, valueSuffix = '', showTooltip = false, marks, error = null, helperText, showErrorMessage = true, id, min = 0, max = 100, value, defaultValue, onChange, ...inputProps } = props;
|
|
27
|
+
const [hovering, setHovering] = useState(false);
|
|
28
|
+
const [internalValue, setInternalValue] = useState(Number(defaultValue !== null && defaultValue !== void 0 ? defaultValue : min));
|
|
29
|
+
const isControlled = value !== undefined;
|
|
30
|
+
const currentVal = Number(isControlled ? value : internalValue);
|
|
31
|
+
const numMin = Number(min);
|
|
32
|
+
const numMax = Number(max);
|
|
33
|
+
const percent = numMax > numMin ? ((currentVal - numMin) / (numMax - numMin)) * 100 : 0;
|
|
34
|
+
const currentSize = sizeClasses[size] || sizeClasses.md;
|
|
35
|
+
const hasError = !isEmpty(error);
|
|
36
|
+
const handleSliderChange = (e) => {
|
|
37
|
+
if (!isControlled) {
|
|
38
|
+
setInternalValue(Number(e.target.value));
|
|
39
|
+
}
|
|
40
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(e);
|
|
41
|
+
};
|
|
42
|
+
// Parse custom marks if object provided
|
|
43
|
+
const markEntries = typeof marks === 'object' && marks !== null
|
|
44
|
+
? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))
|
|
45
|
+
: typeof marks === 'boolean' && marks
|
|
46
|
+
? [
|
|
47
|
+
{ value: numMin, label: String(numMin) },
|
|
48
|
+
{ value: (numMin + numMax) / 2, label: String(Math.round((numMin + numMax) / 2)) },
|
|
49
|
+
{ value: numMax, label: String(numMax) },
|
|
50
|
+
]
|
|
51
|
+
: null;
|
|
52
|
+
return (jsxs("div", { className: buildClassName('group space-y-2', containerClass), children: [label && (jsxs("div", { className: "flex items-center justify-between mb-1", children: [jsx(Label, { htmlFor: id, className: labelClass, children: label }), labelHint] })), jsxs("div", { className: "relative flex items-center gap-3", children: [jsxs("div", { className: "relative flex-1 py-2", children: [showTooltip && hovering && (jsxs("div", { className: "absolute -top-7 transform -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 transition-all z-20", style: { left: `${percent}%` }, children: [currentVal, valueSuffix, jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-100" })] })), jsx("input", { ref: ref, type: "range", id: id, min: min, max: max, value: currentVal, onChange: handleSliderChange, onMouseEnter: () => setHovering(true), onMouseLeave: () => setHovering(false), ...inputProps, style: {
|
|
53
|
+
background: `linear-gradient(to right, ${hasError ? '#ef4444' : '#2563eb'} 0%, ${hasError ? '#ef4444' : '#2563eb'} ${percent}%, ${document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'} ${percent}%, ${document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'} 100%)`,
|
|
54
|
+
}, className: buildClassName('w-full rounded-lg appearance-none cursor-pointer transition-all', currentSize.track, currentSize.thumb, '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full', '[&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:shadow-md', hasError
|
|
55
|
+
? '[&::-webkit-slider-thumb]:border-red-600 [&::-moz-range-thumb]:border-red-600'
|
|
56
|
+
: '[&::-webkit-slider-thumb]:border-blue-600 [&::-moz-range-thumb]:border-blue-600', '[&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:shadow-md', className) }), markEntries && (jsx("div", { className: "relative w-full h-4 mt-1", children: markEntries.map((m) => {
|
|
57
|
+
const markPercent = ((m.value - numMin) / (numMax - numMin)) * 100;
|
|
58
|
+
return (jsxs("div", { className: "absolute top-0 transform -translate-x-1/2 flex flex-col items-center", style: { left: `${markPercent}%` }, children: [jsx("span", { className: "w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full" }), jsx("span", { className: "text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5", children: m.label })] }, m.value));
|
|
59
|
+
}) }))] }), showValue && (jsxs("span", { className: buildClassName('font-medium text-gray-700 dark:text-gray-300 min-w-[3rem] text-right shrink-0', currentSize.text), children: [currentVal, valueSuffix] }))] }), (showErrorMessage && hasError) || helperText ? (jsx("div", { className: "mt-1", children: showErrorMessage && hasError ? (jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsx(TextContent, { muted: true, small: true, children: helperText })) : null })) : null] }));
|
|
60
|
+
});
|
|
61
|
+
RangeInput.displayName = 'RangeInput';
|
|
62
|
+
|
|
63
|
+
export { RangeInput };
|
|
64
|
+
//# sourceMappingURL=RangeInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RangeInput.js","sources":["../../../../../src/components/RangeInput/RangeInput.tsx"],"sourcesContent":["import { forwardRef, useState } from 'react'\nimport { Label } from '../Label'\nimport { buildClassName } from '../../utils/build-classname'\nimport { isEmpty } from '../../utils/is-empty'\nimport { TextContent } from '../TextContent'\nimport type { RangeInputProps, RangeInputSize } from './RangeInput.types'\n\nconst sizeClasses: Record<RangeInputSize, { track: string; thumb: string; text: string }> = {\n sm: {\n track: 'h-1.5',\n thumb:\n '[&::-webkit-slider-thumb]:h-3.5 [&::-webkit-slider-thumb]:w-3.5 [&::-moz-range-thumb]:h-3.5 [&::-moz-range-thumb]:w-3.5',\n text: 'text-xs',\n },\n md: {\n track: 'h-2',\n thumb:\n '[&::-webkit-slider-thumb]:h-4.5 [&::-webkit-slider-thumb]:w-4.5 [&::-moz-range-thumb]:h-4.5 [&::-moz-range-thumb]:w-4.5',\n text: 'text-sm',\n },\n lg: {\n track: 'h-3',\n thumb:\n '[&::-webkit-slider-thumb]:h-6 [&::-webkit-slider-thumb]:w-6 [&::-moz-range-thumb]:h-6 [&::-moz-range-thumb]:w-6',\n text: 'text-base',\n },\n}\n\nexport const RangeInput = forwardRef<HTMLInputElement, RangeInputProps>((props, ref) => {\n const {\n label,\n labelClass = '',\n labelHint = null,\n containerClass = '',\n className = '',\n size = 'md',\n showValue = true,\n valueSuffix = '',\n showTooltip = false,\n marks,\n error = null,\n helperText,\n showErrorMessage = true,\n id,\n min = 0,\n max = 100,\n value,\n defaultValue,\n onChange,\n ...inputProps\n } = props\n\n const [hovering, setHovering] = useState(false)\n const [internalValue, setInternalValue] = useState<number>(Number(defaultValue ?? min))\n\n const isControlled = value !== undefined\n const currentVal = Number(isControlled ? value : internalValue)\n const numMin = Number(min)\n const numMax = Number(max)\n\n const percent = numMax > numMin ? ((currentVal - numMin) / (numMax - numMin)) * 100 : 0\n const currentSize = sizeClasses[size] || sizeClasses.md\n const hasError = !isEmpty(error)\n\n const handleSliderChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) {\n setInternalValue(Number(e.target.value))\n }\n onChange?.(e)\n }\n\n // Parse custom marks if object provided\n const markEntries =\n typeof marks === 'object' && marks !== null\n ? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))\n : typeof marks === 'boolean' && marks\n ? [\n { value: numMin, label: String(numMin) },\n { value: (numMin + numMax) / 2, label: String(Math.round((numMin + numMax) / 2)) },\n { value: numMax, label: String(numMax) },\n ]\n : null\n\n return (\n <div className={buildClassName('group space-y-2', containerClass)}>\n {label && (\n <div className=\"flex items-center justify-between mb-1\">\n <Label htmlFor={id} className={labelClass}>\n {label}\n </Label>\n {labelHint}\n </div>\n )}\n\n <div className=\"relative flex items-center gap-3\">\n <div className=\"relative flex-1 py-2\">\n {/* Floating Tooltip Popup Badge */}\n {showTooltip && hovering && (\n <div\n className=\"absolute -top-7 transform -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 transition-all z-20\"\n style={{ left: `${percent}%` }}\n >\n {currentVal}\n {valueSuffix}\n <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\" />\n </div>\n )}\n\n <input\n ref={ref}\n type=\"range\"\n id={id}\n min={min}\n max={max}\n value={currentVal}\n onChange={handleSliderChange}\n onMouseEnter={() => setHovering(true)}\n onMouseLeave={() => setHovering(false)}\n {...inputProps}\n style={{\n background: `linear-gradient(to right, ${hasError ? '#ef4444' : '#2563eb'} 0%, ${\n hasError ? '#ef4444' : '#2563eb'\n } ${percent}%, ${\n document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'\n } ${percent}%, ${\n document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'\n } 100%)`,\n }}\n className={buildClassName(\n 'w-full rounded-lg appearance-none cursor-pointer transition-all',\n currentSize.track,\n currentSize.thumb,\n '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full',\n '[&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:shadow-md',\n hasError\n ? '[&::-webkit-slider-thumb]:border-red-600 [&::-moz-range-thumb]:border-red-600'\n : '[&::-webkit-slider-thumb]:border-blue-600 [&::-moz-range-thumb]:border-blue-600',\n '[&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:shadow-md',\n className,\n )}\n />\n\n {/* Tick Marks & Labels */}\n {markEntries && (\n <div className=\"relative w-full h-4 mt-1\">\n {markEntries.map((m) => {\n const markPercent = ((m.value - numMin) / (numMax - numMin)) * 100\n return (\n <div\n key={m.value}\n className=\"absolute top-0 transform -translate-x-1/2 flex flex-col items-center\"\n style={{ left: `${markPercent}%` }}\n >\n <span className=\"w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full\" />\n <span className=\"text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5\">\n {m.label}\n </span>\n </div>\n )\n })}\n </div>\n )}\n </div>\n\n {showValue && (\n <span\n className={buildClassName(\n 'font-medium text-gray-700 dark:text-gray-300 min-w-[3rem] text-right shrink-0',\n currentSize.text,\n )}\n >\n {currentVal}\n {valueSuffix}\n </span>\n )}\n </div>\n\n {/* Footer Error or Helper Text */}\n {(showErrorMessage && hasError) || helperText ? (\n <div className=\"mt-1\">\n {showErrorMessage && hasError ? (\n <TextContent error small>\n {error}\n </TextContent>\n ) : helperText ? (\n <TextContent muted small>\n {helperText}\n </TextContent>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n})\n\nRangeInput.displayName = 'RangeInput'\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useState, useEffect } from 'react';
|
|
3
|
+
import { Label } from '../Label/Label.js';
|
|
4
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
5
|
+
import { isEmpty } from '../../utils/is-empty.js';
|
|
6
|
+
import { TextContent } from '../TextContent/TextContent.js';
|
|
7
|
+
|
|
8
|
+
const sizeClasses = {
|
|
9
|
+
sm: {
|
|
10
|
+
track: 'h-1.5',
|
|
11
|
+
thumb: 'h-4 w-4',
|
|
12
|
+
thumbPx: 16,
|
|
13
|
+
text: 'text-xs',
|
|
14
|
+
},
|
|
15
|
+
md: {
|
|
16
|
+
track: 'h-2',
|
|
17
|
+
thumb: 'h-5 w-5',
|
|
18
|
+
thumbPx: 20,
|
|
19
|
+
text: 'text-sm',
|
|
20
|
+
},
|
|
21
|
+
lg: {
|
|
22
|
+
track: 'h-3',
|
|
23
|
+
thumb: 'h-6 w-6',
|
|
24
|
+
thumbPx: 24,
|
|
25
|
+
text: 'text-base',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const RangeSlider = ({ label, labelHint, labelClass = '', containerClass = '', className = '', size = 'md', min, max, step = 1, valueMin, valueMax, onChange, valueSuffix = '', showTooltips = false, marks, error = null, helperText, showErrorMessage = true, }) => {
|
|
29
|
+
const trackRef = useRef(null);
|
|
30
|
+
const activeThumbRef = useRef(null);
|
|
31
|
+
const [activeThumbState, setActiveThumbState] = useState(null);
|
|
32
|
+
const [hoveringThumb, setHoveringThumb] = useState(null);
|
|
33
|
+
const valueMinRef = useRef(valueMin);
|
|
34
|
+
const valueMaxRef = useRef(valueMax);
|
|
35
|
+
const onChangeRef = useRef(onChange);
|
|
36
|
+
valueMinRef.current = valueMin;
|
|
37
|
+
valueMaxRef.current = valueMax;
|
|
38
|
+
onChangeRef.current = onChange;
|
|
39
|
+
const hasError = !isEmpty(error);
|
|
40
|
+
const currentSize = sizeClasses[size] || sizeClasses.md;
|
|
41
|
+
const clampValue = (val) => Math.min(Math.max(val, min), max);
|
|
42
|
+
const snapToStep = (val) => {
|
|
43
|
+
const clamped = clampValue(val);
|
|
44
|
+
const steps = Math.round((clamped - min) / step);
|
|
45
|
+
return Math.min(Math.max(min + steps * step, min), max);
|
|
46
|
+
};
|
|
47
|
+
const percent = (v) => ((clampValue(v) - min) / (max - min)) * 100;
|
|
48
|
+
const stablePointerMoveRef = useRef((e) => {
|
|
49
|
+
if (!trackRef.current || !activeThumbRef.current)
|
|
50
|
+
return;
|
|
51
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
52
|
+
const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width);
|
|
53
|
+
const rawVal = min + (x / rect.width) * (max - min);
|
|
54
|
+
const snappedVal = snapToStep(rawVal);
|
|
55
|
+
if (activeThumbRef.current === 'min') {
|
|
56
|
+
const nextMin = Math.min(snappedVal, valueMaxRef.current - step);
|
|
57
|
+
onChangeRef.current(nextMin, valueMaxRef.current);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const nextMax = Math.max(snappedVal, valueMinRef.current + step);
|
|
61
|
+
onChangeRef.current(valueMinRef.current, nextMax);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const stablePointerUpRef = useRef(() => {
|
|
65
|
+
activeThumbRef.current = null;
|
|
66
|
+
setActiveThumbState(null);
|
|
67
|
+
window.removeEventListener('pointermove', stablePointerMoveRef.current);
|
|
68
|
+
window.removeEventListener('pointerup', stablePointerUpRef.current);
|
|
69
|
+
});
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const move = stablePointerMoveRef.current;
|
|
72
|
+
const up = stablePointerUpRef.current;
|
|
73
|
+
return () => {
|
|
74
|
+
window.removeEventListener('pointermove', move);
|
|
75
|
+
window.removeEventListener('pointerup', up);
|
|
76
|
+
};
|
|
77
|
+
}, []);
|
|
78
|
+
const startDrag = (thumb) => (_e) => {
|
|
79
|
+
activeThumbRef.current = thumb;
|
|
80
|
+
setActiveThumbState(thumb);
|
|
81
|
+
window.addEventListener('pointermove', stablePointerMoveRef.current);
|
|
82
|
+
window.addEventListener('pointerup', stablePointerUpRef.current);
|
|
83
|
+
};
|
|
84
|
+
const handleTrackClick = (e) => {
|
|
85
|
+
if (!trackRef.current)
|
|
86
|
+
return;
|
|
87
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
88
|
+
const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width);
|
|
89
|
+
const rawVal = min + (x / rect.width) * (max - min);
|
|
90
|
+
const snappedVal = snapToStep(rawVal);
|
|
91
|
+
const pxMin = (percent(valueMin) / 100) * rect.width;
|
|
92
|
+
const pxMax = (percent(valueMax) / 100) * rect.width;
|
|
93
|
+
if (x <= pxMin) {
|
|
94
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (x >= pxMax) {
|
|
98
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const distMin = Math.abs(snappedVal - valueMin);
|
|
102
|
+
const distMax = Math.abs(snappedVal - valueMax);
|
|
103
|
+
if (distMin < distMax) {
|
|
104
|
+
onChange(Math.min(snappedVal, valueMax - step), valueMax);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
onChange(valueMin, Math.max(snappedVal, valueMin + step));
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
// Keyboard accessibility handler for thumbs
|
|
111
|
+
const handleKeyDown = (thumb) => (e) => {
|
|
112
|
+
let delta = 0;
|
|
113
|
+
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown')
|
|
114
|
+
delta = -step;
|
|
115
|
+
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp')
|
|
116
|
+
delta = step;
|
|
117
|
+
else if (e.key === 'Home') {
|
|
118
|
+
if (thumb === 'min')
|
|
119
|
+
onChange(min, valueMax);
|
|
120
|
+
else
|
|
121
|
+
onChange(valueMin, valueMin + step);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
else if (e.key === 'End') {
|
|
125
|
+
if (thumb === 'min')
|
|
126
|
+
onChange(valueMax - step, valueMax);
|
|
127
|
+
else
|
|
128
|
+
onChange(valueMin, max);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (delta !== 0) {
|
|
132
|
+
e.preventDefault();
|
|
133
|
+
if (thumb === 'min') {
|
|
134
|
+
const next = snapToStep(valueMin + delta);
|
|
135
|
+
onChange(Math.min(next, valueMax - step), valueMax);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const next = snapToStep(valueMax + delta);
|
|
139
|
+
onChange(valueMin, Math.max(next, valueMin + step));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const markEntries = marks
|
|
144
|
+
? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))
|
|
145
|
+
: null;
|
|
146
|
+
return (jsxs("div", { className: buildClassName('group space-y-2', hasError && 'has-error', containerClass), children: [label && (jsxs("div", { className: "flex items-center justify-between mb-1", children: [jsx(Label, { className: labelClass, children: label }), labelHint] })), jsxs("div", { ref: trackRef, onMouseDown: handleTrackClick, className: "relative h-8 select-none w-full flex items-center cursor-pointer", "data-testid": "range-track", children: [jsx("div", { className: buildClassName('absolute top-1/2 left-0 right-0 rounded-full bg-gray-200 dark:bg-gray-700 -translate-y-1/2', currentSize.track) }), jsx("div", { className: buildClassName('absolute top-1/2 -translate-y-1/2 rounded-full transition-all duration-150 ease-out', hasError ? 'bg-red-500' : 'bg-blue-600 dark:bg-blue-500', currentSize.track), style: {
|
|
147
|
+
left: `${percent(valueMin)}%`,
|
|
148
|
+
width: `${percent(valueMax) - percent(valueMin)}%`,
|
|
149
|
+
} }), 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') &&
|
|
150
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
151
|
+
left: `calc(${percent(valueMin)}% - ${currentSize.thumbPx / 2}px)`,
|
|
152
|
+
zIndex: activeThumbState === 'min' ? 50 : 30,
|
|
153
|
+
}, "data-testid": "thumb-min", children: showTooltips && (activeThumbState === 'min' || hoveringThumb === 'min') && (jsxs("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 px-2 py-0.5 rounded bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-[11px] font-semibold shadow-md pointer-events-none z-50 whitespace-nowrap", children: [Math.round(valueMin), valueSuffix, jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-100" })] })) }), jsx("div", { role: "slider", tabIndex: 0, "aria-label": "Maximum value", "aria-valuenow": valueMax, "aria-valuemin": valueMin + step, "aria-valuemax": max, onPointerDown: startDrag('max'), onMouseEnter: () => setHoveringThumb('max'), onMouseLeave: () => setHoveringThumb(null), onKeyDown: handleKeyDown('max'), className: buildClassName('absolute top-1/2 -translate-y-1/2 rounded-full focus:outline-none', 'bg-white border-2 shadow-md cursor-pointer touch-none', hasError ? 'border-red-600' : 'border-blue-600', 'transition-all duration-150 ease-out', currentSize.thumb, (activeThumbState === 'max' || hoveringThumb === 'max') &&
|
|
154
|
+
(hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'), className), style: {
|
|
155
|
+
left: `calc(${percent(valueMax)}% - ${currentSize.thumbPx / 2}px)`,
|
|
156
|
+
zIndex: activeThumbState === 'max' ? 50 : 40,
|
|
157
|
+
}, "data-testid": "thumb-max", children: showTooltips && (activeThumbState === 'max' || hoveringThumb === 'max') && (jsxs("div", { className: "absolute -top-7 left-1/2 -translate-x-1/2 px-2 py-0.5 rounded bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 text-[11px] font-semibold shadow-md pointer-events-none z-50 whitespace-nowrap", children: [Math.round(valueMax), valueSuffix, jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 border-4 border-transparent border-t-gray-900 dark:border-t-gray-100" })] })) })] }), markEntries && (jsx("div", { className: "relative w-full h-4 mt-1", children: markEntries.map((m) => {
|
|
158
|
+
const markPercent = percent(m.value);
|
|
159
|
+
return (jsxs("div", { className: "absolute top-0 transform -translate-x-1/2 flex flex-col items-center", style: { left: `${markPercent}%` }, children: [jsx("span", { className: "w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full" }), jsx("span", { className: "text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5", children: m.label })] }, m.value));
|
|
160
|
+
}) })), jsxs("div", { className: buildClassName('flex justify-between font-medium text-gray-700 dark:text-gray-300', currentSize.text), children: [jsxs("span", { children: [Math.round(valueMin), valueSuffix] }), jsxs("span", { children: [Math.round(valueMax), valueSuffix] })] }), (showErrorMessage && hasError) || helperText ? (jsx("div", { className: "mt-1", children: showErrorMessage && hasError ? (jsx(TextContent, { error: true, small: true, children: error })) : helperText ? (jsx(TextContent, { muted: true, small: true, children: helperText })) : null })) : null] }));
|
|
161
|
+
};
|
|
162
|
+
RangeSlider.displayName = 'RangeSlider';
|
|
163
|
+
|
|
164
|
+
export { RangeSlider };
|
|
165
|
+
//# sourceMappingURL=RangeSlider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RangeSlider.js","sources":["../../../../../src/components/RangeSlider/RangeSlider.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react'\nimport { Label } from '../Label'\nimport { buildClassName } from '../../utils/build-classname'\nimport { isEmpty } from '../../utils/is-empty'\nimport type { RangeSliderProps, RangeSliderSize } from './RangeSlider.types'\nimport { TextContent } from '../TextContent'\n\nconst sizeClasses: Record<\n RangeSliderSize,\n { track: string; thumb: string; thumbPx: number; text: string }\n> = {\n sm: {\n track: 'h-1.5',\n thumb: 'h-4 w-4',\n thumbPx: 16,\n text: 'text-xs',\n },\n md: {\n track: 'h-2',\n thumb: 'h-5 w-5',\n thumbPx: 20,\n text: 'text-sm',\n },\n lg: {\n track: 'h-3',\n thumb: 'h-6 w-6',\n thumbPx: 24,\n text: 'text-base',\n },\n}\n\nexport const RangeSlider: React.FC<RangeSliderProps> = ({\n label,\n labelHint,\n labelClass = '',\n containerClass = '',\n className = '',\n size = 'md',\n min,\n max,\n step = 1,\n valueMin,\n valueMax,\n onChange,\n valueSuffix = '',\n showTooltips = false,\n marks,\n error = null,\n helperText,\n showErrorMessage = true,\n}) => {\n const trackRef = useRef<HTMLDivElement | null>(null)\n const activeThumbRef = useRef<'min' | 'max' | null>(null)\n const [activeThumbState, setActiveThumbState] = useState<'min' | 'max' | null>(null)\n const [hoveringThumb, setHoveringThumb] = useState<'min' | 'max' | null>(null)\n\n const valueMinRef = useRef(valueMin)\n const valueMaxRef = useRef(valueMax)\n const onChangeRef = useRef(onChange)\n valueMinRef.current = valueMin\n valueMaxRef.current = valueMax\n onChangeRef.current = onChange\n\n const hasError = !isEmpty(error)\n const currentSize = sizeClasses[size] || sizeClasses.md\n\n const clampValue = (val: number) => Math.min(Math.max(val, min), max)\n const snapToStep = (val: number) => {\n const clamped = clampValue(val)\n const steps = Math.round((clamped - min) / step)\n return Math.min(Math.max(min + steps * step, min), max)\n }\n\n const percent = (v: number) => ((clampValue(v) - min) / (max - min)) * 100\n\n const stablePointerMoveRef = useRef((e: PointerEvent) => {\n if (!trackRef.current || !activeThumbRef.current) return\n const rect = trackRef.current.getBoundingClientRect()\n const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width)\n const rawVal = min + (x / rect.width) * (max - min)\n const snappedVal = snapToStep(rawVal)\n\n if (activeThumbRef.current === 'min') {\n const nextMin = Math.min(snappedVal, valueMaxRef.current - step)\n onChangeRef.current(nextMin, valueMaxRef.current)\n } else {\n const nextMax = Math.max(snappedVal, valueMinRef.current + step)\n onChangeRef.current(valueMinRef.current, nextMax)\n }\n })\n\n const stablePointerUpRef = useRef(() => {\n activeThumbRef.current = null\n setActiveThumbState(null)\n window.removeEventListener('pointermove', stablePointerMoveRef.current)\n window.removeEventListener('pointerup', stablePointerUpRef.current)\n })\n\n useEffect(() => {\n const move = stablePointerMoveRef.current\n const up = stablePointerUpRef.current\n return () => {\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', up)\n }\n }, [])\n\n const startDrag = (thumb: 'min' | 'max') => (_e: React.PointerEvent) => {\n activeThumbRef.current = thumb\n setActiveThumbState(thumb)\n window.addEventListener('pointermove', stablePointerMoveRef.current)\n window.addEventListener('pointerup', stablePointerUpRef.current)\n }\n\n const handleTrackClick = (e: React.MouseEvent) => {\n if (!trackRef.current) return\n\n const rect = trackRef.current.getBoundingClientRect()\n const x = Math.min(Math.max(e.clientX - rect.left, 0), rect.width)\n const rawVal = min + (x / rect.width) * (max - min)\n const snappedVal = snapToStep(rawVal)\n\n const pxMin = (percent(valueMin) / 100) * rect.width\n const pxMax = (percent(valueMax) / 100) * rect.width\n\n if (x <= pxMin) {\n onChange(Math.min(snappedVal, valueMax - step), valueMax)\n return\n }\n\n if (x >= pxMax) {\n onChange(valueMin, Math.max(snappedVal, valueMin + step))\n return\n }\n\n const distMin = Math.abs(snappedVal - valueMin)\n const distMax = Math.abs(snappedVal - valueMax)\n\n if (distMin < distMax) {\n onChange(Math.min(snappedVal, valueMax - step), valueMax)\n } else {\n onChange(valueMin, Math.max(snappedVal, valueMin + step))\n }\n }\n\n // Keyboard accessibility handler for thumbs\n const handleKeyDown = (thumb: 'min' | 'max') => (e: React.KeyboardEvent) => {\n let delta = 0\n if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') delta = -step\n else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') delta = step\n else if (e.key === 'Home') {\n if (thumb === 'min') onChange(min, valueMax)\n else onChange(valueMin, valueMin + step)\n return\n } else if (e.key === 'End') {\n if (thumb === 'min') onChange(valueMax - step, valueMax)\n else onChange(valueMin, max)\n return\n }\n\n if (delta !== 0) {\n e.preventDefault()\n if (thumb === 'min') {\n const next = snapToStep(valueMin + delta)\n onChange(Math.min(next, valueMax - step), valueMax)\n } else {\n const next = snapToStep(valueMax + delta)\n onChange(valueMin, Math.max(next, valueMin + step))\n }\n }\n }\n\n const markEntries = marks\n ? Object.entries(marks).map(([k, v]) => ({ value: Number(k), label: v }))\n : null\n\n return (\n <div className={buildClassName('group space-y-2', hasError && 'has-error', containerClass)}>\n {label && (\n <div className=\"flex items-center justify-between mb-1\">\n <Label className={labelClass}>{label}</Label>\n {labelHint}\n </div>\n )}\n\n {/* TRACK CONTAINER */}\n <div\n ref={trackRef}\n onMouseDown={handleTrackClick}\n className=\"relative h-8 select-none w-full flex items-center cursor-pointer\"\n data-testid=\"range-track\"\n >\n {/* Track background */}\n <div\n className={buildClassName(\n 'absolute top-1/2 left-0 right-0 rounded-full bg-gray-200 dark:bg-gray-700 -translate-y-1/2',\n currentSize.track,\n )}\n />\n\n {/* Highlight active range section */}\n <div\n className={buildClassName(\n 'absolute top-1/2 -translate-y-1/2 rounded-full transition-all duration-150 ease-out',\n hasError ? 'bg-red-500' : 'bg-blue-600 dark:bg-blue-500',\n currentSize.track,\n )}\n style={{\n left: `${percent(valueMin)}%`,\n width: `${percent(valueMax) - percent(valueMin)}%`,\n }}\n />\n\n {/* MIN THUMB */}\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label=\"Minimum value\"\n aria-valuenow={valueMin}\n aria-valuemin={min}\n aria-valuemax={valueMax - step}\n onPointerDown={startDrag('min')}\n onMouseEnter={() => setHoveringThumb('min')}\n onMouseLeave={() => setHoveringThumb(null)}\n onKeyDown={handleKeyDown('min')}\n className={buildClassName(\n 'absolute top-1/2 -translate-y-1/2 rounded-full focus:outline-none',\n 'bg-white border-2 shadow-md cursor-pointer touch-none',\n hasError ? 'border-red-600' : 'border-blue-600',\n 'transition-all duration-150 ease-out',\n currentSize.thumb,\n (activeThumbState === 'min' || hoveringThumb === 'min') &&\n (hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'),\n className,\n )}\n style={{\n left: `calc(${percent(valueMin)}% - ${currentSize.thumbPx / 2}px)`,\n zIndex: activeThumbState === 'min' ? 50 : 30,\n }}\n data-testid=\"thumb-min\"\n >\n {/* Floating Tooltip Min */}\n {showTooltips && (activeThumbState === 'min' || hoveringThumb === 'min') && (\n <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\">\n {Math.round(valueMin)}\n {valueSuffix}\n <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\" />\n </div>\n )}\n </div>\n\n {/* MAX THUMB */}\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label=\"Maximum value\"\n aria-valuenow={valueMax}\n aria-valuemin={valueMin + step}\n aria-valuemax={max}\n onPointerDown={startDrag('max')}\n onMouseEnter={() => setHoveringThumb('max')}\n onMouseLeave={() => setHoveringThumb(null)}\n onKeyDown={handleKeyDown('max')}\n className={buildClassName(\n 'absolute top-1/2 -translate-y-1/2 rounded-full focus:outline-none',\n 'bg-white border-2 shadow-md cursor-pointer touch-none',\n hasError ? 'border-red-600' : 'border-blue-600',\n 'transition-all duration-150 ease-out',\n currentSize.thumb,\n (activeThumbState === 'max' || hoveringThumb === 'max') &&\n (hasError ? 'ring-4 ring-red-200' : 'ring-4 ring-blue-200'),\n className,\n )}\n style={{\n left: `calc(${percent(valueMax)}% - ${currentSize.thumbPx / 2}px)`,\n zIndex: activeThumbState === 'max' ? 50 : 40,\n }}\n data-testid=\"thumb-max\"\n >\n {/* Floating Tooltip Max */}\n {showTooltips && (activeThumbState === 'max' || hoveringThumb === 'max') && (\n <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\">\n {Math.round(valueMax)}\n {valueSuffix}\n <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\" />\n </div>\n )}\n </div>\n </div>\n\n {/* Step Marks & Labels */}\n {markEntries && (\n <div className=\"relative w-full h-4 mt-1\">\n {markEntries.map((m) => {\n const markPercent = percent(m.value)\n return (\n <div\n key={m.value}\n className=\"absolute top-0 transform -translate-x-1/2 flex flex-col items-center\"\n style={{ left: `${markPercent}%` }}\n >\n <span className=\"w-1 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full\" />\n <span className=\"text-[10px] font-medium text-gray-400 dark:text-gray-500 mt-0.5\">\n {m.label}\n </span>\n </div>\n )\n })}\n </div>\n )}\n\n {/* Number Range Indicators */}\n <div\n className={buildClassName(\n 'flex justify-between font-medium text-gray-700 dark:text-gray-300',\n currentSize.text,\n )}\n >\n <span>\n {Math.round(valueMin)}\n {valueSuffix}\n </span>\n <span>\n {Math.round(valueMax)}\n {valueSuffix}\n </span>\n </div>\n\n {/* Footer Error or Helper Text */}\n {(showErrorMessage && hasError) || helperText ? (\n <div className=\"mt-1\">\n {showErrorMessage && hasError ? (\n <TextContent error small>\n {error}\n </TextContent>\n ) : helperText ? (\n <TextContent muted small>\n {helperText}\n </TextContent>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\nRangeSlider.displayName = 'RangeSlider'\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { buildClassName } from '../../utils/build-classname.js';
|
|
4
|
+
|
|
5
|
+
const SIZE_CONTAINER_CLASS = {
|
|
6
|
+
sm: 'p-0.5 gap-0.5 rounded-lg text-xs',
|
|
7
|
+
md: 'p-1 gap-1 rounded-xl text-sm',
|
|
8
|
+
lg: 'p-1.5 gap-1.5 rounded-xl text-base',
|
|
9
|
+
};
|
|
10
|
+
const SIZE_OPTION_CLASS = {
|
|
11
|
+
sm: 'px-2 py-1 text-xs font-medium rounded-md',
|
|
12
|
+
md: 'px-3 py-1.5 text-sm font-semibold rounded-lg',
|
|
13
|
+
lg: 'px-4 py-2 text-base font-semibold rounded-lg',
|
|
14
|
+
};
|
|
15
|
+
const SIZE_ICON_CLASS = {
|
|
16
|
+
sm: 'size-3.5',
|
|
17
|
+
md: 'size-4',
|
|
18
|
+
lg: 'size-5',
|
|
19
|
+
};
|
|
20
|
+
const SegmentedControl = forwardRef((props, ref) => {
|
|
21
|
+
const { options, value, onChange, disabled = false, size = 'md', fullWidth = false, className, ...restProps } = props;
|
|
22
|
+
const handleKeyDown = (e, currentIndex) => {
|
|
23
|
+
const enabledOptions = options.filter((opt) => !opt.disabled && !disabled);
|
|
24
|
+
if (enabledOptions.length === 0)
|
|
25
|
+
return;
|
|
26
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
const currentPos = enabledOptions.findIndex((opt) => opt.value === options[currentIndex].value);
|
|
29
|
+
const nextPos = (currentPos + 1) % enabledOptions.length;
|
|
30
|
+
onChange(enabledOptions[nextPos].value);
|
|
31
|
+
}
|
|
32
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
const currentPos = enabledOptions.findIndex((opt) => opt.value === options[currentIndex].value);
|
|
35
|
+
const prevPos = (currentPos - 1 + enabledOptions.length) % enabledOptions.length;
|
|
36
|
+
onChange(enabledOptions[prevPos].value);
|
|
37
|
+
}
|
|
38
|
+
else if (e.key === 'Home') {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
onChange(enabledOptions[0].value);
|
|
41
|
+
}
|
|
42
|
+
else if (e.key === 'End') {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
onChange(enabledOptions[enabledOptions.length - 1].value);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return (jsx("div", { ref: ref, role: "tablist", "aria-orientation": "horizontal", className: buildClassName('inline-flex items-center border border-[var(--ui-border)] bg-gray-100/80 dark:bg-gray-800/80', SIZE_CONTAINER_CLASS[size], fullWidth ? 'w-full flex' : '', disabled ? 'opacity-60 cursor-not-allowed' : '', className), "data-testid": "segmented-control", ...restProps, children: options.map((option, index) => {
|
|
48
|
+
const isSelected = value === option.value;
|
|
49
|
+
const isOptionDisabled = disabled || option.disabled;
|
|
50
|
+
return (jsxs("button", { type: "button", role: "tab", "aria-selected": isSelected, "aria-disabled": isOptionDisabled, tabIndex: isSelected && !isOptionDisabled ? 0 : -1, disabled: isOptionDisabled, title: option.title, onClick: () => {
|
|
51
|
+
if (!isOptionDisabled) {
|
|
52
|
+
onChange(option.value);
|
|
53
|
+
}
|
|
54
|
+
}, onKeyDown: (e) => handleKeyDown(e, index), className: buildClassName('inline-flex items-center justify-center gap-1.5 transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]', SIZE_OPTION_CLASS[size], fullWidth ? 'flex-1' : '', isOptionDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer', isSelected
|
|
55
|
+
? 'bg-white text-[var(--ui-primary)] dark:bg-gray-700 dark:text-blue-400 shadow-xs font-semibold'
|
|
56
|
+
: 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100'), "data-testid": `segmented-option-${option.value}`, children: [option.icon && (jsx("span", { className: buildClassName('shrink-0 inline-flex items-center justify-center', SIZE_ICON_CLASS[size]), children: option.icon })), jsx("span", { children: option.label })] }, option.value));
|
|
57
|
+
}) }));
|
|
58
|
+
});
|
|
59
|
+
SegmentedControl.displayName = 'SegmentedControl';
|
|
60
|
+
|
|
61
|
+
export { SegmentedControl };
|
|
62
|
+
//# sourceMappingURL=SegmentedControl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedControl.js","sources":["../../../../../src/components/SegmentedControl/SegmentedControl.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport type { SegmentedControlProps } from './SegmentedControl.types'\n\nconst SIZE_CONTAINER_CLASS = {\n sm: 'p-0.5 gap-0.5 rounded-lg text-xs',\n md: 'p-1 gap-1 rounded-xl text-sm',\n lg: 'p-1.5 gap-1.5 rounded-xl text-base',\n}\n\nconst SIZE_OPTION_CLASS = {\n sm: 'px-2 py-1 text-xs font-medium rounded-md',\n md: 'px-3 py-1.5 text-sm font-semibold rounded-lg',\n lg: 'px-4 py-2 text-base font-semibold rounded-lg',\n}\n\nconst SIZE_ICON_CLASS = {\n sm: 'size-3.5',\n md: 'size-4',\n lg: 'size-5',\n}\n\nexport const SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>((props, ref) => {\n const {\n options,\n value,\n onChange,\n disabled = false,\n size = 'md',\n fullWidth = false,\n className,\n ...restProps\n } = props\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>, currentIndex: number) => {\n const enabledOptions = options.filter((opt) => !opt.disabled && !disabled)\n if (enabledOptions.length === 0) return\n\n if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {\n e.preventDefault()\n const currentPos = enabledOptions.findIndex(\n (opt) => opt.value === options[currentIndex].value,\n )\n const nextPos = (currentPos + 1) % enabledOptions.length\n onChange(enabledOptions[nextPos].value)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {\n e.preventDefault()\n const currentPos = enabledOptions.findIndex(\n (opt) => opt.value === options[currentIndex].value,\n )\n const prevPos = (currentPos - 1 + enabledOptions.length) % enabledOptions.length\n onChange(enabledOptions[prevPos].value)\n } else if (e.key === 'Home') {\n e.preventDefault()\n onChange(enabledOptions[0].value)\n } else if (e.key === 'End') {\n e.preventDefault()\n onChange(enabledOptions[enabledOptions.length - 1].value)\n }\n }\n\n return (\n <div\n ref={ref}\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n className={buildClassName(\n 'inline-flex items-center border border-[var(--ui-border)] bg-gray-100/80 dark:bg-gray-800/80',\n SIZE_CONTAINER_CLASS[size],\n fullWidth ? 'w-full flex' : '',\n disabled ? 'opacity-60 cursor-not-allowed' : '',\n className,\n )}\n data-testid=\"segmented-control\"\n {...restProps}\n >\n {options.map((option, index) => {\n const isSelected = value === option.value\n const isOptionDisabled = disabled || option.disabled\n\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n aria-disabled={isOptionDisabled}\n tabIndex={isSelected && !isOptionDisabled ? 0 : -1}\n disabled={isOptionDisabled}\n title={option.title}\n onClick={() => {\n if (!isOptionDisabled) {\n onChange(option.value)\n }\n }}\n onKeyDown={(e) => handleKeyDown(e, index)}\n className={buildClassName(\n 'inline-flex items-center justify-center gap-1.5 transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary-ring)]',\n SIZE_OPTION_CLASS[size],\n fullWidth ? 'flex-1' : '',\n isOptionDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',\n isSelected\n ? 'bg-white text-[var(--ui-primary)] dark:bg-gray-700 dark:text-blue-400 shadow-xs font-semibold'\n : 'text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100',\n )}\n data-testid={`segmented-option-${option.value}`}\n >\n {option.icon && (\n <span\n className={buildClassName(\n 'shrink-0 inline-flex items-center justify-center',\n SIZE_ICON_CLASS[size],\n )}\n >\n {option.icon}\n </span>\n )}\n <span>{option.label}</span>\n </button>\n )\n })}\n </div>\n )\n})\n\nSegmentedControl.displayName = 'SegmentedControl'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|