@nofinite/nui 1.1.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -48
- package/dist/components/accordion/Accordion.cjs +1 -1
- package/dist/components/accordion/Accordion.cjs.map +1 -1
- package/dist/components/accordion/Accordion.js +64 -43
- package/dist/components/accordion/Accordion.js.map +1 -1
- package/dist/components/alert/Alert.cjs +1 -1
- package/dist/components/alert/Alert.cjs.map +1 -1
- package/dist/components/alert/Alert.js +39 -25
- package/dist/components/alert/Alert.js.map +1 -1
- package/dist/components/avatar/Avatar.cjs +1 -1
- package/dist/components/avatar/Avatar.cjs.map +1 -1
- package/dist/components/avatar/Avatar.js +58 -44
- package/dist/components/avatar/Avatar.js.map +1 -1
- package/dist/components/avatar/AvatarGroup.cjs +1 -1
- package/dist/components/avatar/AvatarGroup.cjs.map +1 -1
- package/dist/components/avatar/AvatarGroup.js +34 -25
- package/dist/components/avatar/AvatarGroup.js.map +1 -1
- package/dist/components/badge/Badge.cjs +1 -1
- package/dist/components/badge/Badge.cjs.map +1 -1
- package/dist/components/badge/Badge.js +43 -68
- package/dist/components/badge/Badge.js.map +1 -1
- package/dist/components/badge/BadgeGroup.cjs +1 -1
- package/dist/components/badge/BadgeGroup.cjs.map +1 -1
- package/dist/components/badge/BadgeGroup.js +20 -10
- package/dist/components/badge/BadgeGroup.js.map +1 -1
- package/dist/components/breadcrumbs/Breadcrumbs.cjs +1 -1
- package/dist/components/breadcrumbs/Breadcrumbs.cjs.map +1 -1
- package/dist/components/breadcrumbs/Breadcrumbs.js +59 -39
- package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/components/button/Button.cjs +1 -1
- package/dist/components/button/Button.cjs.map +1 -1
- package/dist/components/button/Button.js +52 -17
- package/dist/components/button/Button.js.map +1 -1
- package/dist/components/card/Card.cjs +1 -1
- package/dist/components/card/Card.cjs.map +1 -1
- package/dist/components/card/Card.js +44 -41
- package/dist/components/card/Card.js.map +1 -1
- package/dist/components/checkbox/Checkbox.cjs +1 -1
- package/dist/components/checkbox/Checkbox.cjs.map +1 -1
- package/dist/components/checkbox/Checkbox.js +59 -40
- package/dist/components/checkbox/Checkbox.js.map +1 -1
- package/dist/components/chip/Chip.cjs +1 -1
- package/dist/components/chip/Chip.cjs.map +1 -1
- package/dist/components/chip/Chip.js +67 -47
- package/dist/components/chip/Chip.js.map +1 -1
- package/dist/components/combobox/Combobox.cjs +1 -1
- package/dist/components/combobox/Combobox.cjs.map +1 -1
- package/dist/components/combobox/Combobox.js +123 -108
- package/dist/components/combobox/Combobox.js.map +1 -1
- package/dist/components/commandpalette/CommandPalette.cjs +1 -1
- package/dist/components/commandpalette/CommandPalette.cjs.map +1 -1
- package/dist/components/commandpalette/CommandPalette.js +96 -73
- package/dist/components/commandpalette/CommandPalette.js.map +1 -1
- package/dist/components/contextmenu/ContextMenu.cjs +1 -1
- package/dist/components/contextmenu/ContextMenu.cjs.map +1 -1
- package/dist/components/contextmenu/ContextMenu.js +79 -58
- package/dist/components/contextmenu/ContextMenu.js.map +1 -1
- package/dist/components/datagrid/DataGrid.cjs +1 -1
- package/dist/components/datagrid/DataGrid.cjs.map +1 -1
- package/dist/components/datagrid/DataGrid.js +184 -202
- package/dist/components/datagrid/DataGrid.js.map +1 -1
- package/dist/components/datepicker/DatePicker.cjs +1 -1
- package/dist/components/datepicker/DatePicker.cjs.map +1 -1
- package/dist/components/datepicker/DatePicker.js +197 -164
- package/dist/components/datepicker/DatePicker.js.map +1 -1
- package/dist/components/daterangepicker/DateRangePicker.cjs +1 -1
- package/dist/components/daterangepicker/DateRangePicker.cjs.map +1 -1
- package/dist/components/daterangepicker/DateRangePicker.js +254 -213
- package/dist/components/daterangepicker/DateRangePicker.js.map +1 -1
- package/dist/components/dialog/DialogProvider.cjs +2 -0
- package/dist/components/dialog/DialogProvider.cjs.map +1 -0
- package/dist/components/dialog/DialogProvider.js +71 -0
- package/dist/components/dialog/DialogProvider.js.map +1 -0
- package/dist/components/dialog/dialogStore.cjs +2 -0
- package/dist/components/dialog/dialogStore.cjs.map +1 -0
- package/dist/components/dialog/dialogStore.js +60 -0
- package/dist/components/dialog/dialogStore.js.map +1 -0
- package/dist/components/drawer/Drawer.cjs +1 -1
- package/dist/components/drawer/Drawer.cjs.map +1 -1
- package/dist/components/drawer/Drawer.js +69 -47
- package/dist/components/drawer/Drawer.js.map +1 -1
- package/dist/components/dropdown/Dropdown.cjs +1 -1
- package/dist/components/dropdown/Dropdown.cjs.map +1 -1
- package/dist/components/dropdown/Dropdown.js +134 -108
- package/dist/components/dropdown/Dropdown.js.map +1 -1
- package/dist/components/fileuploader/FileUploader.cjs +1 -1
- package/dist/components/fileuploader/FileUploader.cjs.map +1 -1
- package/dist/components/fileuploader/FileUploader.js +96 -61
- package/dist/components/fileuploader/FileUploader.js.map +1 -1
- package/dist/components/hovercard/HoverCard.cjs +1 -1
- package/dist/components/hovercard/HoverCard.cjs.map +1 -1
- package/dist/components/hovercard/HoverCard.js +124 -69
- package/dist/components/hovercard/HoverCard.js.map +1 -1
- package/dist/components/input/Input.cjs +1 -1
- package/dist/components/input/Input.cjs.map +1 -1
- package/dist/components/input/Input.js +62 -37
- package/dist/components/input/Input.js.map +1 -1
- package/dist/components/layout/Container.cjs +1 -1
- package/dist/components/layout/Container.cjs.map +1 -1
- package/dist/components/layout/Container.js +21 -30
- package/dist/components/layout/Container.js.map +1 -1
- package/dist/components/layout/Flex.cjs +1 -1
- package/dist/components/layout/Flex.cjs.map +1 -1
- package/dist/components/layout/Flex.js +36 -19
- package/dist/components/layout/Flex.js.map +1 -1
- package/dist/components/layout/Grid.cjs +1 -1
- package/dist/components/layout/Grid.cjs.map +1 -1
- package/dist/components/layout/Grid.js +30 -18
- package/dist/components/layout/Grid.js.map +1 -1
- package/dist/components/link/Link.cjs +2 -0
- package/dist/components/link/Link.cjs.map +1 -0
- package/dist/components/link/Link.js +41 -0
- package/dist/components/link/Link.js.map +1 -0
- package/dist/components/megamenu/MegaMenu.cjs +1 -1
- package/dist/components/megamenu/MegaMenu.cjs.map +1 -1
- package/dist/components/megamenu/MegaMenu.js +107 -38
- package/dist/components/megamenu/MegaMenu.js.map +1 -1
- package/dist/components/modal/Modal.cjs +1 -1
- package/dist/components/modal/Modal.cjs.map +1 -1
- package/dist/components/modal/Modal.js +91 -83
- package/dist/components/modal/Modal.js.map +1 -1
- package/dist/components/multiselect/MultiSelect.cjs +2 -0
- package/dist/components/multiselect/MultiSelect.cjs.map +1 -0
- package/dist/components/multiselect/MultiSelect.js +176 -0
- package/dist/components/multiselect/MultiSelect.js.map +1 -0
- package/dist/components/nuiprovider/NUIProvider.cjs +2 -0
- package/dist/components/nuiprovider/NUIProvider.cjs.map +1 -0
- package/dist/components/nuiprovider/NUIProvider.js +36 -0
- package/dist/components/nuiprovider/NUIProvider.js.map +1 -0
- package/dist/components/pagination/Pagination.cjs +1 -1
- package/dist/components/pagination/Pagination.cjs.map +1 -1
- package/dist/components/pagination/Pagination.js +74 -41
- package/dist/components/pagination/Pagination.js.map +1 -1
- package/dist/components/popover/Popover.cjs +1 -1
- package/dist/components/popover/Popover.cjs.map +1 -1
- package/dist/components/popover/Popover.js +99 -100
- package/dist/components/popover/Popover.js.map +1 -1
- package/dist/components/progress/Progress.cjs +1 -1
- package/dist/components/progress/Progress.cjs.map +1 -1
- package/dist/components/progress/Progress.js +44 -22
- package/dist/components/progress/Progress.js.map +1 -1
- package/dist/components/radiogroup/RadioGroup.cjs +1 -1
- package/dist/components/radiogroup/RadioGroup.cjs.map +1 -1
- package/dist/components/radiogroup/RadioGroup.js +69 -74
- package/dist/components/radiogroup/RadioGroup.js.map +1 -1
- package/dist/components/rating/Rating.cjs +1 -1
- package/dist/components/rating/Rating.cjs.map +1 -1
- package/dist/components/rating/Rating.js +72 -33
- package/dist/components/rating/Rating.js.map +1 -1
- package/dist/components/resizable/Resizable.cjs +2 -0
- package/dist/components/resizable/Resizable.cjs.map +1 -0
- package/dist/components/resizable/Resizable.js +134 -0
- package/dist/components/resizable/Resizable.js.map +1 -0
- package/dist/components/select/Select.cjs +1 -1
- package/dist/components/select/Select.cjs.map +1 -1
- package/dist/components/select/Select.js +114 -113
- package/dist/components/select/Select.js.map +1 -1
- package/dist/components/skeleton/Skeleton.cjs +1 -1
- package/dist/components/skeleton/Skeleton.cjs.map +1 -1
- package/dist/components/skeleton/Skeleton.js +90 -67
- package/dist/components/skeleton/Skeleton.js.map +1 -1
- package/dist/components/slider/Slider.cjs +1 -1
- package/dist/components/slider/Slider.cjs.map +1 -1
- package/dist/components/slider/Slider.js +85 -82
- package/dist/components/slider/Slider.js.map +1 -1
- package/dist/components/spinner/Spinner.cjs +1 -1
- package/dist/components/spinner/Spinner.cjs.map +1 -1
- package/dist/components/spinner/Spinner.js +60 -17
- package/dist/components/spinner/Spinner.js.map +1 -1
- package/dist/components/stepper/Stepper.cjs +1 -5
- package/dist/components/stepper/Stepper.cjs.map +1 -1
- package/dist/components/stepper/Stepper.js +65 -39
- package/dist/components/stepper/Stepper.js.map +1 -1
- package/dist/components/switch/Switch.cjs +1 -1
- package/dist/components/switch/Switch.cjs.map +1 -1
- package/dist/components/switch/Switch.js +89 -62
- package/dist/components/switch/Switch.js.map +1 -1
- package/dist/components/table/Table.cjs +1 -1
- package/dist/components/table/Table.cjs.map +1 -1
- package/dist/components/table/Table.js +62 -35
- package/dist/components/table/Table.js.map +1 -1
- package/dist/components/tabs/Tabs.cjs +1 -1
- package/dist/components/tabs/Tabs.cjs.map +1 -1
- package/dist/components/tabs/Tabs.js +110 -50
- package/dist/components/tabs/Tabs.js.map +1 -1
- package/dist/components/textarea/Textarea.cjs +1 -1
- package/dist/components/textarea/Textarea.cjs.map +1 -1
- package/dist/components/textarea/Textarea.js +63 -58
- package/dist/components/textarea/Textarea.js.map +1 -1
- package/dist/components/timepicker/TimePicker.cjs +2 -0
- package/dist/components/timepicker/TimePicker.cjs.map +1 -0
- package/dist/components/timepicker/TimePicker.js +159 -0
- package/dist/components/timepicker/TimePicker.js.map +1 -0
- package/dist/components/timerangepicker/TimeRangePicker.cjs +2 -0
- package/dist/components/timerangepicker/TimeRangePicker.cjs.map +1 -0
- package/dist/components/timerangepicker/TimeRangePicker.js +208 -0
- package/dist/components/timerangepicker/TimeRangePicker.js.map +1 -0
- package/dist/components/toast/Toast.cjs +1 -1
- package/dist/components/toast/Toast.cjs.map +1 -1
- package/dist/components/toast/Toast.js +91 -38
- package/dist/components/toast/Toast.js.map +1 -1
- package/dist/components/tooltip/Tooltip.cjs +1 -1
- package/dist/components/tooltip/Tooltip.cjs.map +1 -1
- package/dist/components/tooltip/Tooltip.js +72 -56
- package/dist/components/tooltip/Tooltip.js.map +1 -1
- package/dist/components/treeview/TreeView.cjs +1 -1
- package/dist/components/treeview/TreeView.cjs.map +1 -1
- package/dist/components/treeview/TreeView.js +120 -90
- package/dist/components/treeview/TreeView.js.map +1 -1
- package/dist/components/virtuallist/VirtualList.cjs +1 -1
- package/dist/components/virtuallist/VirtualList.cjs.map +1 -1
- package/dist/components/virtuallist/VirtualList.js +52 -34
- package/dist/components/virtuallist/VirtualList.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -0
- package/dist/index.js +118 -107
- package/dist/index.js.map +1 -1
- package/dist/package.json +49 -6
- package/dist/types/components/accordion/Accordion.d.ts +7 -3
- package/dist/types/components/accordion/Accordion.d.ts.map +1 -1
- package/dist/types/components/alert/Alert.d.ts +18 -5
- package/dist/types/components/alert/Alert.d.ts.map +1 -1
- package/dist/types/components/avatar/Avatar.d.ts +12 -8
- package/dist/types/components/avatar/Avatar.d.ts.map +1 -1
- package/dist/types/components/avatar/AvatarGroup.d.ts +11 -4
- package/dist/types/components/avatar/AvatarGroup.d.ts.map +1 -1
- package/dist/types/components/badge/Badge.d.ts +19 -11
- package/dist/types/components/badge/Badge.d.ts.map +1 -1
- package/dist/types/components/badge/BadgeGroup.d.ts +7 -4
- package/dist/types/components/badge/BadgeGroup.d.ts.map +1 -1
- package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts +14 -6
- package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/types/components/button/Button.d.ts +25 -10
- package/dist/types/components/button/Button.d.ts.map +1 -1
- package/dist/types/components/card/Card.d.ts +12 -21
- package/dist/types/components/card/Card.d.ts.map +1 -1
- package/dist/types/components/checkbox/Checkbox.d.ts +12 -7
- package/dist/types/components/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/types/components/chip/Chip.d.ts +14 -11
- package/dist/types/components/chip/Chip.d.ts.map +1 -1
- package/dist/types/components/combobox/Combobox.d.ts +15 -4
- package/dist/types/components/combobox/Combobox.d.ts.map +1 -1
- package/dist/types/components/commandpalette/CommandPalette.d.ts +12 -3
- package/dist/types/components/commandpalette/CommandPalette.d.ts.map +1 -1
- package/dist/types/components/contextmenu/ContextMenu.d.ts +14 -6
- package/dist/types/components/contextmenu/ContextMenu.d.ts.map +1 -1
- package/dist/types/components/datagrid/DataGrid.d.ts +16 -4
- package/dist/types/components/datagrid/DataGrid.d.ts.map +1 -1
- package/dist/types/components/datepicker/DatePicker.d.ts +13 -1
- package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
- package/dist/types/components/daterangepicker/DateRangePicker.d.ts +3 -1
- package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -1
- package/dist/types/components/dialog/DialogProvider.d.ts +2 -0
- package/dist/types/components/dialog/DialogProvider.d.ts.map +1 -0
- package/dist/types/components/dialog/dialogStore.d.ts +42 -0
- package/dist/types/components/dialog/dialogStore.d.ts.map +1 -0
- package/dist/types/components/drawer/Drawer.d.ts +18 -4
- package/dist/types/components/drawer/Drawer.d.ts.map +1 -1
- package/dist/types/components/dropdown/Dropdown.d.ts +21 -16
- package/dist/types/components/dropdown/Dropdown.d.ts.map +1 -1
- package/dist/types/components/fileuploader/FileUploader.d.ts +22 -3
- package/dist/types/components/fileuploader/FileUploader.d.ts.map +1 -1
- package/dist/types/components/hovercard/HoverCard.d.ts +45 -5
- package/dist/types/components/hovercard/HoverCard.d.ts.map +1 -1
- package/dist/types/components/input/Input.d.ts +20 -10
- package/dist/types/components/input/Input.d.ts.map +1 -1
- package/dist/types/components/layout/Container.d.ts +8 -4
- package/dist/types/components/layout/Container.d.ts.map +1 -1
- package/dist/types/components/layout/Flex.d.ts +27 -10
- package/dist/types/components/layout/Flex.d.ts.map +1 -1
- package/dist/types/components/layout/Grid.d.ts +11 -5
- package/dist/types/components/layout/Grid.d.ts.map +1 -1
- package/dist/types/components/link/Link.d.ts +22 -0
- package/dist/types/components/link/Link.d.ts.map +1 -0
- package/dist/types/components/megamenu/MegaMenu.d.ts +8 -11
- package/dist/types/components/megamenu/MegaMenu.d.ts.map +1 -1
- package/dist/types/components/modal/Modal.d.ts +8 -7
- package/dist/types/components/modal/Modal.d.ts.map +1 -1
- package/dist/types/components/multiselect/MultiSelect.d.ts +33 -0
- package/dist/types/components/multiselect/MultiSelect.d.ts.map +1 -0
- package/dist/types/components/nuiprovider/NUIProvider.d.ts +29 -0
- package/dist/types/components/nuiprovider/NUIProvider.d.ts.map +1 -0
- package/dist/types/components/pagination/Pagination.d.ts +17 -3
- package/dist/types/components/pagination/Pagination.d.ts.map +1 -1
- package/dist/types/components/popover/Popover.d.ts +54 -16
- package/dist/types/components/popover/Popover.d.ts.map +1 -1
- package/dist/types/components/progress/Progress.d.ts +17 -7
- package/dist/types/components/progress/Progress.d.ts.map +1 -1
- package/dist/types/components/radiogroup/RadioGroup.d.ts +15 -10
- package/dist/types/components/radiogroup/RadioGroup.d.ts.map +1 -1
- package/dist/types/components/rating/Rating.d.ts +24 -10
- package/dist/types/components/rating/Rating.d.ts.map +1 -1
- package/dist/types/components/resizable/Resizable.d.ts +24 -0
- package/dist/types/components/resizable/Resizable.d.ts.map +1 -0
- package/dist/types/components/select/Select.d.ts +17 -8
- package/dist/types/components/select/Select.d.ts.map +1 -1
- package/dist/types/components/skeleton/Skeleton.d.ts +37 -36
- package/dist/types/components/skeleton/Skeleton.d.ts.map +1 -1
- package/dist/types/components/slider/Slider.d.ts +15 -4
- package/dist/types/components/slider/Slider.d.ts.map +1 -1
- package/dist/types/components/spinner/Spinner.d.ts +14 -4
- package/dist/types/components/spinner/Spinner.d.ts.map +1 -1
- package/dist/types/components/stepper/Stepper.d.ts +17 -3
- package/dist/types/components/stepper/Stepper.d.ts.map +1 -1
- package/dist/types/components/switch/Switch.d.ts +20 -5
- package/dist/types/components/switch/Switch.d.ts.map +1 -1
- package/dist/types/components/table/Table.d.ts +24 -4
- package/dist/types/components/table/Table.d.ts.map +1 -1
- package/dist/types/components/tabs/Tabs.d.ts +25 -12
- package/dist/types/components/tabs/Tabs.d.ts.map +1 -1
- package/dist/types/components/textarea/Textarea.d.ts +8 -5
- package/dist/types/components/textarea/Textarea.d.ts.map +1 -1
- package/dist/types/components/timepicker/TimePicker.d.ts +26 -0
- package/dist/types/components/timepicker/TimePicker.d.ts.map +1 -0
- package/dist/types/components/timerangepicker/TimeRangePicker.d.ts +32 -0
- package/dist/types/components/timerangepicker/TimeRangePicker.d.ts.map +1 -0
- package/dist/types/components/toast/Toast.d.ts +23 -7
- package/dist/types/components/toast/Toast.d.ts.map +1 -1
- package/dist/types/components/tooltip/Tooltip.d.ts +13 -2
- package/dist/types/components/tooltip/Tooltip.d.ts.map +1 -1
- package/dist/types/components/treeview/TreeView.d.ts +20 -6
- package/dist/types/components/treeview/TreeView.d.ts.map +1 -1
- package/dist/types/components/virtuallist/VirtualList.d.ts +12 -16
- package/dist/types/components/virtuallist/VirtualList.d.ts.map +1 -1
- package/dist/types/index.d.ts +8 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/cn/cn.d.ts +19 -0
- package/dist/types/utils/cn/cn.d.ts.map +1 -0
- package/dist/types/utils/generateid/generateId.d.ts +7 -0
- package/dist/types/utils/generateid/generateId.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/inertmanager/inertManager.d.ts +13 -0
- package/dist/types/utils/inertmanager/inertManager.d.ts.map +1 -1
- package/dist/types/utils/keyboardnav/keyboardNav.d.ts +17 -6
- package/dist/types/utils/keyboardnav/keyboardNav.d.ts.map +1 -1
- package/dist/types/utils/onclickoutside/onClickOutside.d.ts +9 -1
- package/dist/types/utils/onclickoutside/onClickOutside.d.ts.map +1 -1
- package/dist/types/utils/portal/portal.d.ts +14 -1
- package/dist/types/utils/portal/portal.d.ts.map +1 -1
- package/dist/types/utils/restorefocus/restoreFocus.d.ts +8 -4
- package/dist/types/utils/restorefocus/restoreFocus.d.ts.map +1 -1
- package/dist/types/utils/scrolllock/scrollLock.d.ts +10 -2
- package/dist/types/utils/scrolllock/scrollLock.d.ts.map +1 -1
- package/dist/types/utils/slot/slot.d.ts +12 -0
- package/dist/types/utils/slot/slot.d.ts.map +1 -0
- package/dist/types/utils/trapfocus/trapFocus.d.ts +6 -2
- package/dist/types/utils/trapfocus/trapFocus.d.ts.map +1 -1
- package/dist/utils/cn/cn.cjs +2 -0
- package/dist/utils/cn/cn.cjs.map +1 -0
- package/dist/utils/cn/cn.js +21 -0
- package/dist/utils/cn/cn.js.map +1 -0
- package/dist/utils/inertmanager/inertManager.cjs.map +1 -1
- package/dist/utils/inertmanager/inertManager.js.map +1 -1
- package/dist/utils/onclickoutside/onClickOutside.cjs +1 -1
- package/dist/utils/onclickoutside/onClickOutside.cjs.map +1 -1
- package/dist/utils/onclickoutside/onClickOutside.js +10 -6
- package/dist/utils/onclickoutside/onClickOutside.js.map +1 -1
- package/dist/utils/portal/portal.cjs.map +1 -1
- package/dist/utils/portal/portal.js.map +1 -1
- package/dist/utils/restorefocus/restoreFocus.cjs.map +1 -1
- package/dist/utils/restorefocus/restoreFocus.js.map +1 -1
- package/dist/utils/scrolllock/scrollLock.cjs.map +1 -1
- package/dist/utils/scrolllock/scrollLock.js +7 -0
- package/dist/utils/scrolllock/scrollLock.js.map +1 -1
- package/dist/utils/slot/slot.cjs +2 -0
- package/dist/utils/slot/slot.cjs.map +1 -0
- package/dist/utils/slot/slot.js +57 -0
- package/dist/utils/slot/slot.js.map +1 -0
- package/dist/utils/trapfocus/trapFocus.cjs.map +1 -1
- package/dist/utils/trapfocus/trapFocus.js.map +1 -1
- package/package.json +49 -6
- package/dist/components/layout/HStack.cjs +0 -2
- package/dist/components/layout/HStack.cjs.map +0 -1
- package/dist/components/layout/HStack.js +0 -9
- package/dist/components/layout/HStack.js.map +0 -1
- package/dist/components/layout/Stack.cjs +0 -2
- package/dist/components/layout/Stack.cjs.map +0 -1
- package/dist/components/layout/Stack.js +0 -9
- package/dist/components/layout/Stack.js.map +0 -1
- package/dist/styles/nui.css +0 -1
- package/dist/theme/NUIProvider.cjs +0 -2
- package/dist/theme/NUIProvider.cjs.map +0 -1
- package/dist/theme/NUIProvider.js +0 -34
- package/dist/theme/NUIProvider.js.map +0 -1
- package/dist/theme/useTheme.cjs +0 -2
- package/dist/theme/useTheme.cjs.map +0 -1
- package/dist/theme/useTheme.js +0 -9
- package/dist/theme/useTheme.js.map +0 -1
- package/dist/types/components/layout/HStack.d.ts +0 -8
- package/dist/types/components/layout/HStack.d.ts.map +0 -1
- package/dist/types/components/layout/Stack.d.ts +0 -8
- package/dist/types/components/layout/Stack.d.ts.map +0 -1
- package/dist/types/theme/NUIProvider.d.ts +0 -14
- package/dist/types/theme/NUIProvider.d.ts.map +0 -1
- package/dist/types/theme/useTheme.d.ts +0 -11
- package/dist/types/theme/useTheme.d.ts.map +0 -1
- package/dist/utils/generateid/generateId.cjs +0 -2
- package/dist/utils/generateid/generateId.cjs.map +0 -1
- package/dist/utils/generateid/generateId.js +0 -7
- package/dist/utils/generateid/generateId.js.map +0 -1
- package/dist/utils/keyboardnav/keyboardNav.cjs +0 -2
- package/dist/utils/keyboardnav/keyboardNav.cjs.map +0 -1
- package/dist/utils/keyboardnav/keyboardNav.js +0 -10
- package/dist/utils/keyboardnav/keyboardNav.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["/**\r\n * Select.tsx\r\n * ----------\r\n * Accessible single-select (listbox) component.\r\n *\r\n * Features:\r\n * - WAI-ARIA listbox pattern\r\n * - Keyboard navigation (ArrowUp/ArrowDown, Home, End, Enter, Space, Esc)\r\n * - Typeahead support\r\n * - Controlled + uncontrolled modes\r\n * - Portal rendering for the listbox\r\n * - Click outside to close\r\n * - Proper ARIA attributes and relationships\r\n * - Hidden input for form compatibility (optional name prop)\r\n *\r\n * Usage:\r\n * <Select\r\n * options={[{ value: 'a', label: 'Apple' }, { value: 'b', label: 'Banana' }]}\r\n * value={value} // optional controlled value\r\n * onChange={(v) => setValue(v)} // required if controlled\r\n * placeholder=\"Select fruit\"\r\n * name=\"fruit\" // optional, adds hidden input\r\n * />\r\n */\r\n\r\nimport React, {\r\n useState,\r\n useRef,\r\n useEffect,\r\n useCallback,\r\n KeyboardEvent,\r\n} from 'react';\r\nimport './Select.css';\r\nimport { Portal, onClickOutside, restoreFocus } from '../../utils/index';\r\n\r\ntype Option = {\r\n value: string;\r\n label: React.ReactNode;\r\n disabled?: boolean;\r\n};\r\n\r\ninterface SelectProps {\r\n options: Option[];\r\n value?: string; // controlled value\r\n defaultValue?: string; // uncontrolled initial\r\n onChange?: (value: string) => void;\r\n placeholder?: string;\r\n disabled?: boolean;\r\n name?: string; // if provided, render hidden input for forms\r\n id?: string;\r\n className?: string;\r\n}\r\n\r\n/* Helper: find next enabled index given direction */\r\nfunction findNextEnabled(options: Option[], start: number, direction: 1 | -1) {\r\n const len = options.length;\r\n let i = start;\r\n for (let step = 0; step < len; step++) {\r\n i = (i + direction + len) % len;\r\n if (!options[i].disabled) return i;\r\n }\r\n return -1;\r\n}\r\n\r\nexport function Select({\r\n options,\r\n value,\r\n defaultValue,\r\n onChange,\r\n placeholder = 'Select...',\r\n disabled = false,\r\n name,\r\n id,\r\n className = '',\r\n}: SelectProps) {\r\n // Controlled vs uncontrolled\r\n const isControlled = value !== undefined;\r\n const [internalValue, setInternalValue] = useState<string | undefined>(\r\n defaultValue\r\n );\r\n const selectedValue = isControlled ? value : internalValue;\r\n\r\n const selectedOption = options.find((o) => o.value === selectedValue) ?? null;\r\n\r\n const [open, setOpen] = useState(false);\r\n const [activeIndex, setActiveIndex] = useState<number>(() =>\r\n options.findIndex((o) => !o.disabled)\r\n );\r\n\r\n // Typeahead buffer\r\n const typeaheadRef = useRef({ buffer: '', lastTime: 0 });\r\n\r\n // Refs\r\n const triggerRef = useRef<HTMLButtonElement | null>(null);\r\n const listRef = useRef<HTMLDivElement | null>(null);\r\n\r\n // Unique ids\r\n const reactId = React.useId();\r\n const baseId = id ?? reactId;\r\n const listboxId = `${baseId}-listbox`;\r\n const labelId = `${baseId}-label`;\r\n\r\n // Open/close helpers\r\n const openList = useCallback(() => {\r\n if (disabled) return;\r\n setOpen(true);\r\n }, [disabled]);\r\n\r\n const closeList = useCallback(() => {\r\n setOpen(false);\r\n // restore focus to trigger\r\n restoreFocus(triggerRef.current);\r\n }, []);\r\n\r\n // Toggle\r\n const toggleList = useCallback(() => {\r\n if (disabled) return;\r\n setOpen((s) => !s);\r\n }, [disabled]);\r\n\r\n // Click outside to close\r\n useEffect(() => {\r\n if (!open) return;\r\n return onClickOutside(listRef, () => setOpen(false));\r\n }, [open]);\r\n\r\n // Ensure that when opening, activeIndex is valid and focus moves to listbox\r\n useEffect(() => {\r\n if (!open) return;\r\n // set active to selected or first enabled\r\n const selIndex = options.findIndex(\r\n (o) => o.value === selectedValue && !o.disabled\r\n );\r\n const idx =\r\n selIndex >= 0 ? selIndex : options.findIndex((o) => !o.disabled);\r\n setActiveIndex(idx >= 0 ? idx : -1);\r\n\r\n // focus the list container so keyboard events are captured\r\n setTimeout(() => {\r\n listRef.current?.focus();\r\n }, 0);\r\n }, [open, options, selectedValue]);\r\n\r\n // Selection handler\r\n const selectIndex = useCallback(\r\n (i: number) => {\r\n if (i < 0 || i >= options.length) return;\r\n const opt = options[i];\r\n if (opt.disabled) return;\r\n if (!isControlled) setInternalValue(opt.value);\r\n onChange?.(opt.value);\r\n setOpen(false);\r\n // restore focus\r\n triggerRef.current?.focus();\r\n },\r\n [isControlled, options, onChange]\r\n );\r\n\r\n // Keyboard handling when trigger has focus\r\n const onTriggerKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\r\n if (disabled) return;\r\n if (['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(e.key)) {\r\n e.preventDefault();\r\n openList();\r\n }\r\n };\r\n\r\n // Keyboard handling when listbox has focus\r\n const onListKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\r\n const key = e.key;\r\n if (key === 'ArrowDown') {\r\n e.preventDefault();\r\n const next = findNextEnabled(options, activeIndex, 1);\r\n if (next >= 0) setActiveIndex(next);\r\n } else if (key === 'ArrowUp') {\r\n e.preventDefault();\r\n const prev = findNextEnabled(options, activeIndex, -1);\r\n if (prev >= 0) setActiveIndex(prev);\r\n } else if (key === 'Home') {\r\n e.preventDefault();\r\n const first = options.findIndex((o) => !o.disabled);\r\n if (first >= 0) setActiveIndex(first);\r\n } else if (key === 'End') {\r\n e.preventDefault();\r\n const last =\r\n options.length -\r\n 1 -\r\n [...options].reverse().findIndex((o) => !o.disabled);\r\n if (last >= 0) setActiveIndex(last);\r\n } else if (key === 'Enter' || key === ' ') {\r\n e.preventDefault();\r\n if (activeIndex >= 0) selectIndex(activeIndex);\r\n } else if (key === 'Escape') {\r\n e.preventDefault();\r\n closeList();\r\n } else if (key.length === 1 && key.match(/\\S/)) {\r\n // typeahead: accumulate buffer of characters\r\n const now = Date.now();\r\n if (now - typeaheadRef.current.lastTime > 700) {\r\n typeaheadRef.current.buffer = '';\r\n }\r\n typeaheadRef.current.buffer += key.toLowerCase();\r\n typeaheadRef.current.lastTime = now;\r\n\r\n const buf = typeaheadRef.current.buffer;\r\n const start = activeIndex >= 0 ? activeIndex + 1 : 0;\r\n const len = options.length;\r\n // search forward from next item, wrapping\r\n for (let i = 0; i < len; i++) {\r\n const idx = (start + i) % len;\r\n const lab = String(options[idx].label).toLowerCase();\r\n if (!options[idx].disabled && lab.startsWith(buf)) {\r\n setActiveIndex(idx);\r\n break;\r\n }\r\n }\r\n }\r\n };\r\n\r\n // Click on option\r\n const onOptionClick = (i: number) => {\r\n selectIndex(i);\r\n };\r\n\r\n // compute listbox position based on trigger\r\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\r\n useEffect(() => {\r\n if (!open || !triggerRef.current) {\r\n setPos(null);\r\n return;\r\n }\r\n const rect = triggerRef.current.getBoundingClientRect();\r\n const top = rect.bottom + 6;\r\n const left = rect.left;\r\n setPos({ top, left });\r\n }, [open]);\r\n\r\n // render\r\n return (\r\n <div className={`ui-select ${className}`}>\r\n {/* Hidden input for form compatibility */}\r\n {name && <input type=\"hidden\" name={name} value={selectedValue ?? ''} />}\r\n\r\n <button\r\n ref={triggerRef}\r\n id={labelId}\r\n type=\"button\"\r\n className=\"ui-select-trigger\"\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n aria-controls={open ? listboxId : undefined}\r\n aria-disabled={disabled || undefined}\r\n onClick={() => toggleList()}\r\n onKeyDown={onTriggerKeyDown}\r\n disabled={disabled}\r\n >\r\n <span>\r\n {selectedOption ? (\r\n <span>{selectedOption.label}</span>\r\n ) : (\r\n <span className=\"ui-select-placeholder\">{placeholder}</span>\r\n )}\r\n </span>\r\n <span className=\"ui-select-chevron\" aria-hidden>\r\n ▾\r\n </span>\r\n </button>\r\n\r\n {open && pos && (\r\n <Portal>\r\n <div\r\n id={listboxId}\r\n ref={listRef}\r\n className=\"ui-select-listbox\"\r\n role=\"listbox\"\r\n aria-labelledby={labelId}\r\n tabIndex={0}\r\n style={{\r\n top: pos.top,\r\n left: pos.left,\r\n }}\r\n onKeyDown={onListKeyDown}\r\n >\r\n {options.map((opt, i) => {\r\n const isSelected = selectedValue === opt.value;\r\n const isActive = activeIndex === i;\r\n return (\r\n <div\r\n key={opt.value}\r\n id={`${listboxId}-option-${i}`}\r\n role=\"option\"\r\n aria-selected={isSelected}\r\n aria-disabled={opt.disabled || undefined}\r\n className=\"ui-select-option\"\r\n tabIndex={-1}\r\n onMouseDown={(e) => e.preventDefault()} /* prevent blur */\r\n onClick={() => !opt.disabled && onOptionClick(i)}\r\n // Visual focus when active (not moving DOM focus)\r\n style={{\r\n outline: isActive\r\n ? '2px solid var(--color-primary)'\r\n : undefined,\r\n }}\r\n >\r\n {opt.label}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </Portal>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["findNextEnabled","options","start","direction","len","i","step","Select","value","defaultValue","onChange","placeholder","disabled","name","id","className","isControlled","internalValue","setInternalValue","useState","selectedValue","selectedOption","o","open","setOpen","activeIndex","setActiveIndex","typeaheadRef","useRef","triggerRef","listRef","reactId","React","baseId","listboxId","labelId","openList","useCallback","closeList","restoreFocus","toggleList","s","useEffect","onClickOutside","selIndex","idx","selectIndex","opt","onTriggerKeyDown","onListKeyDown","key","next","prev","first","last","now","buf","lab","onOptionClick","pos","setPos","rect","top","left","jsxs","jsx","Portal","isSelected","isActive","e"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.js","sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useLayoutEffect,\n KeyboardEvent,\n forwardRef,\n} from 'react';\nimport { Portal, onClickOutside, restoreFocus, cn } from '../../utils';\nimport './Select.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type SelectOption = {\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n};\n\nexport interface SelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'defaultValue' | 'onChange'> {\n /** Array of available options */\n options: SelectOption[];\n /** Controlled state value */\n value?: string; \n /** Uncontrolled initial value */\n defaultValue?: string; \n /** Callback fired when an option is selected */\n onChange?: (value: string) => void;\n /** Text displayed when no option is selected */\n placeholder?: string;\n /** Name attribute applied to the hidden input for native form submission */\n name?: string; \n /** Applies error styling to the trigger button */\n error?: boolean; \n}\n\n/* Helper: find next enabled index given direction */\nfunction findNextEnabled(options: SelectOption[], start: number, direction: 1 | -1) {\n const len = options.length;\n let i = start;\n for (let step = 0; step < len; step++) {\n i = (i + direction + len) % len;\n if (!options[i].disabled) return i;\n }\n return -1;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * Select Component\n * * A highly accessible dropdown select menu.\n * * Automatically manages focus, keyboard typeahead navigation, and viewport collision detection.\n */\nexport const Select = forwardRef<HTMLButtonElement, SelectProps>(({\n options,\n value,\n defaultValue,\n onChange,\n placeholder = 'Select...',\n disabled = false,\n error = false,\n name,\n id,\n className,\n ...props\n}, ref) => {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string | undefined>(defaultValue);\n const selectedValue = isControlled ? value : internalValue;\n const selectedOption = options.find((o) => o.value === selectedValue) ?? null;\n\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number>(() => options.findIndex((o) => !o.disabled));\n\n // Used for WAI-ARIA keyboard typeahead navigation\n const typeaheadRef = useRef({ buffer: '', lastTime: 0 });\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const activeOptionRef = useRef<HTMLDivElement | null>(null);\n\n const reactId = React.useId();\n const baseId = id ?? reactId;\n const listboxId = `${baseId}-listbox`;\n const labelId = `${baseId}-label`;\n\n /* ----------------------------------------------------\n Ref Merging\n ---------------------------------------------------- */\n const setTriggerRef = useCallback((node: HTMLButtonElement | null) => {\n triggerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n /* ----------------------------------------------------\n Smart Position & Width Sync\n ---------------------------------------------------- */\n const [coords, setCoords] = useState({ top: -9999, left: -9999, width: 0 });\n\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !listRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const listRect = listRef.current.getBoundingClientRect();\n const scrollY = window.scrollY;\n const scrollX = window.scrollX;\n\n let top = triggerRect.bottom + scrollY + 4;\n const left = triggerRect.left + scrollX;\n const width = triggerRect.width; // Sync Portal width to trigger width\n\n // Viewport Bottom Collision\n const padding = 16;\n if (triggerRect.bottom + listRect.height + 4 > document.documentElement.clientHeight - padding) {\n top = triggerRect.top + scrollY - listRect.height - 4; // Flip above\n if (top < padding + scrollY) top = padding + scrollY; // Hard top clamp\n }\n\n setCoords({ top, left, width });\n }, []);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [open, updatePosition]);\n\n /* ----------------------------------------------------\n Focus & Scroll Management\n ---------------------------------------------------- */\n const closeList = useCallback(() => {\n setOpen(false);\n restoreFocus(triggerRef.current);\n }, []);\n\n useEffect(() => {\n if (!open) return;\n const cleanup = onClickOutside([listRef, triggerRef], () => setOpen(false));\n return cleanup;\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n // Set active index to the currently selected item, or the first available option\n const selIndex = options.findIndex((o) => o.value === selectedValue && !o.disabled);\n const idx = selIndex >= 0 ? selIndex : options.findIndex((o) => !o.disabled);\n setActiveIndex(idx >= 0 ? idx : -1);\n\n // Defer focus to ensure Portal is rendered\n const timeoutId = setTimeout(() => listRef.current?.focus(), 10);\n return () => clearTimeout(timeoutId);\n }, [open, options, selectedValue]);\n\n // Auto-scroll to active item when navigating via keyboard\n useEffect(() => {\n if (open && activeOptionRef.current) {\n activeOptionRef.current.scrollIntoView({ block: 'nearest' });\n }\n }, [activeIndex, open]);\n\n /* ----------------------------------------------------\n Event Handlers\n ---------------------------------------------------- */\n const selectIndex = useCallback((i: number) => {\n if (i < 0 || i >= options.length) return;\n const opt = options[i];\n if (opt.disabled) return;\n if (!isControlled) setInternalValue(opt.value);\n onChange?.(opt.value);\n setOpen(false);\n triggerRef.current?.focus();\n }, [isControlled, options, onChange]);\n\n const onTriggerKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(e.key)) {\n e.preventDefault();\n setOpen(true);\n }\n };\n\n const onListKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const key = e.key;\n if (key === 'ArrowDown') {\n e.preventDefault();\n const next = findNextEnabled(options, activeIndex, 1);\n if (next >= 0) setActiveIndex(next);\n } else if (key === 'ArrowUp') {\n e.preventDefault();\n const prev = findNextEnabled(options, activeIndex, -1);\n if (prev >= 0) setActiveIndex(prev);\n } else if (key === 'Home') {\n e.preventDefault();\n const first = options.findIndex((o) => !o.disabled);\n if (first >= 0) setActiveIndex(first);\n } else if (key === 'End') {\n e.preventDefault();\n const last = options.length - 1 - [...options].reverse().findIndex((o) => !o.disabled);\n if (last >= 0) setActiveIndex(last);\n } else if (key === 'Enter' || key === ' ') {\n e.preventDefault();\n if (activeIndex >= 0) selectIndex(activeIndex);\n } else if (key === 'Escape') {\n e.preventDefault();\n closeList();\n } else if (key.length === 1 && key.match(/\\S/)) {\n // Typeahead logic\n const now = Date.now();\n if (now - typeaheadRef.current.lastTime > 700) typeaheadRef.current.buffer = '';\n typeaheadRef.current.buffer += key.toLowerCase();\n typeaheadRef.current.lastTime = now;\n\n const buf = typeaheadRef.current.buffer;\n const start = activeIndex >= 0 ? activeIndex + 1 : 0;\n const len = options.length;\n for (let i = 0; i < len; i++) {\n const idx = (start + i) % len;\n const lab = String(options[idx].label).toLowerCase();\n if (!options[idx].disabled && lab.startsWith(buf)) {\n setActiveIndex(idx);\n break;\n }\n }\n }\n };\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n return (\n <div className={cn(\"nui-select-root\", className)}>\n {/* Hidden input for native form submission */}\n {name && <input type=\"hidden\" name={name} value={selectedValue ?? ''} />}\n\n <button\n ref={setTriggerRef}\n id={labelId}\n type=\"button\"\n className={cn(\"nui-select-trigger\", error && \"error\")}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-disabled={disabled || undefined}\n onClick={() => !disabled && setOpen((s) => !s)}\n onKeyDown={onTriggerKeyDown}\n disabled={disabled}\n {...props}\n >\n <span className=\"nui-select-value\">\n {selectedOption ? (\n selectedOption.label\n ) : (\n <span className=\"nui-select-placeholder\">{placeholder}</span>\n )}\n </span>\n <svg className=\"nui-select-chevron\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </button>\n\n {open && (\n <Portal>\n <div\n id={listboxId}\n ref={listRef}\n className=\"nui-select-listbox\"\n role=\"listbox\"\n aria-labelledby={labelId}\n tabIndex={0}\n style={{ top: coords.top, left: coords.left, width: coords.width }}\n onKeyDown={onListKeyDown}\n >\n {options.map((opt, i) => {\n const isSelected = selectedValue === opt.value;\n const isActive = activeIndex === i;\n return (\n <div\n key={opt.value}\n ref={isActive ? activeOptionRef : null}\n id={`${listboxId}-option-${i}`}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={opt.disabled || undefined}\n className={cn(\n \"nui-select-option\",\n isActive && \"active\",\n isSelected && \"selected\",\n opt.disabled && \"disabled\"\n )}\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()} \n onClick={() => !opt.disabled && selectIndex(i)}\n onMouseEnter={() => !opt.disabled && setActiveIndex(i)}\n >\n <span className=\"nui-select-option-label\">{opt.label}</span>\n {isSelected && (\n <svg className=\"nui-select-check\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n )}\n </div>\n );\n })}\n </div>\n </Portal>\n )}\n </div>\n );\n});\nSelect.displayName = 'Select';"],"names":["findNextEnabled","options","start","direction","len","i","step","Select","forwardRef","value","defaultValue","onChange","placeholder","disabled","error","name","id","className","props","ref","isControlled","internalValue","setInternalValue","useState","selectedValue","selectedOption","o","open","setOpen","activeIndex","setActiveIndex","typeaheadRef","useRef","triggerRef","listRef","activeOptionRef","reactId","React","baseId","listboxId","labelId","setTriggerRef","useCallback","node","coords","setCoords","updatePosition","triggerRect","listRect","scrollY","scrollX","top","left","width","padding","useLayoutEffect","closeList","restoreFocus","useEffect","onClickOutside","selIndex","idx","timeoutId","selectIndex","opt","onTriggerKeyDown","onListKeyDown","key","next","prev","first","last","now","buf","lab","cn","jsxs","s","jsx","Portal","isSelected","isActive","e"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),h=require("react");;/* empty css */const o=require("../../utils/cn/cn.cjs");function l(e){if(e!==void 0)return typeof e=="number"?`${e}px`:e}const i=h.forwardRef(({size:e="md",width:t,height:r,animated:s=!0,circle:d=!1,ariaHidden:a=!0,className:x,style:p,...f},m)=>n.jsx("span",{ref:m,"aria-hidden":a,role:"presentation",className:o.cn("nui-skeleton",`nui-skeleton--${e}`,s&&"nui-skeleton--animated",d&&"nui-skeleton--circle",x),style:{width:l(t),height:l(r),...p},...f}));i.displayName="Skeleton";function j({width:e="100%",size:t="md",className:r,...s}){return n.jsx(i,{width:e,size:t,className:r,...s})}function u({lines:e=3,size:t="md",className:r,...s}){return n.jsx("div",{"aria-hidden":"true",className:o.cn("nui-skeleton-paragraph",r),style:{display:"flex",flexDirection:"column",gap:"8px"},...s,children:Array.from({length:e}).map((d,a)=>n.jsx(i,{width:a===e-1?"75%":"100%",size:t},a))})}function c({size:e=40,className:t,...r}){return n.jsx(i,{circle:!0,width:e,className:t,...r})}function y({width:e=100,height:t=40,className:r,...s}){return n.jsx(i,{width:e,height:t,className:o.cn("nui-skeleton-button",r),style:{borderRadius:"6px"},...s})}function g({className:e,style:t,...r}){return n.jsxs("div",{"aria-hidden":"true",className:o.cn("nui-skeleton-card",e),style:{padding:"16px",border:"1px solid var(--nui-border-default, #e2e8f0)",borderRadius:"12px",...t},...r,children:[n.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"12px",marginBottom:"16px"},children:[n.jsx(c,{size:48}),n.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:"8px"},children:[n.jsx(i,{width:"40%",size:"md"}),n.jsx(i,{width:"20%",size:"sm"})]})]}),n.jsx(u,{lines:3})]})}const k=Object.assign(i,{Text:j,Paragraph:u,Avatar:c,Button:y,Card:g});exports.Skeleton=k;
|
|
2
2
|
//# sourceMappingURL=Skeleton.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Skeleton.cjs","sources":["../../../src/components/skeleton/Skeleton.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Skeleton.cjs","sources":["../../../src/components/skeleton/Skeleton.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils';\nimport './Skeleton.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\ntype SkeletonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** The predefined height mapping for the skeleton */\n size?: SkeletonSize;\n /** Explicit width override (supports numbers as px, or strings like '100%') */\n width?: number | string;\n /** Explicit height override (supports numbers as px, or strings like '50px') */\n height?: number | string; \n /** Enables or disables the sweeping shimmer animation. Defaults to true. */\n animated?: boolean;\n /** Forces the skeleton into a perfect circle, ignoring the size height */\n circle?: boolean;\n /** Hides the element from screen readers. Defaults to true (recommended). */\n ariaHidden?: boolean;\n}\n\nfunction formatSize(val?: number | string): string | undefined {\n if (val === undefined) return undefined;\n return typeof val === 'number' ? `${val}px` : val;\n}\n\n/* ============================================================\n * 1. Root Component\n * ============================================================ */\n\n/**\n * Skeleton Component (Root)\n * * A visual placeholder used during asynchronous data fetching.\n * * WAI-ARIA Note: Skeletons are strictly visual and should remain hidden from \n * screen readers (`aria-hidden=\"true\"`) to prevent them from reading out \n * dozens of \"presentation\" or \"empty\" blocks while data loads.\n */\nconst SkeletonRoot = React.forwardRef<HTMLSpanElement, SkeletonProps>(({\n size = 'md',\n width,\n height,\n animated = true,\n circle = false,\n ariaHidden = true,\n className,\n style,\n ...props\n}, ref) => {\n return (\n <span\n ref={ref}\n aria-hidden={ariaHidden}\n role=\"presentation\"\n className={cn(\n 'nui-skeleton',\n `nui-skeleton--${size}`,\n animated && 'nui-skeleton--animated',\n circle && 'nui-skeleton--circle',\n className\n )}\n style={{\n width: formatSize(width),\n height: formatSize(height),\n ...style,\n }}\n {...props}\n />\n );\n});\nSkeletonRoot.displayName = 'Skeleton';\n\n/* ============================================================\n * Helper Components\n * ============================================================ */\n\nexport interface SkeletonTextProps extends React.HTMLAttributes<HTMLSpanElement> {\n width?: number | string;\n size?: SkeletonSize;\n}\n\nfunction Text({ width = '100%', size = 'md', className, ...props }: SkeletonTextProps) {\n return <SkeletonRoot width={width} size={size} className={className} {...props} />;\n}\n\nexport interface SkeletonParagraphProps extends React.HTMLAttributes<HTMLDivElement> {\n lines?: number;\n size?: SkeletonSize;\n}\n\nfunction Paragraph({ lines = 3, size = 'md', className, ...props }: SkeletonParagraphProps) {\n return (\n <div \n aria-hidden=\"true\" \n className={cn(\"nui-skeleton-paragraph\", className)} \n style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}\n {...props}\n >\n {Array.from({ length: lines }).map((_, i) => (\n <SkeletonRoot \n key={i} \n width={i === lines - 1 ? '75%' : '100%'} \n size={size} \n />\n ))}\n </div>\n );\n}\n\nexport interface SkeletonAvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n size?: number | string;\n}\n\nfunction Avatar({ size = 40, className, ...props }: SkeletonAvatarProps) {\n // width sets the size, the CSS aspect-ratio: 1/1 guarantees it stays a perfect circle!\n return <SkeletonRoot circle width={size} className={className} {...props} />;\n}\n\nexport interface SkeletonButtonProps extends React.HTMLAttributes<HTMLSpanElement> {\n width?: number | string;\n height?: number | string;\n}\n\nfunction Button({ width = 100, height = 40, className, ...props }: SkeletonButtonProps) {\n return (\n <SkeletonRoot\n width={width}\n height={height}\n className={cn(\"nui-skeleton-button\", className)}\n style={{ borderRadius: '6px' }}\n {...props}\n />\n );\n}\n\nfunction Card({ className, style, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div \n aria-hidden=\"true\" \n className={cn(\"nui-skeleton-card\", className)} \n style={{ padding: '16px', border: '1px solid var(--nui-border-default, #e2e8f0)', borderRadius: '12px', ...style }}\n {...props}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '16px' }}>\n <Avatar size={48} />\n <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <SkeletonRoot width=\"40%\" size=\"md\" />\n <SkeletonRoot width=\"20%\" size=\"sm\" />\n </div>\n </div>\n <Paragraph lines={3} />\n </div>\n );\n}\n\n/* ============================================================\n * Export\n * ============================================================ */\n\nexport const Skeleton = Object.assign(SkeletonRoot, {\n Text,\n Paragraph,\n Avatar,\n Button,\n Card,\n});"],"names":["formatSize","val","SkeletonRoot","React","size","width","height","animated","circle","ariaHidden","className","style","props","ref","jsx","cn","Text","Paragraph","lines","_","i","Avatar","Button","Card","jsxs","Skeleton"],"mappings":"+MAyBA,SAASA,EAAWC,EAA2C,CAC7D,GAAIA,IAAQ,OACZ,OAAO,OAAOA,GAAQ,SAAW,GAAGA,CAAG,KAAOA,CAChD,CAaA,MAAMC,EAAeC,EAAM,WAA2C,CAAC,CACrE,KAAAC,EAAO,KACP,MAAAC,EACA,OAAAC,EACA,SAAAC,EAAW,GACX,OAAAC,EAAS,GACT,WAAAC,EAAa,GACb,UAAAC,EACA,MAAAC,EACA,GAAGC,CACL,EAAGC,IAECC,EAAAA,IAAC,OAAA,CACC,IAAAD,EACA,cAAaJ,EACb,KAAK,eACL,UAAWM,EAAAA,GACT,eACA,iBAAiBX,CAAI,GACrBG,GAAY,yBACZC,GAAU,uBACVE,CAAA,EAEF,MAAO,CACL,MAAOV,EAAWK,CAAK,EACvB,OAAQL,EAAWM,CAAM,EACzB,GAAGK,CAAA,EAEJ,GAAGC,CAAA,CAAA,CAGT,EACDV,EAAa,YAAc,WAW3B,SAASc,EAAK,CAAE,MAAAX,EAAQ,OAAQ,KAAAD,EAAO,KAAM,UAAAM,EAAW,GAAGE,GAA4B,CACrF,aAAQV,EAAA,CAAa,MAAAG,EAAc,KAAAD,EAAY,UAAAM,EAAuB,GAAGE,EAAO,CAClF,CAOA,SAASK,EAAU,CAAE,MAAAC,EAAQ,EAAG,KAAAd,EAAO,KAAM,UAAAM,EAAW,GAAGE,GAAiC,CAC1F,OACEE,EAAAA,IAAC,MAAA,CACC,cAAY,OACZ,UAAWC,EAAAA,GAAG,yBAA0BL,CAAS,EACjD,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,KAAA,EACvD,GAAGE,EAEH,SAAA,MAAM,KAAK,CAAE,OAAQM,EAAO,EAAE,IAAI,CAACC,EAAGC,IACrCN,EAAAA,IAACZ,EAAA,CAEC,MAAOkB,IAAMF,EAAQ,EAAI,MAAQ,OACjC,KAAAd,CAAA,EAFKgB,CAAA,CAIR,CAAA,CAAA,CAGP,CAMA,SAASC,EAAO,CAAE,KAAAjB,EAAO,GAAI,UAAAM,EAAW,GAAGE,GAA8B,CAEvE,OAAOE,EAAAA,IAACZ,GAAa,OAAM,GAAC,MAAOE,EAAM,UAAAM,EAAuB,GAAGE,EAAO,CAC5E,CAOA,SAASU,EAAO,CAAE,MAAAjB,EAAQ,IAAK,OAAAC,EAAS,GAAI,UAAAI,EAAW,GAAGE,GAA8B,CACtF,OACEE,EAAAA,IAACZ,EAAA,CACC,MAAAG,EACA,OAAAC,EACA,UAAWS,EAAAA,GAAG,sBAAuBL,CAAS,EAC9C,MAAO,CAAE,aAAc,KAAA,EACtB,GAAGE,CAAA,CAAA,CAGV,CAEA,SAASW,EAAK,CAAE,UAAAb,EAAW,MAAAC,EAAO,GAAGC,GAA+C,CAClF,OACEY,EAAAA,KAAC,MAAA,CACC,cAAY,OACZ,UAAWT,EAAAA,GAAG,oBAAqBL,CAAS,EAC5C,MAAO,CAAE,QAAS,OAAQ,OAAQ,+CAAgD,aAAc,OAAQ,GAAGC,CAAA,EAC1G,GAAGC,EAEJ,SAAA,CAAAY,EAAAA,KAAC,MAAA,CAAI,MAAO,CAAE,QAAS,OAAQ,WAAY,SAAU,IAAK,OAAQ,aAAc,MAAA,EAC9E,SAAA,CAAAV,EAAAA,IAACO,EAAA,CAAO,KAAM,EAAA,CAAI,EAClBG,EAAAA,KAAC,MAAA,CAAI,MAAO,CAAE,KAAM,EAAG,QAAS,OAAQ,cAAe,SAAU,IAAK,KAAA,EACpE,SAAA,CAAAV,EAAAA,IAACZ,EAAA,CAAa,MAAM,MAAM,KAAK,KAAK,EACpCY,EAAAA,IAACZ,EAAA,CAAa,MAAM,MAAM,KAAK,IAAA,CAAK,CAAA,CAAA,CACtC,CAAA,EACF,EACAY,EAAAA,IAACG,EAAA,CAAU,MAAO,CAAA,CAAG,CAAA,CAAA,CAAA,CAG3B,CAMO,MAAMQ,EAAW,OAAO,OAAOvB,EAAc,CAClD,KAAAc,EACA,UAAAC,EACA,OAAAI,EACA,OAAAC,EACA,KAAAC,CACF,CAAC"}
|
|
@@ -1,86 +1,109 @@
|
|
|
1
|
-
import { jsx as
|
|
1
|
+
import { jsx as n, jsxs as s } from "react/jsx-runtime";
|
|
2
|
+
import y from "react";
|
|
2
3
|
/* empty css */
|
|
3
|
-
|
|
4
|
+
import { cn as d } from "../../utils/cn/cn.js";
|
|
5
|
+
function u(e) {
|
|
4
6
|
if (e !== void 0)
|
|
5
7
|
return typeof e == "number" ? `${e}px` : e;
|
|
6
8
|
}
|
|
7
|
-
|
|
9
|
+
const i = y.forwardRef(({
|
|
8
10
|
size: e = "md",
|
|
9
|
-
width:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
width: t,
|
|
12
|
+
height: r,
|
|
13
|
+
animated: o = !0,
|
|
14
|
+
circle: l = !1,
|
|
15
|
+
ariaHidden: a = !0,
|
|
16
|
+
className: m,
|
|
17
|
+
style: f,
|
|
18
|
+
...x
|
|
19
|
+
}, h) => /* @__PURE__ */ n(
|
|
20
|
+
"span",
|
|
21
|
+
{
|
|
22
|
+
ref: h,
|
|
23
|
+
"aria-hidden": a,
|
|
24
|
+
role: "presentation",
|
|
25
|
+
className: d(
|
|
26
|
+
"nui-skeleton",
|
|
27
|
+
`nui-skeleton--${e}`,
|
|
28
|
+
o && "nui-skeleton--animated",
|
|
29
|
+
l && "nui-skeleton--circle",
|
|
30
|
+
m
|
|
31
|
+
),
|
|
32
|
+
style: {
|
|
33
|
+
width: u(t),
|
|
34
|
+
height: u(r),
|
|
35
|
+
...f
|
|
36
|
+
},
|
|
37
|
+
...x
|
|
38
|
+
}
|
|
39
|
+
));
|
|
40
|
+
i.displayName = "Skeleton";
|
|
41
|
+
function g({ width: e = "100%", size: t = "md", className: r, ...o }) {
|
|
42
|
+
return /* @__PURE__ */ n(i, { width: e, size: t, className: r, ...o });
|
|
43
|
+
}
|
|
44
|
+
function c({ lines: e = 3, size: t = "md", className: r, ...o }) {
|
|
45
|
+
return /* @__PURE__ */ n(
|
|
46
|
+
"div",
|
|
25
47
|
{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
className: d("nui-skeleton-paragraph", r),
|
|
50
|
+
style: { display: "flex", flexDirection: "column", gap: "8px" },
|
|
51
|
+
...o,
|
|
52
|
+
children: Array.from({ length: e }).map((l, a) => /* @__PURE__ */ n(
|
|
53
|
+
i,
|
|
54
|
+
{
|
|
55
|
+
width: a === e - 1 ? "75%" : "100%",
|
|
56
|
+
size: t
|
|
57
|
+
},
|
|
58
|
+
a
|
|
59
|
+
))
|
|
34
60
|
}
|
|
35
61
|
);
|
|
36
62
|
}
|
|
37
|
-
function
|
|
38
|
-
width: e
|
|
39
|
-
size: n = "md"
|
|
40
|
-
}) {
|
|
41
|
-
return /* @__PURE__ */ r(t, { width: e, size: n });
|
|
42
|
-
}
|
|
43
|
-
function d({
|
|
44
|
-
lines: e = 3,
|
|
45
|
-
size: n = "md"
|
|
46
|
-
}) {
|
|
47
|
-
const a = Array.from({ length: e });
|
|
48
|
-
return /* @__PURE__ */ r("div", { "aria-hidden": "true", children: a.map((o, i) => /* @__PURE__ */ r("div", { style: { marginBlockEnd: "8px" }, children: /* @__PURE__ */ r(t, { width: i === e - 1 ? "75%" : "100%", size: n }) }, i)) });
|
|
49
|
-
}
|
|
50
|
-
function h({ size: e = 40 }) {
|
|
51
|
-
return /* @__PURE__ */ r(t, { circle: !0, width: e, animated: !0 });
|
|
63
|
+
function p({ size: e = 40, className: t, ...r }) {
|
|
64
|
+
return /* @__PURE__ */ n(i, { circle: !0, width: e, className: t, ...r });
|
|
52
65
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}) {
|
|
57
|
-
return /* @__PURE__ */ r(
|
|
58
|
-
t,
|
|
66
|
+
function k({ width: e = 100, height: t = 40, className: r, ...o }) {
|
|
67
|
+
return /* @__PURE__ */ n(
|
|
68
|
+
i,
|
|
59
69
|
{
|
|
60
70
|
width: e,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
style: {
|
|
64
|
-
|
|
65
|
-
borderRadius: "var(--radius-md)"
|
|
66
|
-
}
|
|
71
|
+
height: t,
|
|
72
|
+
className: d("nui-skeleton-button", r),
|
|
73
|
+
style: { borderRadius: "6px" },
|
|
74
|
+
...o
|
|
67
75
|
}
|
|
68
76
|
);
|
|
69
77
|
}
|
|
70
|
-
function
|
|
71
|
-
return /* @__PURE__ */
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
function b({ className: e, style: t, ...r }) {
|
|
79
|
+
return /* @__PURE__ */ s(
|
|
80
|
+
"div",
|
|
81
|
+
{
|
|
82
|
+
"aria-hidden": "true",
|
|
83
|
+
className: d("nui-skeleton-card", e),
|
|
84
|
+
style: { padding: "16px", border: "1px solid var(--nui-border-default, #e2e8f0)", borderRadius: "12px", ...t },
|
|
85
|
+
...r,
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ s("div", { style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "16px" }, children: [
|
|
88
|
+
/* @__PURE__ */ n(p, { size: 48 }),
|
|
89
|
+
/* @__PURE__ */ s("div", { style: { flex: 1, display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
90
|
+
/* @__PURE__ */ n(i, { width: "40%", size: "md" }),
|
|
91
|
+
/* @__PURE__ */ n(i, { width: "20%", size: "sm" })
|
|
92
|
+
] })
|
|
93
|
+
] }),
|
|
94
|
+
/* @__PURE__ */ n(c, { lines: 3 })
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
);
|
|
76
98
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
99
|
+
const z = Object.assign(i, {
|
|
100
|
+
Text: g,
|
|
101
|
+
Paragraph: c,
|
|
102
|
+
Avatar: p,
|
|
103
|
+
Button: k,
|
|
104
|
+
Card: b
|
|
105
|
+
});
|
|
82
106
|
export {
|
|
83
|
-
|
|
84
|
-
t as default
|
|
107
|
+
z as Skeleton
|
|
85
108
|
};
|
|
86
109
|
//# sourceMappingURL=Skeleton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Skeleton.js","sources":["../../../src/components/skeleton/Skeleton.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"Skeleton.js","sources":["../../../src/components/skeleton/Skeleton.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils';\nimport './Skeleton.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\ntype SkeletonSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** The predefined height mapping for the skeleton */\n size?: SkeletonSize;\n /** Explicit width override (supports numbers as px, or strings like '100%') */\n width?: number | string;\n /** Explicit height override (supports numbers as px, or strings like '50px') */\n height?: number | string; \n /** Enables or disables the sweeping shimmer animation. Defaults to true. */\n animated?: boolean;\n /** Forces the skeleton into a perfect circle, ignoring the size height */\n circle?: boolean;\n /** Hides the element from screen readers. Defaults to true (recommended). */\n ariaHidden?: boolean;\n}\n\nfunction formatSize(val?: number | string): string | undefined {\n if (val === undefined) return undefined;\n return typeof val === 'number' ? `${val}px` : val;\n}\n\n/* ============================================================\n * 1. Root Component\n * ============================================================ */\n\n/**\n * Skeleton Component (Root)\n * * A visual placeholder used during asynchronous data fetching.\n * * WAI-ARIA Note: Skeletons are strictly visual and should remain hidden from \n * screen readers (`aria-hidden=\"true\"`) to prevent them from reading out \n * dozens of \"presentation\" or \"empty\" blocks while data loads.\n */\nconst SkeletonRoot = React.forwardRef<HTMLSpanElement, SkeletonProps>(({\n size = 'md',\n width,\n height,\n animated = true,\n circle = false,\n ariaHidden = true,\n className,\n style,\n ...props\n}, ref) => {\n return (\n <span\n ref={ref}\n aria-hidden={ariaHidden}\n role=\"presentation\"\n className={cn(\n 'nui-skeleton',\n `nui-skeleton--${size}`,\n animated && 'nui-skeleton--animated',\n circle && 'nui-skeleton--circle',\n className\n )}\n style={{\n width: formatSize(width),\n height: formatSize(height),\n ...style,\n }}\n {...props}\n />\n );\n});\nSkeletonRoot.displayName = 'Skeleton';\n\n/* ============================================================\n * Helper Components\n * ============================================================ */\n\nexport interface SkeletonTextProps extends React.HTMLAttributes<HTMLSpanElement> {\n width?: number | string;\n size?: SkeletonSize;\n}\n\nfunction Text({ width = '100%', size = 'md', className, ...props }: SkeletonTextProps) {\n return <SkeletonRoot width={width} size={size} className={className} {...props} />;\n}\n\nexport interface SkeletonParagraphProps extends React.HTMLAttributes<HTMLDivElement> {\n lines?: number;\n size?: SkeletonSize;\n}\n\nfunction Paragraph({ lines = 3, size = 'md', className, ...props }: SkeletonParagraphProps) {\n return (\n <div \n aria-hidden=\"true\" \n className={cn(\"nui-skeleton-paragraph\", className)} \n style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}\n {...props}\n >\n {Array.from({ length: lines }).map((_, i) => (\n <SkeletonRoot \n key={i} \n width={i === lines - 1 ? '75%' : '100%'} \n size={size} \n />\n ))}\n </div>\n );\n}\n\nexport interface SkeletonAvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n size?: number | string;\n}\n\nfunction Avatar({ size = 40, className, ...props }: SkeletonAvatarProps) {\n // width sets the size, the CSS aspect-ratio: 1/1 guarantees it stays a perfect circle!\n return <SkeletonRoot circle width={size} className={className} {...props} />;\n}\n\nexport interface SkeletonButtonProps extends React.HTMLAttributes<HTMLSpanElement> {\n width?: number | string;\n height?: number | string;\n}\n\nfunction Button({ width = 100, height = 40, className, ...props }: SkeletonButtonProps) {\n return (\n <SkeletonRoot\n width={width}\n height={height}\n className={cn(\"nui-skeleton-button\", className)}\n style={{ borderRadius: '6px' }}\n {...props}\n />\n );\n}\n\nfunction Card({ className, style, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div \n aria-hidden=\"true\" \n className={cn(\"nui-skeleton-card\", className)} \n style={{ padding: '16px', border: '1px solid var(--nui-border-default, #e2e8f0)', borderRadius: '12px', ...style }}\n {...props}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '16px' }}>\n <Avatar size={48} />\n <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <SkeletonRoot width=\"40%\" size=\"md\" />\n <SkeletonRoot width=\"20%\" size=\"sm\" />\n </div>\n </div>\n <Paragraph lines={3} />\n </div>\n );\n}\n\n/* ============================================================\n * Export\n * ============================================================ */\n\nexport const Skeleton = Object.assign(SkeletonRoot, {\n Text,\n Paragraph,\n Avatar,\n Button,\n Card,\n});"],"names":["formatSize","val","SkeletonRoot","React","size","width","height","animated","circle","ariaHidden","className","style","props","ref","jsx","cn","Text","Paragraph","lines","_","i","Avatar","Button","Card","jsxs","Skeleton"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),i=require("react");;/* empty css */const N=require("../../utils/cn/cn.cjs");function V({min:n=0,max:s=100,step:a=1,value:v,defaultValue:L,onChange:f,disabled:c=!1,className:D,...R}){const d=v!==void 0,[j,x]=i.useState(L??n),r=Math.min(s,Math.max(n,d?v:j)),h=i.useRef(null),k=i.useRef(null),[g,m]=i.useState(!1),u=i.useCallback(e=>{const t=Math.min(s,Math.max(n,e));let o=n+Math.round((t-n)/a)*a;o=Number(o.toFixed(5)),d||x(o),f?.(o)},[d,s,n,a,f]),w=i.useCallback(e=>{const t=h.current;if(!t)return r;const o=t.getBoundingClientRect(),y=Math.max(0,Math.min(e-o.left,o.width))/o.width;return n+y*(s-n)},[n,s,r]),b=e=>"touches"in e?e.touches[0].clientX:e.clientX,E=e=>{c||(k.current?.focus(),m(!0),u(w(b(e))))};i.useEffect(()=>{if(!g||c)return;const e=o=>{u(w(b(o)))},t=()=>{m(!1)};return window.addEventListener("mousemove",e),window.addEventListener("touchmove",e,{passive:!1}),window.addEventListener("mouseup",t),window.addEventListener("touchend",t),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("touchmove",e),window.removeEventListener("mouseup",t),window.removeEventListener("touchend",t)}},[g,c,w,u]);const S=i.useCallback(e=>{if(c)return;let t=r;switch(e.key){case"ArrowRight":case"ArrowUp":t=r+a;break;case"ArrowLeft":case"ArrowDown":t=r-a;break;case"PageUp":t=r+a*10;break;case"PageDown":t=r-a*10;break;case"Home":t=n;break;case"End":t=s;break;default:return}e.preventDefault(),u(t)},[c,r,a,n,s,u]),M=(r-n)/(s-n)*100;return l.jsx("div",{className:N.cn("nui-slider-root",c&&"nui-slider--disabled",D),onMouseDown:E,onTouchStart:E,...R,children:l.jsx("div",{className:"nui-slider-track-container",children:l.jsxs("div",{ref:h,className:"nui-slider-track",children:[l.jsx("div",{className:"nui-slider-fill",style:{width:`${M}%`}}),l.jsx("div",{ref:k,className:"nui-slider-thumb",role:"slider",tabIndex:c?-1:0,"aria-valuemin":n,"aria-valuemax":s,"aria-valuenow":r,"aria-disabled":c||void 0,onKeyDown:S,style:{left:`${M}%`}})]})})})}exports.Slider=V;
|
|
2
2
|
//# sourceMappingURL=Slider.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.cjs","sources":["../../../src/components/slider/Slider.tsx"],"sourcesContent":["/**\r\n * Slider.tsx\r\n * -----------\r\n * Fully accessible single-thumb slider.\r\n * WAI-ARIA compliant, supports pointer, touch, keyboard.\r\n */\r\n\r\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\r\nimport './Slider.css';\r\n\r\ninterface SliderProps {\r\n min?: number;\r\n max?: number;\r\n step?: number;\r\n value?: number;\r\n defaultValue?: number;\r\n onChange?: (value: number) => void;\r\n disabled?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function Slider({\r\n min = 0,\r\n max = 100,\r\n step = 1,\r\n value,\r\n defaultValue,\r\n onChange,\r\n disabled = false,\r\n className = '',\r\n}: SliderProps) {\r\n const isControlled = value !== undefined;\r\n\r\n const [internalValue, setInternalValue] = useState(defaultValue ?? min);\r\n\r\n const val = isControlled ? value : internalValue;\r\n\r\n /** Safe setter */\r\n const setVal = useCallback(\r\n (v: number) => {\r\n const clamped = Math.min(max, Math.max(min, v));\r\n const stepped = Math.round(clamped / step) * step;\r\n\r\n if (!isControlled) setInternalValue(stepped);\r\n onChange?.(stepped);\r\n },\r\n [isControlled, max, min, step, onChange]\r\n );\r\n\r\n const trackRef = useRef<HTMLDivElement | null>(null);\r\n\r\n /** Calculate percentage for UI */\r\n const percent = ((val - min) / (max - min)) * 100;\r\n\r\n /** Pixel → value conversion (FIXED: wrapped in useCallback) */\r\n const pixelToValue = useCallback(\r\n (clientX: number) => {\r\n const track = trackRef.current;\r\n if (!track) return val;\r\n\r\n const rect = track.getBoundingClientRect();\r\n const x = clientX - rect.left;\r\n const ratio = x / rect.width;\r\n const rawValue = min + ratio * (max - min);\r\n return rawValue;\r\n },\r\n [min, max, val]\r\n );\r\n\r\n /** Dragging state */\r\n const [dragging, setDragging] = useState(false);\r\n\r\n const startDrag = useCallback(\r\n (e: React.MouseEvent | React.TouchEvent) => {\r\n if (disabled) return;\r\n setDragging(true);\r\n\r\n const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;\r\n\r\n setVal(pixelToValue(clientX));\r\n },\r\n [disabled, pixelToValue, setVal]\r\n );\r\n\r\n const onMove = useCallback(\r\n (e: MouseEvent | TouchEvent) => {\r\n if (!dragging || disabled) return;\r\n\r\n const clientX =\r\n (e as TouchEvent).touches?.[0]?.clientX ?? (e as MouseEvent).clientX;\r\n\r\n setVal(pixelToValue(clientX));\r\n },\r\n [dragging, disabled, pixelToValue, setVal]\r\n );\r\n\r\n const endDrag = useCallback(() => {\r\n setDragging(false);\r\n }, []);\r\n\r\n /** Global listeners while dragging */\r\n useEffect(() => {\r\n if (!dragging) return;\r\n\r\n window.addEventListener('mousemove', onMove);\r\n window.addEventListener('touchmove', onMove);\r\n window.addEventListener('mouseup', endDrag);\r\n window.addEventListener('touchend', endDrag);\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', onMove);\r\n window.removeEventListener('touchmove', onMove);\r\n window.removeEventListener('mouseup', endDrag);\r\n window.removeEventListener('touchend', endDrag);\r\n };\r\n }, [dragging, onMove, endDrag]);\r\n\r\n /** Keyboard handling */\r\n const onKeyDown = useCallback(\r\n (e: React.KeyboardEvent) => {\r\n if (disabled) return;\r\n\r\n let next = val;\r\n\r\n switch (e.key) {\r\n case 'ArrowRight':\r\n case 'ArrowUp':\r\n next = val + step;\r\n break;\r\n case 'ArrowLeft':\r\n case 'ArrowDown':\r\n next = val - step;\r\n break;\r\n case 'PageUp':\r\n next = val + step * 10;\r\n break;\r\n case 'PageDown':\r\n next = val - step * 10;\r\n break;\r\n case 'Home':\r\n next = min;\r\n break;\r\n case 'End':\r\n next = max;\r\n break;\r\n default:\r\n return;\r\n }\r\n\r\n e.preventDefault();\r\n setVal(next);\r\n },\r\n [disabled, val, step, min, max, setVal]\r\n );\r\n\r\n return (\r\n <div className={`ui-slider ${disabled ? 'disabled' : ''} ${className}`}>\r\n <div\r\n ref={trackRef}\r\n className=\"ui-slider-track\"\r\n onMouseDown={startDrag}\r\n onTouchStart={startDrag}\r\n >\r\n <div className=\"ui-slider-fill\" style={{ width: `${percent}%` }} />\r\n\r\n <div\r\n className=\"ui-slider-thumb\"\r\n role=\"slider\"\r\n tabIndex={disabled ? -1 : 0}\r\n aria-valuemin={min}\r\n aria-valuemax={max}\r\n aria-valuenow={val}\r\n aria-disabled={disabled || undefined}\r\n onKeyDown={onKeyDown}\r\n onMouseDown={startDrag}\r\n onTouchStart={startDrag}\r\n style={{ left: `${percent}%` }}\r\n />\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["Slider","min","max","step","value","defaultValue","onChange","disabled","className","isControlled","internalValue","setInternalValue","useState","val","setVal","useCallback","v","clamped","stepped","trackRef","useRef","percent","pixelToValue","clientX","track","rect","ratio","dragging","setDragging","startDrag","e","onMove","endDrag","useEffect","onKeyDown","next","jsx","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Slider.cjs","sources":["../../../src/components/slider/Slider.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { cn } from '../../utils';\nimport './Slider.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport interface SliderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {\n /** The minimum allowed value. Defaults to 0. */\n min?: number;\n /** The maximum allowed value. Defaults to 100. */\n max?: number;\n /** The interval between valid values. Defaults to 1. */\n step?: number;\n /** The controlled value of the slider. */\n value?: number;\n /** The initial uncontrolled value of the slider. */\n defaultValue?: number;\n /** Callback fired when the value changes. */\n onChange?: (value: number) => void;\n /** Disables the slider and prevents interaction. */\n disabled?: boolean;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * Slider Component\n * * A WAI-ARIA compliant input that allows users to select a value from a given range.\n * * Automatically handles global window pointer events for smooth dragging outside the hit area.\n */\nexport function Slider({\n min = 0,\n max = 100,\n step = 1,\n value,\n defaultValue,\n onChange,\n disabled = false,\n className,\n ...props // <-- Capture the rest of the HTML attributes (like style, id, etc.)\n}: SliderProps) {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue ?? min);\n \n // Safely clamp the initial/current value to prevent out-of-bounds rendering\n const rawVal = isControlled ? value : internalValue;\n const val = Math.min(max, Math.max(min, rawVal as number));\n\n const trackRef = useRef<HTMLDivElement | null>(null);\n const thumbRef = useRef<HTMLDivElement | null>(null);\n const [isDragging, setIsDragging] = useState(false);\n\n /* ----------------------------------------------------\n Value Management\n ---------------------------------------------------- */\n const setVal = useCallback(\n (v: number) => {\n const clamped = Math.min(max, Math.max(min, v));\n // Ensures the stepped value correctly aligns with the minimum bound\n let stepped = min + Math.round((clamped - min) / step) * step;\n \n // Fixes JavaScript floating point math errors (e.g., 0.3000000000004)\n stepped = Number(stepped.toFixed(5));\n\n if (!isControlled) setInternalValue(stepped);\n onChange?.(stepped);\n },\n [isControlled, max, min, step, onChange]\n );\n\n const calculateValueFromPointer = useCallback(\n (clientX: number) => {\n const track = trackRef.current;\n if (!track) return val;\n\n const rect = track.getBoundingClientRect();\n const x = Math.max(0, Math.min(clientX - rect.left, rect.width));\n const ratio = x / rect.width;\n \n return min + ratio * (max - min);\n },\n [min, max, val]\n );\n\n /* ----------------------------------------------------\n Drag State Management\n ---------------------------------------------------- */\n const getClientX = (e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent) => {\n return 'touches' in e ? e.touches[0].clientX : (e as MouseEvent | React.MouseEvent).clientX;\n };\n\n const handlePointerDown = (e: React.MouseEvent | React.TouchEvent) => {\n if (disabled) return;\n \n // Instantly focus the thumb so Arrow Keys work immediately!\n thumbRef.current?.focus(); \n \n setIsDragging(true);\n setVal(calculateValueFromPointer(getClientX(e)));\n };\n\n // Syncs global drag listeners without memory leaks\n useEffect(() => {\n if (!isDragging || disabled) return;\n\n const handleMove = (e: MouseEvent | TouchEvent) => {\n setVal(calculateValueFromPointer(getClientX(e)));\n };\n\n const handleUp = () => {\n setIsDragging(false);\n };\n\n window.addEventListener('mousemove', handleMove);\n window.addEventListener('touchmove', handleMove, { passive: false });\n window.addEventListener('mouseup', handleUp);\n window.addEventListener('touchend', handleUp);\n\n return () => {\n window.removeEventListener('mousemove', handleMove);\n window.removeEventListener('touchmove', handleMove);\n window.removeEventListener('mouseup', handleUp);\n window.removeEventListener('touchend', handleUp);\n };\n }, [isDragging, disabled, calculateValueFromPointer, setVal]);\n\n /* ----------------------------------------------------\n Keyboard Navigation (WAI-ARIA)\n ---------------------------------------------------- */\n const onKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n\n let next = val;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = val + step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = val - step;\n break;\n case 'PageUp':\n next = val + step * 10;\n break;\n case 'PageDown':\n next = val - step * 10;\n break;\n case 'Home':\n next = min;\n break;\n case 'End':\n next = max;\n break;\n default:\n return; // Exit if it's not a recognized key\n }\n\n e.preventDefault(); // Prevent page scrolling ONLY when using valid arrow keys\n setVal(next);\n },\n [disabled, val, step, min, max, setVal]\n );\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n const percent = ((val - min) / (max - min)) * 100;\n\n return (\n <div \n className={cn(\n \"nui-slider-root\", \n disabled && \"nui-slider--disabled\",\n className\n )}\n onMouseDown={handlePointerDown}\n onTouchStart={handlePointerDown}\n {...props} // <-- Spread the rest of the props (including style) to the root element\n >\n <div className=\"nui-slider-track-container\">\n <div ref={trackRef} className=\"nui-slider-track\">\n \n <div \n className=\"nui-slider-fill\" \n style={{ width: `${percent}%` }} \n />\n\n <div\n ref={thumbRef}\n className=\"nui-slider-thumb\"\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={val}\n aria-disabled={disabled || undefined}\n onKeyDown={onKeyDown}\n style={{ left: `${percent}%` }}\n />\n </div>\n </div>\n </div>\n );\n}"],"names":["Slider","min","max","step","value","defaultValue","onChange","disabled","className","props","isControlled","internalValue","setInternalValue","useState","val","trackRef","useRef","thumbRef","isDragging","setIsDragging","setVal","useCallback","v","clamped","stepped","calculateValueFromPointer","clientX","track","rect","ratio","getClientX","handlePointerDown","useEffect","handleMove","e","handleUp","onKeyDown","next","percent","jsx","cn"],"mappings":"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"}
|