@nofinite/nui 1.0.0 → 1.0.2
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/components/accordion/Accordion.cjs +2 -0
- package/dist/components/accordion/Accordion.cjs.map +1 -0
- package/dist/components/accordion/Accordion.js +51 -0
- package/dist/components/accordion/Accordion.js.map +1 -0
- package/dist/components/alert/Alert.cjs +2 -0
- package/dist/components/alert/Alert.cjs.map +1 -0
- package/dist/components/alert/Alert.js +32 -0
- package/dist/components/alert/Alert.js.map +1 -0
- package/dist/components/avatar/Avatar.cjs +2 -0
- package/dist/components/avatar/Avatar.cjs.map +1 -0
- package/dist/components/avatar/Avatar.js +51 -0
- package/dist/components/avatar/Avatar.js.map +1 -0
- package/dist/components/avatar/AvatarGroup.cjs +2 -0
- package/dist/components/avatar/AvatarGroup.cjs.map +1 -0
- package/dist/components/avatar/AvatarGroup.js +32 -0
- package/dist/components/avatar/AvatarGroup.js.map +1 -0
- package/dist/components/badge/Badge.cjs +2 -0
- package/dist/components/badge/Badge.cjs.map +1 -0
- package/dist/components/badge/Badge.js +81 -0
- package/dist/components/badge/Badge.js.map +1 -0
- package/dist/components/badge/BadgeGroup.cjs +2 -0
- package/dist/components/badge/BadgeGroup.cjs.map +1 -0
- package/dist/components/badge/BadgeGroup.js +17 -0
- package/dist/components/badge/BadgeGroup.js.map +1 -0
- package/dist/components/breadcrumbs/Breadcrumbs.cjs +2 -0
- package/dist/components/breadcrumbs/Breadcrumbs.cjs.map +1 -0
- package/dist/components/breadcrumbs/Breadcrumbs.js +46 -0
- package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -0
- package/dist/components/button/Button.cjs +2 -0
- package/dist/components/button/Button.cjs.map +1 -0
- package/dist/components/button/Button.js +21 -0
- package/dist/components/button/Button.js.map +1 -0
- package/dist/components/card/Card.cjs +2 -0
- package/dist/components/card/Card.cjs.map +1 -0
- package/dist/components/card/Card.js +50 -0
- package/dist/components/card/Card.js.map +1 -0
- package/dist/components/checkbox/Checkbox.cjs +2 -0
- package/dist/components/checkbox/Checkbox.cjs.map +1 -0
- package/dist/components/checkbox/Checkbox.js +46 -0
- package/dist/components/checkbox/Checkbox.js.map +1 -0
- package/dist/components/chip/Chip.cjs +2 -0
- package/dist/components/chip/Chip.cjs.map +1 -0
- package/dist/components/chip/Chip.js +51 -0
- package/dist/components/chip/Chip.js.map +1 -0
- package/dist/components/combobox/Combobox.cjs +2 -0
- package/dist/components/combobox/Combobox.cjs.map +1 -0
- package/dist/components/combobox/Combobox.js +114 -0
- package/dist/components/combobox/Combobox.js.map +1 -0
- package/dist/components/commandpalette/CommandPalette.cjs +2 -0
- package/dist/components/commandpalette/CommandPalette.cjs.map +1 -0
- package/dist/components/commandpalette/CommandPalette.js +111 -0
- package/dist/components/commandpalette/CommandPalette.js.map +1 -0
- package/dist/components/contextmenu/ContextMenu.cjs +2 -0
- package/dist/components/contextmenu/ContextMenu.cjs.map +1 -0
- package/dist/components/contextmenu/ContextMenu.js +104 -0
- package/dist/components/contextmenu/ContextMenu.js.map +1 -0
- package/dist/components/datagrid/DataGrid.cjs +2 -0
- package/dist/components/datagrid/DataGrid.cjs.map +1 -0
- package/dist/components/datagrid/DataGrid.js +227 -0
- package/dist/components/datagrid/DataGrid.js.map +1 -0
- package/dist/components/datepicker/DatePicker.cjs +2 -0
- package/dist/components/datepicker/DatePicker.cjs.map +1 -0
- package/dist/components/datepicker/DatePicker.js +265 -0
- package/dist/components/datepicker/DatePicker.js.map +1 -0
- package/dist/components/daterangepicker/DateRangePicker.cjs +2 -0
- package/dist/components/daterangepicker/DateRangePicker.cjs.map +1 -0
- package/dist/components/daterangepicker/DateRangePicker.js +322 -0
- package/dist/components/daterangepicker/DateRangePicker.js.map +1 -0
- package/dist/components/drawer/Drawer.cjs +2 -0
- package/dist/components/drawer/Drawer.cjs.map +1 -0
- package/dist/components/drawer/Drawer.js +57 -0
- package/dist/components/drawer/Drawer.js.map +1 -0
- package/dist/components/dropdown/Dropdown.cjs +2 -0
- package/dist/components/dropdown/Dropdown.cjs.map +1 -0
- package/dist/components/dropdown/Dropdown.js +115 -0
- package/dist/components/dropdown/Dropdown.js.map +1 -0
- package/dist/components/fileuploader/FileUploader.cjs +2 -0
- package/dist/components/fileuploader/FileUploader.cjs.map +1 -0
- package/dist/components/fileuploader/FileUploader.js +83 -0
- package/dist/components/fileuploader/FileUploader.js.map +1 -0
- package/dist/components/hovercard/HoverCard.cjs +2 -0
- package/dist/components/hovercard/HoverCard.cjs.map +1 -0
- package/dist/components/hovercard/HoverCard.js +78 -0
- package/dist/components/hovercard/HoverCard.js.map +1 -0
- package/dist/components/input/Input.cjs +2 -0
- package/dist/components/input/Input.cjs.map +1 -0
- package/dist/components/input/Input.js +41 -0
- package/dist/components/input/Input.js.map +1 -0
- package/dist/components/layout/Container.cjs +2 -0
- package/dist/components/layout/Container.cjs.map +1 -0
- package/dist/components/layout/Container.js +33 -0
- package/dist/components/layout/Container.js.map +1 -0
- package/dist/components/layout/Flex.cjs +2 -0
- package/dist/components/layout/Flex.cjs.map +1 -0
- package/dist/components/layout/Flex.js +26 -0
- package/dist/components/layout/Flex.js.map +1 -0
- package/dist/components/layout/Grid.cjs +2 -0
- package/dist/components/layout/Grid.cjs.map +1 -0
- package/dist/components/layout/Grid.js +21 -0
- package/dist/components/layout/Grid.js.map +1 -0
- package/dist/components/layout/HStack.cjs +2 -0
- package/dist/components/layout/HStack.cjs.map +1 -0
- package/dist/components/layout/HStack.js +9 -0
- package/dist/components/layout/HStack.js.map +1 -0
- package/dist/components/layout/Stack.cjs +2 -0
- package/dist/components/layout/Stack.cjs.map +1 -0
- package/dist/components/layout/Stack.js +9 -0
- package/dist/components/layout/Stack.js.map +1 -0
- package/dist/components/megamenu/MegaMenu.cjs +2 -0
- package/dist/components/megamenu/MegaMenu.cjs.map +1 -0
- package/dist/components/megamenu/MegaMenu.js +43 -0
- package/dist/components/megamenu/MegaMenu.js.map +1 -0
- package/dist/components/modal/Modal.cjs +2 -0
- package/dist/components/modal/Modal.cjs.map +1 -0
- package/dist/components/modal/Modal.js +91 -0
- package/dist/components/modal/Modal.js.map +1 -0
- package/dist/components/pagination/Pagination.cjs +2 -0
- package/dist/components/pagination/Pagination.cjs.map +1 -0
- package/dist/components/pagination/Pagination.js +62 -0
- package/dist/components/pagination/Pagination.js.map +1 -0
- package/dist/components/popover/Popover.cjs +2 -0
- package/dist/components/popover/Popover.cjs.map +1 -0
- package/dist/components/popover/Popover.js +123 -0
- package/dist/components/popover/Popover.js.map +1 -0
- package/dist/components/progress/Progress.cjs +2 -0
- package/dist/components/progress/Progress.cjs.map +1 -0
- package/dist/components/progress/Progress.js +33 -0
- package/dist/components/progress/Progress.js.map +1 -0
- package/dist/components/radiogroup/RadioGroup.cjs +2 -0
- package/dist/components/radiogroup/RadioGroup.cjs.map +1 -0
- package/dist/components/radiogroup/RadioGroup.js +79 -0
- package/dist/components/radiogroup/RadioGroup.js.map +1 -0
- package/dist/components/rating/Rating.cjs +2 -0
- package/dist/components/rating/Rating.cjs.map +1 -0
- package/dist/components/rating/Rating.js +49 -0
- package/dist/components/rating/Rating.js.map +1 -0
- package/dist/components/skeleton/Skeleton.cjs +2 -0
- package/dist/components/skeleton/Skeleton.cjs.map +1 -0
- package/dist/components/skeleton/Skeleton.js +86 -0
- package/dist/components/skeleton/Skeleton.js.map +1 -0
- package/dist/components/slider/Slider.cjs +2 -0
- package/dist/components/slider/Slider.cjs.map +1 -0
- package/dist/components/slider/Slider.js +116 -0
- package/dist/components/slider/Slider.js.map +1 -0
- package/dist/components/spinner/Spinner.cjs +2 -0
- package/dist/components/spinner/Spinner.cjs.map +1 -0
- package/dist/components/spinner/Spinner.js +21 -0
- package/dist/components/spinner/Spinner.js.map +1 -0
- package/dist/components/stepper/Stepper.cjs +6 -0
- package/dist/components/stepper/Stepper.cjs.map +1 -0
- package/dist/components/stepper/Stepper.js +43 -0
- package/dist/components/stepper/Stepper.js.map +1 -0
- package/dist/components/switch/Switch.cjs +2 -0
- package/dist/components/switch/Switch.cjs.map +1 -0
- package/dist/components/switch/Switch.js +67 -0
- package/dist/components/switch/Switch.js.map +1 -0
- package/dist/components/table/Table.cjs +2 -0
- package/dist/components/table/Table.cjs.map +1 -0
- package/dist/components/table/Table.js +46 -0
- package/dist/components/table/Table.js.map +1 -0
- package/dist/components/tabs/Tabs.cjs +2 -0
- package/dist/components/tabs/Tabs.cjs.map +1 -0
- package/dist/components/tabs/Tabs.js +56 -0
- package/dist/components/tabs/Tabs.js.map +1 -0
- package/dist/components/textarea/Textarea.cjs +2 -0
- package/dist/components/textarea/Textarea.cjs.map +1 -0
- package/dist/components/textarea/Textarea.js +75 -0
- package/dist/components/textarea/Textarea.js.map +1 -0
- package/dist/components/toast/Toast.cjs +2 -0
- package/dist/components/toast/Toast.cjs.map +1 -0
- package/dist/components/toast/Toast.js +52 -0
- package/dist/components/toast/Toast.js.map +1 -0
- package/dist/components/tooltip/Tooltip.cjs +2 -0
- package/dist/components/tooltip/Tooltip.cjs.map +1 -0
- package/dist/components/tooltip/Tooltip.js +73 -0
- package/dist/components/tooltip/Tooltip.js.map +1 -0
- package/dist/components/treeview/TreeView.cjs +2 -0
- package/dist/components/treeview/TreeView.cjs.map +1 -0
- package/dist/components/treeview/TreeView.js +98 -0
- package/dist/components/treeview/TreeView.js.map +1 -0
- package/dist/components/virtuallist/VirtualList.cjs +2 -0
- package/dist/components/virtuallist/VirtualList.cjs.map +1 -0
- package/dist/components/virtuallist/VirtualList.js +58 -0
- package/dist/components/virtuallist/VirtualList.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/styles/index.css +1 -0
- package/dist/theme/NUIProvider.cjs +2 -0
- package/dist/theme/NUIProvider.cjs.map +1 -0
- package/dist/theme/NUIProvider.js +34 -0
- package/dist/theme/NUIProvider.js.map +1 -0
- package/dist/theme/useTheme.cjs +2 -0
- package/dist/theme/useTheme.cjs.map +1 -0
- package/dist/theme/useTheme.js +9 -0
- package/dist/theme/useTheme.js.map +1 -0
- package/dist/types/components/accordion/Accordion.d.ts +18 -0
- package/dist/types/components/accordion/Accordion.d.ts.map +1 -0
- package/dist/types/components/alert/Alert.d.ts +13 -0
- package/dist/types/components/alert/Alert.d.ts.map +1 -0
- package/dist/types/components/avatar/Avatar.d.ts +18 -0
- package/dist/types/components/avatar/Avatar.d.ts.map +1 -0
- package/dist/types/components/avatar/AvatarGroup.d.ts +10 -0
- package/dist/types/components/avatar/AvatarGroup.d.ts.map +1 -0
- package/dist/types/components/badge/Badge.d.ts +22 -0
- package/dist/types/components/badge/Badge.d.ts.map +1 -0
- package/dist/types/components/badge/BadgeGroup.d.ts +9 -0
- package/dist/types/components/badge/BadgeGroup.d.ts.map +1 -0
- package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts +15 -0
- package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts.map +1 -0
- package/dist/types/components/button/Button.d.ts +15 -0
- package/dist/types/components/button/Button.d.ts.map +1 -0
- package/dist/types/components/card/Card.d.ts +27 -0
- package/dist/types/components/card/Card.d.ts.map +1 -0
- package/dist/types/components/checkbox/Checkbox.d.ts +15 -0
- package/dist/types/components/checkbox/Checkbox.d.ts.map +1 -0
- package/dist/types/components/chip/Chip.d.ts +21 -0
- package/dist/types/components/chip/Chip.d.ts.map +1 -0
- package/dist/types/components/combobox/Combobox.d.ts +24 -0
- package/dist/types/components/combobox/Combobox.d.ts.map +1 -0
- package/dist/types/components/commandpalette/CommandPalette.d.ts +21 -0
- package/dist/types/components/commandpalette/CommandPalette.d.ts.map +1 -0
- package/dist/types/components/contextmenu/ContextMenu.d.ts +17 -0
- package/dist/types/components/contextmenu/ContextMenu.d.ts.map +1 -0
- package/dist/types/components/datagrid/DataGrid.d.ts +28 -0
- package/dist/types/components/datagrid/DataGrid.d.ts.map +1 -0
- package/dist/types/components/datepicker/DatePicker.d.ts +14 -0
- package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -0
- package/dist/types/components/daterangepicker/DateRangePicker.d.ts +19 -0
- package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -0
- package/dist/types/components/drawer/Drawer.d.ts +12 -0
- package/dist/types/components/drawer/Drawer.d.ts.map +1 -0
- package/dist/types/components/dropdown/Dropdown.d.ts +18 -0
- package/dist/types/components/dropdown/Dropdown.d.ts.map +1 -0
- package/dist/types/components/fileuploader/FileUploader.d.ts +9 -0
- package/dist/types/components/fileuploader/FileUploader.d.ts.map +1 -0
- package/dist/types/components/hovercard/HoverCard.d.ts +10 -0
- package/dist/types/components/hovercard/HoverCard.d.ts.map +1 -0
- package/dist/types/components/input/Input.d.ts +15 -0
- package/dist/types/components/input/Input.d.ts.map +1 -0
- package/dist/types/components/layout/Container.d.ts +8 -0
- package/dist/types/components/layout/Container.d.ts.map +1 -0
- package/dist/types/components/layout/Flex.d.ts +14 -0
- package/dist/types/components/layout/Flex.d.ts.map +1 -0
- package/dist/types/components/layout/Grid.d.ts +10 -0
- package/dist/types/components/layout/Grid.d.ts.map +1 -0
- package/dist/types/components/layout/HStack.d.ts +8 -0
- package/dist/types/components/layout/HStack.d.ts.map +1 -0
- package/dist/types/components/layout/Stack.d.ts +8 -0
- package/dist/types/components/layout/Stack.d.ts.map +1 -0
- package/dist/types/components/megamenu/MegaMenu.d.ts +12 -0
- package/dist/types/components/megamenu/MegaMenu.d.ts.map +1 -0
- package/dist/types/components/modal/Modal.d.ts +16 -0
- package/dist/types/components/modal/Modal.d.ts.map +1 -0
- package/dist/types/components/pagination/Pagination.d.ts +9 -0
- package/dist/types/components/pagination/Pagination.d.ts.map +1 -0
- package/dist/types/components/popover/Popover.d.ts +21 -0
- package/dist/types/components/popover/Popover.d.ts.map +1 -0
- package/dist/types/components/progress/Progress.d.ts +13 -0
- package/dist/types/components/progress/Progress.d.ts.map +1 -0
- package/dist/types/components/radiogroup/RadioGroup.d.ts +18 -0
- package/dist/types/components/radiogroup/RadioGroup.d.ts.map +1 -0
- package/dist/types/components/rating/Rating.d.ts +19 -0
- package/dist/types/components/rating/Rating.d.ts.map +1 -0
- package/dist/types/components/select/Select.d.ts +20 -0
- package/dist/types/components/select/Select.d.ts.map +1 -0
- package/dist/types/components/skeleton/Skeleton.d.ts +44 -0
- package/dist/types/components/skeleton/Skeleton.d.ts.map +1 -0
- package/dist/types/components/slider/Slider.d.ts +13 -0
- package/dist/types/components/slider/Slider.d.ts.map +1 -0
- package/dist/types/components/spinner/Spinner.d.ts +7 -0
- package/dist/types/components/spinner/Spinner.d.ts.map +1 -0
- package/dist/types/components/stepper/Stepper.d.ts +12 -0
- package/dist/types/components/stepper/Stepper.d.ts.map +1 -0
- package/dist/types/components/switch/Switch.d.ts +15 -0
- package/dist/types/components/switch/Switch.d.ts.map +1 -0
- package/dist/types/components/table/Table.d.ts +14 -0
- package/dist/types/components/table/Table.d.ts.map +1 -0
- package/dist/types/components/tabs/Tabs.d.ts +14 -0
- package/dist/types/components/tabs/Tabs.d.ts.map +1 -0
- package/dist/types/components/textarea/Textarea.d.ts +14 -0
- package/dist/types/components/textarea/Textarea.d.ts.map +1 -0
- package/dist/types/components/toast/Toast.d.ts +16 -0
- package/dist/types/components/toast/Toast.d.ts.map +1 -0
- package/dist/types/components/tooltip/Tooltip.d.ts +10 -0
- package/dist/types/components/tooltip/Tooltip.d.ts.map +1 -0
- package/dist/types/components/treeview/TreeView.d.ts +16 -0
- package/dist/types/components/treeview/TreeView.d.ts.map +1 -0
- package/dist/types/components/virtuallist/VirtualList.d.ts +23 -0
- package/dist/types/components/virtuallist/VirtualList.d.ts.map +1 -0
- package/dist/types/index.d.ts +50 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/theme/NUIProvider.d.ts +14 -0
- package/dist/types/theme/NUIProvider.d.ts.map +1 -0
- package/dist/types/theme/useTheme.d.ts +11 -0
- package/dist/types/theme/useTheme.d.ts.map +1 -0
- package/dist/types/utils/generateid/generateId.d.ts +2 -0
- package/dist/types/utils/generateid/generateId.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +9 -0
- package/dist/types/utils/index.d.ts.map +1 -0
- package/dist/types/utils/inertmanager/inertManager.d.ts +13 -0
- package/dist/types/utils/inertmanager/inertManager.d.ts.map +1 -0
- package/dist/types/utils/keyboardnav/keyboardNav.d.ts +11 -0
- package/dist/types/utils/keyboardnav/keyboardNav.d.ts.map +1 -0
- package/dist/types/utils/onclickoutside/onClickOutside.d.ts +3 -0
- package/dist/types/utils/onclickoutside/onClickOutside.d.ts.map +1 -0
- package/dist/types/utils/portal/portal.d.ts +4 -0
- package/dist/types/utils/portal/portal.d.ts.map +1 -0
- package/dist/types/utils/restorefocus/restoreFocus.d.ts +8 -0
- package/dist/types/utils/restorefocus/restoreFocus.d.ts.map +1 -0
- package/dist/types/utils/scrolllock/scrollLock.d.ts +11 -0
- package/dist/types/utils/scrolllock/scrollLock.d.ts.map +1 -0
- package/dist/types/utils/trapfocus/trapFocus.d.ts +8 -0
- package/dist/types/utils/trapfocus/trapFocus.d.ts.map +1 -0
- package/dist/utils/generateid/generateId.cjs +2 -0
- package/dist/utils/generateid/generateId.cjs.map +1 -0
- package/dist/utils/generateid/generateId.js +7 -0
- package/dist/utils/generateid/generateId.js.map +1 -0
- package/dist/utils/inertmanager/inertManager.cjs +2 -0
- package/dist/utils/inertmanager/inertManager.cjs.map +1 -0
- package/dist/utils/inertmanager/inertManager.js +18 -0
- package/dist/utils/inertmanager/inertManager.js.map +1 -0
- package/dist/utils/keyboardnav/keyboardNav.cjs +2 -0
- package/dist/utils/keyboardnav/keyboardNav.cjs.map +1 -0
- package/dist/utils/keyboardnav/keyboardNav.js +10 -0
- package/dist/utils/keyboardnav/keyboardNav.js.map +1 -0
- package/dist/utils/onclickoutside/onClickOutside.cjs +2 -0
- package/dist/utils/onclickoutside/onClickOutside.cjs.map +1 -0
- package/dist/utils/onclickoutside/onClickOutside.js +11 -0
- package/dist/utils/onclickoutside/onClickOutside.js.map +1 -0
- package/dist/utils/portal/portal.cjs +2 -0
- package/dist/utils/portal/portal.cjs.map +1 -0
- package/dist/utils/portal/portal.js +8 -0
- package/dist/utils/portal/portal.js.map +1 -0
- package/dist/utils/restorefocus/restoreFocus.cjs +2 -0
- package/dist/utils/restorefocus/restoreFocus.cjs.map +1 -0
- package/dist/utils/restorefocus/restoreFocus.js +7 -0
- package/dist/utils/restorefocus/restoreFocus.js.map +1 -0
- package/dist/utils/scrolllock/scrollLock.cjs +2 -0
- package/dist/utils/scrolllock/scrollLock.cjs.map +1 -0
- package/dist/utils/scrolllock/scrollLock.js +12 -0
- package/dist/utils/scrolllock/scrollLock.js.map +1 -0
- package/dist/utils/trapfocus/trapFocus.cjs +3 -0
- package/dist/utils/trapfocus/trapFocus.cjs.map +1 -0
- package/dist/utils/trapfocus/trapFocus.js +14 -0
- package/dist/utils/trapfocus/trapFocus.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as r, jsxs as d } from "react/jsx-runtime";
|
|
2
|
+
import { useState as m, useMemo as f } from "react";
|
|
3
|
+
/* empty css */
|
|
4
|
+
function N({
|
|
5
|
+
columns: a,
|
|
6
|
+
data: s,
|
|
7
|
+
emptyText: u = "No data available",
|
|
8
|
+
className: b = ""
|
|
9
|
+
}) {
|
|
10
|
+
const [n, h] = m(null), c = f(() => n ? [...s].sort((t, i) => {
|
|
11
|
+
const o = t[n.key], l = i[n.key];
|
|
12
|
+
return o < l ? n.direction === "asc" ? -1 : 1 : o > l ? n.direction === "asc" ? 1 : -1 : 0;
|
|
13
|
+
}) : s, [s, n]), y = (e) => {
|
|
14
|
+
e.sortable && h((t) => !t || t.key !== e.key ? { key: e.key, direction: "asc" } : t.direction === "asc" ? { key: e.key, direction: "desc" } : null);
|
|
15
|
+
}, k = (e) => {
|
|
16
|
+
if (!e.sortable) return null;
|
|
17
|
+
const t = n?.key === e.key, i = n?.direction ?? "asc";
|
|
18
|
+
return /* @__PURE__ */ r(
|
|
19
|
+
"span",
|
|
20
|
+
{
|
|
21
|
+
className: `ui-table-sort-indicator ${t ? "active" : ""}`,
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
children: t ? i === "asc" ? "▲" : "▼" : "↕"
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
return /* @__PURE__ */ r("div", { className: "ui-table-container", children: /* @__PURE__ */ d("table", { className: `ui-table ${b}`, children: [
|
|
28
|
+
/* @__PURE__ */ r("thead", { children: /* @__PURE__ */ r("tr", { children: a.map((e) => /* @__PURE__ */ r("th", { scope: "col", children: e.sortable ? /* @__PURE__ */ d(
|
|
29
|
+
"button",
|
|
30
|
+
{
|
|
31
|
+
type: "button",
|
|
32
|
+
className: "ui-table-sort-button",
|
|
33
|
+
onClick: () => y(e),
|
|
34
|
+
children: [
|
|
35
|
+
e.label,
|
|
36
|
+
k(e)
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
) : e.label }, String(e.key))) }) }),
|
|
40
|
+
/* @__PURE__ */ r("tbody", { children: c.length === 0 ? /* @__PURE__ */ r("tr", { children: /* @__PURE__ */ r("td", { className: "ui-table-empty", colSpan: a.length, children: u }) }) : c.map((e, t) => /* @__PURE__ */ r("tr", { className: "ui-table-row", children: a.map((i) => /* @__PURE__ */ r("td", { children: String(e[i.key]) }, String(i.key))) }, t)) })
|
|
41
|
+
] }) });
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
N as Table
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=Table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Table.js","sources":["../../../../src/components/table/Table.tsx"],"sourcesContent":["/**\r\n * Table.tsx\r\n * ----------\r\n * Accessible, sortable, theme-aware table.\r\n */\r\n\r\nimport { useState, useMemo } from 'react';\r\nimport './Table.css';\r\n\r\nexport interface TableColumn<T> {\r\n key: keyof T;\r\n label: string;\r\n sortable?: boolean;\r\n}\r\n\r\ninterface TableProps<T> {\r\n columns: TableColumn<T>[];\r\n data: T[];\r\n emptyText?: string;\r\n className?: string;\r\n}\r\n\r\ntype SortState<T> = {\r\n key: keyof T;\r\n direction: 'asc' | 'desc';\r\n} | null;\r\n\r\nexport function Table<T extends Record<string, any>>({\r\n columns,\r\n data,\r\n emptyText = 'No data available',\r\n className = '',\r\n}: TableProps<T>) {\r\n const [sort, setSort] = useState<SortState<T>>(null);\r\n\r\n const sortedData = useMemo(() => {\r\n if (!sort) return data;\r\n\r\n const sorted = [...data].sort((a, b) => {\r\n const aVal = a[sort.key];\r\n const bVal = b[sort.key];\r\n\r\n if (aVal < bVal) return sort.direction === 'asc' ? -1 : 1;\r\n if (aVal > bVal) return sort.direction === 'asc' ? 1 : -1;\r\n return 0;\r\n });\r\n\r\n return sorted;\r\n }, [data, sort]);\r\n\r\n const toggleSort = (col: TableColumn<T>) => {\r\n if (!col.sortable) return;\r\n\r\n setSort((prev) => {\r\n if (!prev || prev.key !== col.key) {\r\n return { key: col.key, direction: 'asc' };\r\n }\r\n if (prev.direction === 'asc') {\r\n return { key: col.key, direction: 'desc' };\r\n }\r\n return null; // reset\r\n });\r\n };\r\n\r\n const renderSortIcon = (col: TableColumn<T>) => {\r\n if (!col.sortable) return null;\r\n\r\n const isActive = sort?.key === col.key;\r\n const dir = sort?.direction ?? 'asc';\r\n\r\n return (\r\n <span\r\n className={`ui-table-sort-indicator ${isActive ? 'active' : ''}`}\r\n aria-hidden=\"true\"\r\n >\r\n {isActive ? (dir === 'asc' ? '▲' : '▼') : '↕'}\r\n </span>\r\n );\r\n };\r\n\r\n return (\r\n <div className=\"ui-table-container\">\r\n <table className={`ui-table ${className}`}>\r\n <thead>\r\n <tr>\r\n {columns.map((col) => (\r\n <th key={String(col.key)} scope=\"col\">\r\n {col.sortable ? (\r\n <button\r\n type=\"button\"\r\n className=\"ui-table-sort-button\"\r\n onClick={() => toggleSort(col)}\r\n >\r\n {col.label}\r\n {renderSortIcon(col)}\r\n </button>\r\n ) : (\r\n col.label\r\n )}\r\n </th>\r\n ))}\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n {sortedData.length === 0 ? (\r\n <tr>\r\n <td className=\"ui-table-empty\" colSpan={columns.length}>\r\n {emptyText}\r\n </td>\r\n </tr>\r\n ) : (\r\n sortedData.map((row, i) => (\r\n <tr key={i} className=\"ui-table-row\">\r\n {columns.map((col) => (\r\n <td key={String(col.key)}>{String(row[col.key])}</td>\r\n ))}\r\n </tr>\r\n ))\r\n )}\r\n </tbody>\r\n </table>\r\n </div>\r\n );\r\n}\r\n"],"names":["Table","columns","data","emptyText","className","sort","setSort","useState","sortedData","useMemo","a","b","aVal","bVal","toggleSort","col","prev","renderSortIcon","isActive","dir","jsx","jsxs","row","i"],"mappings":";;;AA2BO,SAASA,EAAqC;AAAA,EACnD,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,WAAAC,IAAY;AACd,GAAkB;AAChB,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAuB,IAAI,GAE7CC,IAAaC,EAAQ,MACpBJ,IAEU,CAAC,GAAGH,CAAI,EAAE,KAAK,CAACQ,GAAGC,MAAM;AACtC,UAAMC,IAAOF,EAAEL,EAAK,GAAG,GACjBQ,IAAOF,EAAEN,EAAK,GAAG;AAEvB,WAAIO,IAAOC,IAAaR,EAAK,cAAc,QAAQ,KAAK,IACpDO,IAAOC,IAAaR,EAAK,cAAc,QAAQ,IAAI,KAChD;AAAA,EACT,CAAC,IATiBH,GAYjB,CAACA,GAAMG,CAAI,CAAC,GAETS,IAAa,CAACC,MAAwB;AAC1C,IAAKA,EAAI,YAETT,EAAQ,CAACU,MACH,CAACA,KAAQA,EAAK,QAAQD,EAAI,MACrB,EAAE,KAAKA,EAAI,KAAK,WAAW,MAAA,IAEhCC,EAAK,cAAc,QACd,EAAE,KAAKD,EAAI,KAAK,WAAW,OAAA,IAE7B,IACR;AAAA,EACH,GAEME,IAAiB,CAACF,MAAwB;AAC9C,QAAI,CAACA,EAAI,SAAU,QAAO;AAE1B,UAAMG,IAAWb,GAAM,QAAQU,EAAI,KAC7BI,IAAMd,GAAM,aAAa;AAE/B,WACE,gBAAAe;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,2BAA2BF,IAAW,WAAW,EAAE;AAAA,QAC9D,eAAY;AAAA,QAEX,UAAAA,IAAYC,MAAQ,QAAQ,MAAM,MAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAGhD;AAEA,SACE,gBAAAC,EAAC,SAAI,WAAU,sBACb,4BAAC,SAAA,EAAM,WAAW,YAAYhB,CAAS,IACrC,UAAA;AAAA,IAAA,gBAAAgB,EAAC,SAAA,EACC,UAAA,gBAAAA,EAAC,MAAA,EACE,UAAAnB,EAAQ,IAAI,CAACc,MACZ,gBAAAK,EAAC,MAAA,EAAyB,OAAM,OAC7B,UAAAL,EAAI,WACH,gBAAAM;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,MAAMP,EAAWC,CAAG;AAAA,QAE5B,UAAA;AAAA,UAAAA,EAAI;AAAA,UACJE,EAAeF,CAAG;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,IAGrBA,EAAI,MAAA,GAXC,OAAOA,EAAI,GAAG,CAavB,CACD,EAAA,CACH,GACF;AAAA,IAEA,gBAAAK,EAAC,WACE,UAAAZ,EAAW,WAAW,IACrB,gBAAAY,EAAC,MAAA,EACC,4BAAC,MAAA,EAAG,WAAU,kBAAiB,SAASnB,EAAQ,QAC7C,UAAAE,EAAA,CACH,GACF,IAEAK,EAAW,IAAI,CAACc,GAAKC,MACnB,gBAAAH,EAAC,QAAW,WAAU,gBACnB,YAAQ,IAAI,CAACL,MACZ,gBAAAK,EAAC,MAAA,EAA0B,iBAAOE,EAAIP,EAAI,GAAG,CAAC,EAAA,GAArC,OAAOA,EAAI,GAAG,CAAyB,CACjD,KAHMQ,CAIT,CACD,EAAA,CAEL;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("react/jsx-runtime"),c=require("react");;/* empty css */function h({tabs:i,defaultTab:u,className:a=""}){const[t,s]=c.useState(u||i[0]?.id),o=c.useRef([]);c.useEffect(()=>{const e=i.findIndex(n=>n.id===t);o.current[e]?.focus()},[t,i]);const f=(e,n)=>{if(!["ArrowRight","ArrowLeft","Home","End"].includes(e.key))return;e.preventDefault();let r=n;e.key==="ArrowRight"&&(r=(n+1)%i.length),e.key==="ArrowLeft"&&(r=(n-1+i.length)%i.length),e.key==="Home"&&(r=0),e.key==="End"&&(r=i.length-1),s(i[r].id)};return l.jsxs("div",{className:`ui-tabs ${a}`,children:[l.jsx("div",{role:"tablist",className:"ui-tabs-list",children:i.map((e,n)=>{const r=e.id===t;return l.jsx("button",{ref:d=>{o.current[n]=d},role:"tab",id:`tab-${e.id}`,"aria-selected":r,"aria-controls":`panel-${e.id}`,tabIndex:r?0:-1,className:"ui-tab",onClick:()=>s(e.id),onKeyDown:d=>f(d,n),children:e.label},e.id)})}),i.map(e=>e.id===t?l.jsx("div",{id:`panel-${e.id}`,role:"tabpanel","aria-labelledby":`tab-${e.id}`,className:"ui-tabs-panel",children:e.content},e.id):null)]})}exports.Tabs=h;
|
|
2
|
+
//# sourceMappingURL=Tabs.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.cjs","sources":["../../../../src/components/tabs/Tabs.tsx"],"sourcesContent":["/**\r\n * Tabs.tsx\r\n * ---------\r\n * Fully accessible WAI-ARIA Tabs Component.\r\n *\r\n * Features:\r\n * - roving tabindex\r\n * - ArrowLeft, ArrowRight, Home, End keyboard navigation\r\n * - aria-selected, aria-controls, role=\"tablist\"\r\n * - auto-focus on selected tab\r\n * - single-component API\r\n */\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport './Tabs.css';\r\n\r\nexport interface TabItem {\r\n id: string;\r\n label: string;\r\n content: React.ReactNode;\r\n}\r\n\r\ninterface TabsProps {\r\n tabs: TabItem[];\r\n defaultTab?: string;\r\n className?: string;\r\n}\r\n\r\nexport function Tabs({ tabs, defaultTab, className = '' }: TabsProps) {\r\n const [active, setActive] = useState(defaultTab || tabs[0]?.id);\r\n\r\n const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);\r\n\r\n // Focus active tab\r\n useEffect(() => {\r\n const index = tabs.findIndex((t) => t.id === active);\r\n tabRefs.current[index]?.focus();\r\n }, [active, tabs]);\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\r\n if (!['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(e.key)) return;\r\n\r\n e.preventDefault();\r\n\r\n let newIndex = index;\r\n\r\n if (e.key === 'ArrowRight') newIndex = (index + 1) % tabs.length;\r\n if (e.key === 'ArrowLeft')\r\n newIndex = (index - 1 + tabs.length) % tabs.length;\r\n if (e.key === 'Home') newIndex = 0;\r\n if (e.key === 'End') newIndex = tabs.length - 1;\r\n\r\n setActive(tabs[newIndex].id);\r\n };\r\n\r\n return (\r\n <div className={`ui-tabs ${className}`}>\r\n <div role=\"tablist\" className=\"ui-tabs-list\">\r\n {tabs.map((tab, index) => {\r\n const isSelected = tab.id === active;\r\n\r\n return (\r\n <button\r\n key={tab.id}\r\n ref={(el) => {\r\n tabRefs.current[index] = el;\r\n }}\r\n role=\"tab\"\r\n id={`tab-${tab.id}`}\r\n aria-selected={isSelected}\r\n aria-controls={`panel-${tab.id}`}\r\n tabIndex={isSelected ? 0 : -1}\r\n className=\"ui-tab\"\r\n onClick={() => setActive(tab.id)}\r\n onKeyDown={(e) => handleKeyDown(e, index)}\r\n >\r\n {tab.label}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n {tabs.map((tab) =>\r\n tab.id === active ? (\r\n <div\r\n key={tab.id}\r\n id={`panel-${tab.id}`}\r\n role=\"tabpanel\"\r\n aria-labelledby={`tab-${tab.id}`}\r\n className=\"ui-tabs-panel\"\r\n >\r\n {tab.content}\r\n </div>\r\n ) : null\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["Tabs","tabs","defaultTab","className","active","setActive","useState","tabRefs","useRef","useEffect","index","t","handleKeyDown","newIndex","jsxs","jsx","tab","isSelected","el","e"],"mappings":"kKA4BO,SAASA,EAAK,CAAE,KAAAC,EAAM,WAAAC,EAAY,UAAAC,EAAY,IAAiB,CACpE,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAASJ,GAAcD,EAAK,CAAC,GAAG,EAAE,EAExDM,EAAUC,EAAAA,OAAqC,EAAE,EAGvDC,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAQT,EAAK,UAAWU,GAAMA,EAAE,KAAOP,CAAM,EACnDG,EAAQ,QAAQG,CAAK,GAAG,MAAA,CAC1B,EAAG,CAACN,EAAQH,CAAI,CAAC,EAEjB,MAAMW,EAAgB,CAAC,EAAwBF,IAAkB,CAC/D,GAAI,CAAC,CAAC,aAAc,YAAa,OAAQ,KAAK,EAAE,SAAS,EAAE,GAAG,EAAG,OAEjE,EAAE,eAAA,EAEF,IAAIG,EAAWH,EAEX,EAAE,MAAQ,eAAcG,GAAYH,EAAQ,GAAKT,EAAK,QACtD,EAAE,MAAQ,cACZY,GAAYH,EAAQ,EAAIT,EAAK,QAAUA,EAAK,QAC1C,EAAE,MAAQ,SAAQY,EAAW,GAC7B,EAAE,MAAQ,QAAOA,EAAWZ,EAAK,OAAS,GAE9CI,EAAUJ,EAAKY,CAAQ,EAAE,EAAE,CAC7B,EAEA,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAW,WAAWX,CAAS,GAClC,SAAA,CAAAY,EAAAA,IAAC,MAAA,CAAI,KAAK,UAAU,UAAU,eAC3B,SAAAd,EAAK,IAAI,CAACe,EAAKN,IAAU,CACxB,MAAMO,EAAaD,EAAI,KAAOZ,EAE9B,OACEW,EAAAA,IAAC,SAAA,CAEC,IAAMG,GAAO,CACXX,EAAQ,QAAQG,CAAK,EAAIQ,CAC3B,EACA,KAAK,MACL,GAAI,OAAOF,EAAI,EAAE,GACjB,gBAAeC,EACf,gBAAe,SAASD,EAAI,EAAE,GAC9B,SAAUC,EAAa,EAAI,GAC3B,UAAU,SACV,QAAS,IAAMZ,EAAUW,EAAI,EAAE,EAC/B,UAAYG,GAAMP,EAAcO,EAAGT,CAAK,EAEvC,SAAAM,EAAI,KAAA,EAbAA,EAAI,EAAA,CAgBf,CAAC,CAAA,CACH,EAECf,EAAK,IAAKe,GACTA,EAAI,KAAOZ,EACTW,EAAAA,IAAC,MAAA,CAEC,GAAI,SAASC,EAAI,EAAE,GACnB,KAAK,WACL,kBAAiB,OAAOA,EAAI,EAAE,GAC9B,UAAU,gBAET,SAAAA,EAAI,OAAA,EANAA,EAAI,EAAA,EAQT,IAAA,CACN,EACF,CAEJ"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsxs as u, jsx as d } from "react/jsx-runtime";
|
|
2
|
+
import { useState as m, useRef as h, useEffect as p } from "react";
|
|
3
|
+
/* empty css */
|
|
4
|
+
function k({ tabs: i, defaultTab: s, className: a = "" }) {
|
|
5
|
+
const [l, o] = m(s || i[0]?.id), c = h([]);
|
|
6
|
+
p(() => {
|
|
7
|
+
const e = i.findIndex((n) => n.id === l);
|
|
8
|
+
c.current[e]?.focus();
|
|
9
|
+
}, [l, i]);
|
|
10
|
+
const f = (e, n) => {
|
|
11
|
+
if (!["ArrowRight", "ArrowLeft", "Home", "End"].includes(e.key)) return;
|
|
12
|
+
e.preventDefault();
|
|
13
|
+
let r = n;
|
|
14
|
+
e.key === "ArrowRight" && (r = (n + 1) % i.length), e.key === "ArrowLeft" && (r = (n - 1 + i.length) % i.length), e.key === "Home" && (r = 0), e.key === "End" && (r = i.length - 1), o(i[r].id);
|
|
15
|
+
};
|
|
16
|
+
return /* @__PURE__ */ u("div", { className: `ui-tabs ${a}`, children: [
|
|
17
|
+
/* @__PURE__ */ d("div", { role: "tablist", className: "ui-tabs-list", children: i.map((e, n) => {
|
|
18
|
+
const r = e.id === l;
|
|
19
|
+
return /* @__PURE__ */ d(
|
|
20
|
+
"button",
|
|
21
|
+
{
|
|
22
|
+
ref: (t) => {
|
|
23
|
+
c.current[n] = t;
|
|
24
|
+
},
|
|
25
|
+
role: "tab",
|
|
26
|
+
id: `tab-${e.id}`,
|
|
27
|
+
"aria-selected": r,
|
|
28
|
+
"aria-controls": `panel-${e.id}`,
|
|
29
|
+
tabIndex: r ? 0 : -1,
|
|
30
|
+
className: "ui-tab",
|
|
31
|
+
onClick: () => o(e.id),
|
|
32
|
+
onKeyDown: (t) => f(t, n),
|
|
33
|
+
children: e.label
|
|
34
|
+
},
|
|
35
|
+
e.id
|
|
36
|
+
);
|
|
37
|
+
}) }),
|
|
38
|
+
i.map(
|
|
39
|
+
(e) => e.id === l ? /* @__PURE__ */ d(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
id: `panel-${e.id}`,
|
|
43
|
+
role: "tabpanel",
|
|
44
|
+
"aria-labelledby": `tab-${e.id}`,
|
|
45
|
+
className: "ui-tabs-panel",
|
|
46
|
+
children: e.content
|
|
47
|
+
},
|
|
48
|
+
e.id
|
|
49
|
+
) : null
|
|
50
|
+
)
|
|
51
|
+
] });
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
k as Tabs
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=Tabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.js","sources":["../../../../src/components/tabs/Tabs.tsx"],"sourcesContent":["/**\r\n * Tabs.tsx\r\n * ---------\r\n * Fully accessible WAI-ARIA Tabs Component.\r\n *\r\n * Features:\r\n * - roving tabindex\r\n * - ArrowLeft, ArrowRight, Home, End keyboard navigation\r\n * - aria-selected, aria-controls, role=\"tablist\"\r\n * - auto-focus on selected tab\r\n * - single-component API\r\n */\r\n\r\nimport React, { useState, useRef, useEffect } from 'react';\r\nimport './Tabs.css';\r\n\r\nexport interface TabItem {\r\n id: string;\r\n label: string;\r\n content: React.ReactNode;\r\n}\r\n\r\ninterface TabsProps {\r\n tabs: TabItem[];\r\n defaultTab?: string;\r\n className?: string;\r\n}\r\n\r\nexport function Tabs({ tabs, defaultTab, className = '' }: TabsProps) {\r\n const [active, setActive] = useState(defaultTab || tabs[0]?.id);\r\n\r\n const tabRefs = useRef<(HTMLButtonElement | null)[]>([]);\r\n\r\n // Focus active tab\r\n useEffect(() => {\r\n const index = tabs.findIndex((t) => t.id === active);\r\n tabRefs.current[index]?.focus();\r\n }, [active, tabs]);\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\r\n if (!['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(e.key)) return;\r\n\r\n e.preventDefault();\r\n\r\n let newIndex = index;\r\n\r\n if (e.key === 'ArrowRight') newIndex = (index + 1) % tabs.length;\r\n if (e.key === 'ArrowLeft')\r\n newIndex = (index - 1 + tabs.length) % tabs.length;\r\n if (e.key === 'Home') newIndex = 0;\r\n if (e.key === 'End') newIndex = tabs.length - 1;\r\n\r\n setActive(tabs[newIndex].id);\r\n };\r\n\r\n return (\r\n <div className={`ui-tabs ${className}`}>\r\n <div role=\"tablist\" className=\"ui-tabs-list\">\r\n {tabs.map((tab, index) => {\r\n const isSelected = tab.id === active;\r\n\r\n return (\r\n <button\r\n key={tab.id}\r\n ref={(el) => {\r\n tabRefs.current[index] = el;\r\n }}\r\n role=\"tab\"\r\n id={`tab-${tab.id}`}\r\n aria-selected={isSelected}\r\n aria-controls={`panel-${tab.id}`}\r\n tabIndex={isSelected ? 0 : -1}\r\n className=\"ui-tab\"\r\n onClick={() => setActive(tab.id)}\r\n onKeyDown={(e) => handleKeyDown(e, index)}\r\n >\r\n {tab.label}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n {tabs.map((tab) =>\r\n tab.id === active ? (\r\n <div\r\n key={tab.id}\r\n id={`panel-${tab.id}`}\r\n role=\"tabpanel\"\r\n aria-labelledby={`tab-${tab.id}`}\r\n className=\"ui-tabs-panel\"\r\n >\r\n {tab.content}\r\n </div>\r\n ) : null\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["Tabs","tabs","defaultTab","className","active","setActive","useState","tabRefs","useRef","useEffect","index","t","handleKeyDown","newIndex","jsxs","jsx","tab","isSelected","el","e"],"mappings":";;;AA4BO,SAASA,EAAK,EAAE,MAAAC,GAAM,YAAAC,GAAY,WAAAC,IAAY,MAAiB;AACpE,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAASJ,KAAcD,EAAK,CAAC,GAAG,EAAE,GAExDM,IAAUC,EAAqC,EAAE;AAGvD,EAAAC,EAAU,MAAM;AACd,UAAMC,IAAQT,EAAK,UAAU,CAACU,MAAMA,EAAE,OAAOP,CAAM;AACnD,IAAAG,EAAQ,QAAQG,CAAK,GAAG,MAAA;AAAA,EAC1B,GAAG,CAACN,GAAQH,CAAI,CAAC;AAEjB,QAAMW,IAAgB,CAAC,GAAwBF,MAAkB;AAC/D,QAAI,CAAC,CAAC,cAAc,aAAa,QAAQ,KAAK,EAAE,SAAS,EAAE,GAAG,EAAG;AAEjE,MAAE,eAAA;AAEF,QAAIG,IAAWH;AAEf,IAAI,EAAE,QAAQ,iBAAcG,KAAYH,IAAQ,KAAKT,EAAK,SACtD,EAAE,QAAQ,gBACZY,KAAYH,IAAQ,IAAIT,EAAK,UAAUA,EAAK,SAC1C,EAAE,QAAQ,WAAQY,IAAW,IAC7B,EAAE,QAAQ,UAAOA,IAAWZ,EAAK,SAAS,IAE9CI,EAAUJ,EAAKY,CAAQ,EAAE,EAAE;AAAA,EAC7B;AAEA,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAW,WAAWX,CAAS,IAClC,UAAA;AAAA,IAAA,gBAAAY,EAAC,OAAA,EAAI,MAAK,WAAU,WAAU,gBAC3B,UAAAd,EAAK,IAAI,CAACe,GAAKN,MAAU;AACxB,YAAMO,IAAaD,EAAI,OAAOZ;AAE9B,aACE,gBAAAW;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,KAAK,CAACG,MAAO;AACX,YAAAX,EAAQ,QAAQG,CAAK,IAAIQ;AAAA,UAC3B;AAAA,UACA,MAAK;AAAA,UACL,IAAI,OAAOF,EAAI,EAAE;AAAA,UACjB,iBAAeC;AAAA,UACf,iBAAe,SAASD,EAAI,EAAE;AAAA,UAC9B,UAAUC,IAAa,IAAI;AAAA,UAC3B,WAAU;AAAA,UACV,SAAS,MAAMZ,EAAUW,EAAI,EAAE;AAAA,UAC/B,WAAW,CAACG,MAAMP,EAAcO,GAAGT,CAAK;AAAA,UAEvC,UAAAM,EAAI;AAAA,QAAA;AAAA,QAbAA,EAAI;AAAA,MAAA;AAAA,IAgBf,CAAC,EAAA,CACH;AAAA,IAECf,EAAK;AAAA,MAAI,CAACe,MACTA,EAAI,OAAOZ,IACT,gBAAAW;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,IAAI,SAASC,EAAI,EAAE;AAAA,UACnB,MAAK;AAAA,UACL,mBAAiB,OAAOA,EAAI,EAAE;AAAA,UAC9B,WAAU;AAAA,UAET,UAAAA,EAAI;AAAA,QAAA;AAAA,QANAA,EAAI;AAAA,MAAA,IAQT;AAAA,IAAA;AAAA,EACN,GACF;AAEJ;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const c=require("react/jsx-runtime"),t=require("react");;/* empty css */function x(e){e&&(e.style.height="0px",e.style.height=`${e.scrollHeight}px`)}const l=t.forwardRef(({value:e,defaultValue:o,onChange:h,className:v="",maxLength:s,showCount:g=!1,autoGrow:i=!0,disabled:m=!1,readOnly:p=!1,required:y=!1,error:d=!1,id:b,name:T,placeholder:$,helperId:j,rows:R=3,...C},N)=>{const n=t.useRef(null);t.useImperativeHandle(N,()=>n.current??document.createElement("textarea"));const f=e!==void 0,[q,E]=t.useState(()=>o||""),u=f?e:q,r=t.useCallback(()=>{i&&x(n.current)},[i]);t.useEffect(()=>{r();const a=setTimeout(r,0);return()=>clearTimeout(a)},[r]),t.useEffect(()=>{r()},[u,r]);const H=a=>{f||E(a.target.value),h?.(a),i&&x(a.target)},S=j||void 0;return c.jsxs("div",{className:`ui-textarea-wrapper ${v}`,children:[c.jsx("textarea",{ref:n,id:b,name:T,className:`ui-textarea ${d?"ui-textarea--error":""}`,value:u,defaultValue:o,onChange:H,maxLength:s,disabled:m,readOnly:p,required:y,"aria-invalid":d||void 0,"aria-describedby":S,placeholder:$,rows:R,...C}),(g||s)&&c.jsx("div",{className:"ui-textarea-counter","aria-hidden":"true",children:`${u?.length??0}${s?` / ${s}`:""}`})]})});l.displayName="Textarea";exports.Textarea=l;exports.default=l;
|
|
2
|
+
//# sourceMappingURL=Textarea.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.cjs","sources":["../../../../src/components/textarea/Textarea.tsx"],"sourcesContent":["/**\r\n * Textarea.tsx\r\n * -------------\r\n * Advanced, accessible textarea (auto-grow).\r\n *\r\n * Features:\r\n * - auto-resize (autoGrow)\r\n * - controlled / uncontrolled modes\r\n * - maxLength + optional character counter\r\n * - disabled, readOnly, required support\r\n * - aria-describedby linking for error / help text\r\n * - identical coding style to your existing library\r\n */\r\n\r\nimport React, {\r\n useRef,\r\n useEffect,\r\n useCallback,\r\n useState,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\n\r\nimport './Textarea.css';\r\n\r\nexport interface TextareaProps\r\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\r\n /** Show character counter */\r\n showCount?: boolean;\r\n\r\n /** Enable auto resizing of height */\r\n autoGrow?: boolean;\r\n\r\n /** Visual error state */\r\n error?: boolean;\r\n\r\n /** Used for aria-describedby */\r\n helperId?: string;\r\n}\r\n\r\n/* Auto-grow helper */\r\nfunction syncHeight(el: HTMLTextAreaElement | null) {\r\n if (!el) return;\r\n el.style.height = '0px'; // reset first\r\n el.style.height = `${el.scrollHeight}px`;\r\n}\r\n\r\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\r\n (\r\n {\r\n value,\r\n defaultValue,\r\n onChange,\r\n className = '',\r\n maxLength,\r\n showCount = false,\r\n autoGrow = true,\r\n disabled = false,\r\n readOnly = false,\r\n required = false,\r\n error = false,\r\n id,\r\n name,\r\n placeholder,\r\n helperId,\r\n rows = 3,\r\n ...rest\r\n },\r\n ref\r\n ) => {\r\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\r\n\r\n useImperativeHandle(ref, () => {\r\n return innerRef.current ?? document.createElement('textarea');\r\n });\r\n\r\n const isControlled = value !== undefined;\r\n\r\n const [internalValue, setInternalValue] = useState<string>(\r\n () => (defaultValue as string) || ''\r\n );\r\n\r\n const currentValue = isControlled ? (value as string) : internalValue;\r\n\r\n /* Auto-grow on mount & updates */\r\n const resize = useCallback(() => {\r\n if (!autoGrow) return;\r\n syncHeight(innerRef.current);\r\n }, [autoGrow]);\r\n\r\n useEffect(() => {\r\n resize();\r\n const t = setTimeout(resize, 0);\r\n return () => clearTimeout(t);\r\n }, [resize]);\r\n\r\n useEffect(() => {\r\n resize();\r\n }, [currentValue, resize]);\r\n\r\n /* On change */\r\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n if (!isControlled) setInternalValue(e.target.value);\r\n onChange?.(e);\r\n\r\n if (autoGrow) syncHeight(e.target);\r\n };\r\n\r\n const describedBy = helperId || undefined;\r\n\r\n return (\r\n <div className={`ui-textarea-wrapper ${className}`}>\r\n <textarea\r\n ref={innerRef}\r\n id={id}\r\n name={name}\r\n className={`ui-textarea ${error ? 'ui-textarea--error' : ''}`}\r\n value={currentValue}\r\n defaultValue={defaultValue as string | undefined}\r\n onChange={handleChange}\r\n maxLength={maxLength}\r\n disabled={disabled}\r\n readOnly={readOnly}\r\n required={required}\r\n aria-invalid={error || undefined}\r\n aria-describedby={describedBy}\r\n placeholder={placeholder}\r\n rows={rows}\r\n {...rest}\r\n />\r\n\r\n {(showCount || maxLength) && (\r\n <div className=\"ui-textarea-counter\" aria-hidden=\"true\">\r\n {`${currentValue?.length ?? 0}${\r\n maxLength ? ` / ${maxLength}` : ''\r\n }`}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nTextarea.displayName = 'Textarea';\r\n\r\nexport default Textarea;\r\n"],"names":["syncHeight","el","Textarea","forwardRef","value","defaultValue","onChange","className","maxLength","showCount","autoGrow","disabled","readOnly","required","error","id","name","placeholder","helperId","rows","rest","ref","innerRef","useRef","useImperativeHandle","isControlled","internalValue","setInternalValue","useState","currentValue","resize","useCallback","useEffect","t","handleChange","e","describedBy","jsxs","jsx"],"mappings":"kMAyCA,SAASA,EAAWC,EAAgC,CAC7CA,IACLA,EAAG,MAAM,OAAS,MAClBA,EAAG,MAAM,OAAS,GAAGA,EAAG,YAAY,KACtC,CAEO,MAAMC,EAAWC,EAAAA,WACtB,CACE,CACE,MAAAC,EACA,aAAAC,EACA,SAAAC,EACA,UAAAC,EAAY,GACZ,UAAAC,EACA,UAAAC,EAAY,GACZ,SAAAC,EAAW,GACX,SAAAC,EAAW,GACX,SAAAC,EAAW,GACX,SAAAC,EAAW,GACX,MAAAC,EAAQ,GACR,GAAAC,EACA,KAAAC,EACA,YAAAC,EACA,SAAAC,EACA,KAAAC,EAAO,EACP,GAAGC,CAAA,EAELC,IACG,CACH,MAAMC,EAAWC,EAAAA,OAAmC,IAAI,EAExDC,EAAAA,oBAAoBH,EAAK,IAChBC,EAAS,SAAW,SAAS,cAAc,UAAU,CAC7D,EAED,MAAMG,EAAerB,IAAU,OAEzB,CAACsB,EAAeC,CAAgB,EAAIC,EAAAA,SACxC,IAAOvB,GAA2B,EAAA,EAG9BwB,EAAeJ,EAAgBrB,EAAmBsB,EAGlDI,EAASC,EAAAA,YAAY,IAAM,CAC1BrB,GACLV,EAAWsB,EAAS,OAAO,CAC7B,EAAG,CAACZ,CAAQ,CAAC,EAEbsB,EAAAA,UAAU,IAAM,CACdF,EAAA,EACA,MAAMG,EAAI,WAAWH,EAAQ,CAAC,EAC9B,MAAO,IAAM,aAAaG,CAAC,CAC7B,EAAG,CAACH,CAAM,CAAC,EAEXE,EAAAA,UAAU,IAAM,CACdF,EAAA,CACF,EAAG,CAACD,EAAcC,CAAM,CAAC,EAGzB,MAAMI,EAAgBC,GAA8C,CAC7DV,GAAcE,EAAiBQ,EAAE,OAAO,KAAK,EAClD7B,IAAW6B,CAAC,EAERzB,GAAUV,EAAWmC,EAAE,MAAM,CACnC,EAEMC,EAAclB,GAAY,OAEhC,OACEmB,EAAAA,KAAC,MAAA,CAAI,UAAW,uBAAuB9B,CAAS,GAC9C,SAAA,CAAA+B,EAAAA,IAAC,WAAA,CACC,IAAKhB,EACL,GAAAP,EACA,KAAAC,EACA,UAAW,eAAeF,EAAQ,qBAAuB,EAAE,GAC3D,MAAOe,EACP,aAAAxB,EACA,SAAU6B,EACV,UAAA1B,EACA,SAAAG,EACA,SAAAC,EACA,SAAAC,EACA,eAAcC,GAAS,OACvB,mBAAkBsB,EAClB,YAAAnB,EACA,KAAAE,EACC,GAAGC,CAAA,CAAA,GAGJX,GAAaD,IACb8B,EAAAA,IAAC,OAAI,UAAU,sBAAsB,cAAY,OAC9C,SAAA,GAAGT,GAAc,QAAU,CAAC,GAC3BrB,EAAY,MAAMA,CAAS,GAAK,EAClC,EAAA,CACF,CAAA,EAEJ,CAEJ,CACF,EAEAN,EAAS,YAAc"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsxs as V, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as k, useRef as z, useImperativeHandle as B, useState as S, useCallback as q, useEffect as d } from "react";
|
|
3
|
+
/* empty css */
|
|
4
|
+
function f(e) {
|
|
5
|
+
e && (e.style.height = "0px", e.style.height = `${e.scrollHeight}px`);
|
|
6
|
+
}
|
|
7
|
+
const w = k(
|
|
8
|
+
({
|
|
9
|
+
value: e,
|
|
10
|
+
defaultValue: l,
|
|
11
|
+
onChange: m,
|
|
12
|
+
className: h = "",
|
|
13
|
+
maxLength: a,
|
|
14
|
+
showCount: p = !1,
|
|
15
|
+
autoGrow: s = !0,
|
|
16
|
+
disabled: x = !1,
|
|
17
|
+
readOnly: v = !1,
|
|
18
|
+
required: g = !1,
|
|
19
|
+
error: c = !1,
|
|
20
|
+
id: y,
|
|
21
|
+
name: $,
|
|
22
|
+
placeholder: b,
|
|
23
|
+
helperId: C,
|
|
24
|
+
rows: N = 3,
|
|
25
|
+
...T
|
|
26
|
+
}, H) => {
|
|
27
|
+
const i = z(null);
|
|
28
|
+
B(H, () => i.current ?? document.createElement("textarea"));
|
|
29
|
+
const u = e !== void 0, [R, j] = S(
|
|
30
|
+
() => l || ""
|
|
31
|
+
), n = u ? e : R, t = q(() => {
|
|
32
|
+
s && f(i.current);
|
|
33
|
+
}, [s]);
|
|
34
|
+
d(() => {
|
|
35
|
+
t();
|
|
36
|
+
const r = setTimeout(t, 0);
|
|
37
|
+
return () => clearTimeout(r);
|
|
38
|
+
}, [t]), d(() => {
|
|
39
|
+
t();
|
|
40
|
+
}, [n, t]);
|
|
41
|
+
const E = (r) => {
|
|
42
|
+
u || j(r.target.value), m?.(r), s && f(r.target);
|
|
43
|
+
}, I = C || void 0;
|
|
44
|
+
return /* @__PURE__ */ V("div", { className: `ui-textarea-wrapper ${h}`, children: [
|
|
45
|
+
/* @__PURE__ */ o(
|
|
46
|
+
"textarea",
|
|
47
|
+
{
|
|
48
|
+
ref: i,
|
|
49
|
+
id: y,
|
|
50
|
+
name: $,
|
|
51
|
+
className: `ui-textarea ${c ? "ui-textarea--error" : ""}`,
|
|
52
|
+
value: n,
|
|
53
|
+
defaultValue: l,
|
|
54
|
+
onChange: E,
|
|
55
|
+
maxLength: a,
|
|
56
|
+
disabled: x,
|
|
57
|
+
readOnly: v,
|
|
58
|
+
required: g,
|
|
59
|
+
"aria-invalid": c || void 0,
|
|
60
|
+
"aria-describedby": I,
|
|
61
|
+
placeholder: b,
|
|
62
|
+
rows: N,
|
|
63
|
+
...T
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
(p || a) && /* @__PURE__ */ o("div", { className: "ui-textarea-counter", "aria-hidden": "true", children: `${n?.length ?? 0}${a ? ` / ${a}` : ""}` })
|
|
67
|
+
] });
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
w.displayName = "Textarea";
|
|
71
|
+
export {
|
|
72
|
+
w as Textarea,
|
|
73
|
+
w as default
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=Textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.js","sources":["../../../../src/components/textarea/Textarea.tsx"],"sourcesContent":["/**\r\n * Textarea.tsx\r\n * -------------\r\n * Advanced, accessible textarea (auto-grow).\r\n *\r\n * Features:\r\n * - auto-resize (autoGrow)\r\n * - controlled / uncontrolled modes\r\n * - maxLength + optional character counter\r\n * - disabled, readOnly, required support\r\n * - aria-describedby linking for error / help text\r\n * - identical coding style to your existing library\r\n */\r\n\r\nimport React, {\r\n useRef,\r\n useEffect,\r\n useCallback,\r\n useState,\r\n forwardRef,\r\n useImperativeHandle,\r\n} from 'react';\r\n\r\nimport './Textarea.css';\r\n\r\nexport interface TextareaProps\r\n extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {\r\n /** Show character counter */\r\n showCount?: boolean;\r\n\r\n /** Enable auto resizing of height */\r\n autoGrow?: boolean;\r\n\r\n /** Visual error state */\r\n error?: boolean;\r\n\r\n /** Used for aria-describedby */\r\n helperId?: string;\r\n}\r\n\r\n/* Auto-grow helper */\r\nfunction syncHeight(el: HTMLTextAreaElement | null) {\r\n if (!el) return;\r\n el.style.height = '0px'; // reset first\r\n el.style.height = `${el.scrollHeight}px`;\r\n}\r\n\r\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\r\n (\r\n {\r\n value,\r\n defaultValue,\r\n onChange,\r\n className = '',\r\n maxLength,\r\n showCount = false,\r\n autoGrow = true,\r\n disabled = false,\r\n readOnly = false,\r\n required = false,\r\n error = false,\r\n id,\r\n name,\r\n placeholder,\r\n helperId,\r\n rows = 3,\r\n ...rest\r\n },\r\n ref\r\n ) => {\r\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\r\n\r\n useImperativeHandle(ref, () => {\r\n return innerRef.current ?? document.createElement('textarea');\r\n });\r\n\r\n const isControlled = value !== undefined;\r\n\r\n const [internalValue, setInternalValue] = useState<string>(\r\n () => (defaultValue as string) || ''\r\n );\r\n\r\n const currentValue = isControlled ? (value as string) : internalValue;\r\n\r\n /* Auto-grow on mount & updates */\r\n const resize = useCallback(() => {\r\n if (!autoGrow) return;\r\n syncHeight(innerRef.current);\r\n }, [autoGrow]);\r\n\r\n useEffect(() => {\r\n resize();\r\n const t = setTimeout(resize, 0);\r\n return () => clearTimeout(t);\r\n }, [resize]);\r\n\r\n useEffect(() => {\r\n resize();\r\n }, [currentValue, resize]);\r\n\r\n /* On change */\r\n const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n if (!isControlled) setInternalValue(e.target.value);\r\n onChange?.(e);\r\n\r\n if (autoGrow) syncHeight(e.target);\r\n };\r\n\r\n const describedBy = helperId || undefined;\r\n\r\n return (\r\n <div className={`ui-textarea-wrapper ${className}`}>\r\n <textarea\r\n ref={innerRef}\r\n id={id}\r\n name={name}\r\n className={`ui-textarea ${error ? 'ui-textarea--error' : ''}`}\r\n value={currentValue}\r\n defaultValue={defaultValue as string | undefined}\r\n onChange={handleChange}\r\n maxLength={maxLength}\r\n disabled={disabled}\r\n readOnly={readOnly}\r\n required={required}\r\n aria-invalid={error || undefined}\r\n aria-describedby={describedBy}\r\n placeholder={placeholder}\r\n rows={rows}\r\n {...rest}\r\n />\r\n\r\n {(showCount || maxLength) && (\r\n <div className=\"ui-textarea-counter\" aria-hidden=\"true\">\r\n {`${currentValue?.length ?? 0}${\r\n maxLength ? ` / ${maxLength}` : ''\r\n }`}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nTextarea.displayName = 'Textarea';\r\n\r\nexport default Textarea;\r\n"],"names":["syncHeight","el","Textarea","forwardRef","value","defaultValue","onChange","className","maxLength","showCount","autoGrow","disabled","readOnly","required","error","id","name","placeholder","helperId","rows","rest","ref","innerRef","useRef","useImperativeHandle","isControlled","internalValue","setInternalValue","useState","currentValue","resize","useCallback","useEffect","t","handleChange","e","describedBy","jsxs","jsx"],"mappings":";;;AAyCA,SAASA,EAAWC,GAAgC;AAClD,EAAKA,MACLA,EAAG,MAAM,SAAS,OAClBA,EAAG,MAAM,SAAS,GAAGA,EAAG,YAAY;AACtC;AAEO,MAAMC,IAAWC;AAAA,EACtB,CACE;AAAA,IACE,OAAAC;AAAA,IACA,cAAAC;AAAA,IACA,UAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,WAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,UAAAC,IAAW;AAAA,IACX,UAAAC,IAAW;AAAA,IACX,UAAAC,IAAW;AAAA,IACX,UAAAC,IAAW;AAAA,IACX,OAAAC,IAAQ;AAAA,IACR,IAAAC;AAAA,IACA,MAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAMC,IAAWC,EAAmC,IAAI;AAExD,IAAAC,EAAoBH,GAAK,MAChBC,EAAS,WAAW,SAAS,cAAc,UAAU,CAC7D;AAED,UAAMG,IAAerB,MAAU,QAEzB,CAACsB,GAAeC,CAAgB,IAAIC;AAAA,MACxC,MAAOvB,KAA2B;AAAA,IAAA,GAG9BwB,IAAeJ,IAAgBrB,IAAmBsB,GAGlDI,IAASC,EAAY,MAAM;AAC/B,MAAKrB,KACLV,EAAWsB,EAAS,OAAO;AAAA,IAC7B,GAAG,CAACZ,CAAQ,CAAC;AAEb,IAAAsB,EAAU,MAAM;AACd,MAAAF,EAAA;AACA,YAAMG,IAAI,WAAWH,GAAQ,CAAC;AAC9B,aAAO,MAAM,aAAaG,CAAC;AAAA,IAC7B,GAAG,CAACH,CAAM,CAAC,GAEXE,EAAU,MAAM;AACd,MAAAF,EAAA;AAAA,IACF,GAAG,CAACD,GAAcC,CAAM,CAAC;AAGzB,UAAMI,IAAe,CAACC,MAA8C;AAClE,MAAKV,KAAcE,EAAiBQ,EAAE,OAAO,KAAK,GAClD7B,IAAW6B,CAAC,GAERzB,KAAUV,EAAWmC,EAAE,MAAM;AAAA,IACnC,GAEMC,IAAclB,KAAY;AAEhC,WACE,gBAAAmB,EAAC,OAAA,EAAI,WAAW,uBAAuB9B,CAAS,IAC9C,UAAA;AAAA,MAAA,gBAAA+B;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAKhB;AAAA,UACL,IAAAP;AAAA,UACA,MAAAC;AAAA,UACA,WAAW,eAAeF,IAAQ,uBAAuB,EAAE;AAAA,UAC3D,OAAOe;AAAA,UACP,cAAAxB;AAAA,UACA,UAAU6B;AAAA,UACV,WAAA1B;AAAA,UACA,UAAAG;AAAA,UACA,UAAAC;AAAA,UACA,UAAAC;AAAA,UACA,gBAAcC,KAAS;AAAA,UACvB,oBAAkBsB;AAAA,UAClB,aAAAnB;AAAA,UACA,MAAAE;AAAA,UACC,GAAGC;AAAA,QAAA;AAAA,MAAA;AAAA,OAGJX,KAAaD,MACb,gBAAA8B,EAAC,SAAI,WAAU,uBAAsB,eAAY,QAC9C,UAAA,GAAGT,GAAc,UAAU,CAAC,GAC3BrB,IAAY,MAAMA,CAAS,KAAK,EAClC,GAAA,CACF;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEAN,EAAS,cAAc;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),i=require("react"),T=require("../../utils/portal/portal.cjs");;/* empty css */function l({id:s,message:a,onClose:o}){return t.jsxs("div",{className:"ui-toast",role:"alert",children:[t.jsx("span",{children:a}),t.jsx("button",{type:"button","aria-label":"Close notification",onClick:()=>o(s),children:"×"})]})}const u=i.createContext(null);function v({children:s}){const[a,o]=i.useState([]),d=i.useCallback((e,n=3e3)=>{const r=Math.random().toString(36).slice(2);o(c=>[...c,{id:r,message:e}]),setTimeout(()=>{o(c=>c.filter(x=>x.id!==r))},n)},[]),m=e=>{o(n=>n.filter(r=>r.id!==e))};return t.jsxs(u.Provider,{value:{show:d},children:[s,t.jsx(T.Portal,{children:t.jsx("div",{className:"ui-toast-container","aria-live":"polite","aria-atomic":"true",children:a.map(e=>t.jsx(l,{id:e.id,message:e.message,onClose:m},e.id))})})]})}function h(){const s=i.useContext(u);if(!s)throw new Error("useToast must be used inside <ToastProvider>");return s}exports.Toast=l;exports.ToastProvider=v;exports.useToast=h;
|
|
2
|
+
//# sourceMappingURL=Toast.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.cjs","sources":["../../../../src/components/toast/Toast.tsx"],"sourcesContent":["/**\r\n * Toast.tsx\r\n * ----------\r\n * Basic toast component UI. The provider handles logic.\r\n * ------------------\r\n * - Global provider that renders all toasts\r\n * - Contains aria-live region for screen readers\r\n * - Handles auto-dismiss\r\n * - Provides useToast() hook\r\n */\r\n\r\nimport React, { createContext, useContext, useState, useCallback } from 'react';\r\nimport { Portal } from '../../utils/portal/portal';\r\nimport './Toast.css';\r\n\r\ninterface ToastItem {\r\n id: string;\r\n message: string;\r\n}\r\n\r\ninterface ToastContextValue {\r\n show: (message: string, timeout?: number) => void;\r\n}\r\n\r\ninterface ToastProps {\r\n id: string;\r\n message: string;\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Toast({ id, message, onClose }: ToastProps) {\r\n return (\r\n <div className=\"ui-toast\" role=\"alert\">\r\n <span>{message}</span>\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close notification\"\r\n onClick={() => onClose(id)}\r\n >\r\n ×\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\nconst ToastContext = createContext<ToastContextValue | null>(null);\r\n\r\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\r\n const [toasts, setToasts] = useState<ToastItem[]>([]);\r\n\r\n const show = useCallback((message: string, timeout = 3000) => {\r\n const id = Math.random().toString(36).slice(2);\r\n\r\n setToasts((prev) => [...prev, { id, message }]);\r\n\r\n setTimeout(() => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, timeout);\r\n }, []);\r\n\r\n const remove = (id: string) => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n };\r\n\r\n return (\r\n <ToastContext.Provider value={{ show }}>\r\n {/* Main app */}\r\n {children}\r\n\r\n {/* Portal for notification list */}\r\n <Portal>\r\n <div\r\n className=\"ui-toast-container\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n >\r\n {toasts.map((t) => (\r\n <Toast key={t.id} id={t.id} message={t.message} onClose={remove} />\r\n ))}\r\n </div>\r\n </Portal>\r\n </ToastContext.Provider>\r\n );\r\n}\r\n\r\nexport function useToast() {\r\n const ctx = useContext(ToastContext);\r\n if (!ctx) throw new Error('useToast must be used inside <ToastProvider>');\r\n return ctx;\r\n}\r\n"],"names":["Toast","id","message","onClose","jsxs","jsx","ToastContext","createContext","ToastProvider","children","toasts","setToasts","useState","show","useCallback","timeout","prev","t","remove","Portal","useToast","ctx","useContext"],"mappings":"8MA8BO,SAASA,EAAM,CAAE,GAAAC,EAAI,QAAAC,EAAS,QAAAC,GAAuB,CAC1D,OACEC,EAAAA,KAAC,MAAA,CAAI,UAAU,WAAW,KAAK,QAC7B,SAAA,CAAAC,EAAAA,IAAC,QAAM,SAAAH,CAAA,CAAQ,EACfG,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,aAAW,qBACX,QAAS,IAAMF,EAAQF,CAAE,EAC1B,SAAA,GAAA,CAAA,CAED,EACF,CAEJ,CAEA,MAAMK,EAAeC,EAAAA,cAAwC,IAAI,EAE1D,SAASC,EAAc,CAAE,SAAAC,GAA2C,CACzE,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAsB,CAAA,CAAE,EAE9CC,EAAOC,EAAAA,YAAY,CAACZ,EAAiBa,EAAU,MAAS,CAC5D,MAAMd,EAAK,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,CAAC,EAE7CU,EAAWK,GAAS,CAAC,GAAGA,EAAM,CAAE,GAAAf,EAAI,QAAAC,CAAA,CAAS,CAAC,EAE9C,WAAW,IAAM,CACfS,EAAWK,GAASA,EAAK,OAAQC,GAAMA,EAAE,KAAOhB,CAAE,CAAC,CACrD,EAAGc,CAAO,CACZ,EAAG,CAAA,CAAE,EAECG,EAAUjB,GAAe,CAC7BU,EAAWK,GAASA,EAAK,OAAQC,GAAMA,EAAE,KAAOhB,CAAE,CAAC,CACrD,EAEA,cACGK,EAAa,SAAb,CAAsB,MAAO,CAAE,KAAAO,GAE7B,SAAA,CAAAJ,QAGAU,EAAAA,OAAA,CACC,SAAAd,EAAAA,IAAC,MAAA,CACC,UAAU,qBACV,YAAU,SACV,cAAY,OAEX,WAAO,IAAKY,GACXZ,MAACL,GAAiB,GAAIiB,EAAE,GAAI,QAASA,EAAE,QAAS,QAASC,CAAA,EAA7CD,EAAE,EAAmD,CAClE,CAAA,CAAA,CACH,CACF,CAAA,EACF,CAEJ,CAEO,SAASG,GAAW,CACzB,MAAMC,EAAMC,EAAAA,WAAWhB,CAAY,EACnC,GAAI,CAACe,EAAK,MAAM,IAAI,MAAM,8CAA8C,EACxE,OAAOA,CACT"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsxs as l, jsx as i } from "react/jsx-runtime";
|
|
2
|
+
import { useState as f, useCallback as h, createContext as p, useContext as v } from "react";
|
|
3
|
+
import { Portal as T } from "../../utils/portal/portal.js";
|
|
4
|
+
/* empty css */
|
|
5
|
+
function x({ id: e, message: s, onClose: o }) {
|
|
6
|
+
return /* @__PURE__ */ l("div", { className: "ui-toast", role: "alert", children: [
|
|
7
|
+
/* @__PURE__ */ i("span", { children: s }),
|
|
8
|
+
/* @__PURE__ */ i(
|
|
9
|
+
"button",
|
|
10
|
+
{
|
|
11
|
+
type: "button",
|
|
12
|
+
"aria-label": "Close notification",
|
|
13
|
+
onClick: () => o(e),
|
|
14
|
+
children: "×"
|
|
15
|
+
}
|
|
16
|
+
)
|
|
17
|
+
] });
|
|
18
|
+
}
|
|
19
|
+
const c = p(null);
|
|
20
|
+
function w({ children: e }) {
|
|
21
|
+
const [s, o] = f([]), u = h((t, n = 3e3) => {
|
|
22
|
+
const r = Math.random().toString(36).slice(2);
|
|
23
|
+
o((a) => [...a, { id: r, message: t }]), setTimeout(() => {
|
|
24
|
+
o((a) => a.filter((m) => m.id !== r));
|
|
25
|
+
}, n);
|
|
26
|
+
}, []), d = (t) => {
|
|
27
|
+
o((n) => n.filter((r) => r.id !== t));
|
|
28
|
+
};
|
|
29
|
+
return /* @__PURE__ */ l(c.Provider, { value: { show: u }, children: [
|
|
30
|
+
e,
|
|
31
|
+
/* @__PURE__ */ i(T, { children: /* @__PURE__ */ i(
|
|
32
|
+
"div",
|
|
33
|
+
{
|
|
34
|
+
className: "ui-toast-container",
|
|
35
|
+
"aria-live": "polite",
|
|
36
|
+
"aria-atomic": "true",
|
|
37
|
+
children: s.map((t) => /* @__PURE__ */ i(x, { id: t.id, message: t.message, onClose: d }, t.id))
|
|
38
|
+
}
|
|
39
|
+
) })
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
function j() {
|
|
43
|
+
const e = v(c);
|
|
44
|
+
if (!e) throw new Error("useToast must be used inside <ToastProvider>");
|
|
45
|
+
return e;
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
x as Toast,
|
|
49
|
+
w as ToastProvider,
|
|
50
|
+
j as useToast
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=Toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.js","sources":["../../../../src/components/toast/Toast.tsx"],"sourcesContent":["/**\r\n * Toast.tsx\r\n * ----------\r\n * Basic toast component UI. The provider handles logic.\r\n * ------------------\r\n * - Global provider that renders all toasts\r\n * - Contains aria-live region for screen readers\r\n * - Handles auto-dismiss\r\n * - Provides useToast() hook\r\n */\r\n\r\nimport React, { createContext, useContext, useState, useCallback } from 'react';\r\nimport { Portal } from '../../utils/portal/portal';\r\nimport './Toast.css';\r\n\r\ninterface ToastItem {\r\n id: string;\r\n message: string;\r\n}\r\n\r\ninterface ToastContextValue {\r\n show: (message: string, timeout?: number) => void;\r\n}\r\n\r\ninterface ToastProps {\r\n id: string;\r\n message: string;\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Toast({ id, message, onClose }: ToastProps) {\r\n return (\r\n <div className=\"ui-toast\" role=\"alert\">\r\n <span>{message}</span>\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close notification\"\r\n onClick={() => onClose(id)}\r\n >\r\n ×\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\nconst ToastContext = createContext<ToastContextValue | null>(null);\r\n\r\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\r\n const [toasts, setToasts] = useState<ToastItem[]>([]);\r\n\r\n const show = useCallback((message: string, timeout = 3000) => {\r\n const id = Math.random().toString(36).slice(2);\r\n\r\n setToasts((prev) => [...prev, { id, message }]);\r\n\r\n setTimeout(() => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, timeout);\r\n }, []);\r\n\r\n const remove = (id: string) => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n };\r\n\r\n return (\r\n <ToastContext.Provider value={{ show }}>\r\n {/* Main app */}\r\n {children}\r\n\r\n {/* Portal for notification list */}\r\n <Portal>\r\n <div\r\n className=\"ui-toast-container\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n >\r\n {toasts.map((t) => (\r\n <Toast key={t.id} id={t.id} message={t.message} onClose={remove} />\r\n ))}\r\n </div>\r\n </Portal>\r\n </ToastContext.Provider>\r\n );\r\n}\r\n\r\nexport function useToast() {\r\n const ctx = useContext(ToastContext);\r\n if (!ctx) throw new Error('useToast must be used inside <ToastProvider>');\r\n return ctx;\r\n}\r\n"],"names":["Toast","id","message","onClose","jsxs","jsx","ToastContext","createContext","ToastProvider","children","toasts","setToasts","useState","show","useCallback","timeout","prev","t","remove","Portal","useToast","ctx","useContext"],"mappings":";;;;AA8BO,SAASA,EAAM,EAAE,IAAAC,GAAI,SAAAC,GAAS,SAAAC,KAAuB;AAC1D,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,YAAW,MAAK,SAC7B,UAAA;AAAA,IAAA,gBAAAC,EAAC,UAAM,UAAAH,EAAA,CAAQ;AAAA,IACf,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,MAAMF,EAAQF,CAAE;AAAA,QAC1B,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GACF;AAEJ;AAEA,MAAMK,IAAeC,EAAwC,IAAI;AAE1D,SAASC,EAAc,EAAE,UAAAC,KAA2C;AACzE,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAsB,CAAA,CAAE,GAE9CC,IAAOC,EAAY,CAACZ,GAAiBa,IAAU,QAAS;AAC5D,UAAMd,IAAK,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,CAAC;AAE7C,IAAAU,EAAU,CAACK,MAAS,CAAC,GAAGA,GAAM,EAAE,IAAAf,GAAI,SAAAC,EAAA,CAAS,CAAC,GAE9C,WAAW,MAAM;AACf,MAAAS,EAAU,CAACK,MAASA,EAAK,OAAO,CAACC,MAAMA,EAAE,OAAOhB,CAAE,CAAC;AAAA,IACrD,GAAGc,CAAO;AAAA,EACZ,GAAG,CAAA,CAAE,GAECG,IAAS,CAACjB,MAAe;AAC7B,IAAAU,EAAU,CAACK,MAASA,EAAK,OAAO,CAACC,MAAMA,EAAE,OAAOhB,CAAE,CAAC;AAAA,EACrD;AAEA,2BACGK,EAAa,UAAb,EAAsB,OAAO,EAAE,MAAAO,KAE7B,UAAA;AAAA,IAAAJ;AAAA,sBAGAU,GAAA,EACC,UAAA,gBAAAd;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,aAAU;AAAA,QACV,eAAY;AAAA,QAEX,YAAO,IAAI,CAAC,MACX,gBAAAA,EAACL,KAAiB,IAAI,EAAE,IAAI,SAAS,EAAE,SAAS,SAASkB,EAAA,GAA7C,EAAE,EAAmD,CAClE;AAAA,MAAA;AAAA,IAAA,EACH,CACF;AAAA,EAAA,GACF;AAEJ;AAEO,SAASE,IAAW;AACzB,QAAMC,IAAMC,EAAWhB,CAAY;AACnC,MAAI,CAACe,EAAK,OAAM,IAAI,MAAM,8CAA8C;AACxE,SAAOA;AACT;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),e=require("react");;/* empty css */const P=require("../../utils/portal/portal.cjs");function S({label:g,children:R,className:E="",delay:y=200,offset:i=8}){const[o,p]=e.useState(!1),[m,h]=e.useState({top:0,left:0}),[L,x]=e.useState("top"),c=e.useRef(null),l=e.useRef(null),r=e.useRef(null),w=`tooltip-${e.useId()}`,v=()=>{r.current=window.setTimeout(()=>{p(!0)},y)},u=()=>{r.current&&clearTimeout(r.current),p(!1)},n=e.useCallback(()=>{if(!c.current||!l.current)return;const t=c.current.getBoundingClientRect(),a=l.current.getBoundingClientRect(),j=window.scrollX,d=window.scrollY,T=t.left+j+t.width/2;let f=t.top+d-a.height-i,b="top";f<d+8&&(f=t.bottom+d+i,b="bottom"),x(b),h({top:f,left:T})},[i]);return e.useLayoutEffect(()=>{if(o)return n(),window.addEventListener("scroll",n,!0),window.addEventListener("resize",n),()=>{window.removeEventListener("scroll",n,!0),window.removeEventListener("resize",n)}},[o,n]),e.useEffect(()=>{if(!o)return;const t=a=>{a.key==="Escape"&&u()};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[o]),e.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),s.jsxs(s.Fragment,{children:[s.jsx("span",{ref:c,className:"ui-tooltip-container","aria-describedby":o?w:void 0,onMouseEnter:v,onMouseLeave:u,onFocus:v,onBlur:u,tabIndex:0,children:R}),o&&s.jsx(P.Portal,{children:s.jsx("div",{ref:l,id:w,role:"tooltip","data-placement":L,className:`ui-tooltip-bubble ${E}`,style:{position:"absolute",top:m.top,left:m.left},children:g})})]})}exports.Tooltip=S;
|
|
2
|
+
//# sourceMappingURL=Tooltip.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.cjs","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import React, {\r\n useState,\r\n useRef,\r\n useLayoutEffect,\r\n useEffect,\r\n useCallback,\r\n useId,\r\n} from 'react';\r\nimport './Tooltip.css';\r\nimport { Portal } from '../../utils/portal/portal';\r\n\r\ntype Placement = 'top' | 'bottom';\r\n\r\nexport interface TooltipProps {\r\n label: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n delay?: number;\r\n offset?: number;\r\n}\r\n\r\nexport function Tooltip({\r\n label,\r\n children,\r\n className = '',\r\n delay = 200,\r\n offset = 8,\r\n}: TooltipProps) {\r\n const [open, setOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const [placement, setPlacement] = useState<Placement>('top');\r\n\r\n const triggerRef = useRef<HTMLSpanElement | null>(null);\r\n const tooltipRef = useRef<HTMLDivElement | null>(null);\r\nconst timeoutRef = useRef<number | null>(null);\r\n\r\n const id = `tooltip-${useId()}`;\r\n\r\n /* ---------------- Visibility ---------------- */\r\n\r\n const show = () => {\r\n timeoutRef.current = window.setTimeout(() => {\r\n setOpen(true);\r\n }, delay);\r\n };\r\n\r\n const hide = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setOpen(false);\r\n };\r\n\r\n /* ---------------- Positioning ---------------- */\r\n\r\n const updatePosition = useCallback(() => {\r\n if (!triggerRef.current || !tooltipRef.current) return;\r\n\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\r\n\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n\r\n const centerX =\r\n triggerRect.left + scrollX + triggerRect.width / 2;\r\n\r\n // Try top first\r\n let top =\r\n triggerRect.top +\r\n scrollY -\r\n tooltipRect.height -\r\n offset;\r\n\r\n let nextPlacement: Placement = 'top';\r\n\r\n // Flip to bottom if clipped\r\n if (top < scrollY + 8) {\r\n top =\r\n triggerRect.bottom +\r\n scrollY +\r\n offset;\r\n nextPlacement = 'bottom';\r\n }\r\n\r\n setPlacement(nextPlacement);\r\n setCoords({ top, left: centerX });\r\n }, [offset]);\r\n\r\n /* ---------------- Effects ---------------- */\r\n\r\n useLayoutEffect(() => {\r\n if (!open) return;\r\n\r\n updatePosition();\r\n\r\n window.addEventListener('scroll', updatePosition, true);\r\n window.addEventListener('resize', updatePosition);\r\n\r\n return () => {\r\n window.removeEventListener('scroll', updatePosition, true);\r\n window.removeEventListener('resize', updatePosition);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') hide();\r\n };\r\n\r\n document.addEventListener('keydown', onKeyDown);\r\n return () => document.removeEventListener('keydown', onKeyDown);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n /* ---------------- Render ---------------- */\r\n\r\n return (\r\n <>\r\n <span\r\n ref={triggerRef}\r\n className=\"ui-tooltip-container\"\r\n aria-describedby={open ? id : undefined}\r\n onMouseEnter={show}\r\n onMouseLeave={hide}\r\n onFocus={show}\r\n onBlur={hide}\r\n tabIndex={0}\r\n >\r\n {children}\r\n </span>\r\n\r\n {open && (\r\n <Portal>\r\n <div\r\n ref={tooltipRef}\r\n id={id}\r\n role=\"tooltip\"\r\n data-placement={placement}\r\n className={`ui-tooltip-bubble ${className}`}\r\n style={{\r\n position: 'absolute',\r\n top: coords.top,\r\n left: coords.left,\r\n }}\r\n >\r\n {label}\r\n </div>\r\n </Portal>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["Tooltip","label","children","className","delay","offset","open","setOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","id","useId","show","hide","updatePosition","useCallback","triggerRect","tooltipRect","scrollX","scrollY","centerX","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","e","jsxs","Fragment","jsx","Portal"],"mappings":"sNAqBO,SAASA,EAAQ,CACtB,MAAAC,EACA,SAAAC,EACA,UAAAC,EAAY,GACZ,MAAAC,EAAQ,IACR,OAAAC,EAAS,CACX,EAAiB,CACf,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,EAAK,EAChC,CAACC,EAAQC,CAAS,EAAIF,EAAAA,SAAS,CAAE,IAAK,EAAG,KAAM,EAAG,EAClD,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAoB,KAAK,EAErDK,EAAaC,EAAAA,OAA+B,IAAI,EAChDC,EAAaD,EAAAA,OAA8B,IAAI,EACjDE,EAAaF,EAAAA,OAAsB,IAAI,EAErCG,EAAK,WAAWC,EAAAA,MAAA,CAAO,GAIvBC,EAAO,IAAM,CACjBH,EAAW,QAAU,OAAO,WAAW,IAAM,CAC3CT,EAAQ,EAAI,CACd,EAAGH,CAAK,CACV,EAEMgB,EAAO,IAAM,CACbJ,EAAW,SAAS,aAAaA,EAAW,OAAO,EACvDT,EAAQ,EAAK,CACf,EAIMc,EAAiBC,EAAAA,YAAY,IAAM,CACvC,GAAI,CAACT,EAAW,SAAW,CAACE,EAAW,QAAS,OAEhD,MAAMQ,EAAcV,EAAW,QAAQ,sBAAA,EACjCW,EAAcT,EAAW,QAAQ,sBAAA,EAEjCU,EAAU,OAAO,QACjBC,EAAU,OAAO,QAEjBC,EACJJ,EAAY,KAAOE,EAAUF,EAAY,MAAQ,EAGnD,IAAIK,EACFL,EAAY,IACZG,EACAF,EAAY,OACZnB,EAEEwB,EAA2B,MAG3BD,EAAMF,EAAU,IAClBE,EACEL,EAAY,OACZG,EACArB,EACFwB,EAAgB,UAGlBjB,EAAaiB,CAAa,EAC1BnB,EAAU,CAAE,IAAAkB,EAAK,KAAMD,CAAA,CAAS,CAClC,EAAG,CAACtB,CAAM,CAAC,EAIXyB,OAAAA,EAAAA,gBAAgB,IAAM,CACpB,GAAKxB,EAEL,OAAAe,EAAA,EAEA,OAAO,iBAAiB,SAAUA,EAAgB,EAAI,EACtD,OAAO,iBAAiB,SAAUA,CAAc,EAEzC,IAAM,CACX,OAAO,oBAAoB,SAAUA,EAAgB,EAAI,EACzD,OAAO,oBAAoB,SAAUA,CAAc,CACrD,CACF,EAAG,CAACf,EAAMe,CAAc,CAAC,EAEzBU,EAAAA,UAAU,IAAM,CACd,GAAI,CAACzB,EAAM,OAEX,MAAM0B,EAAaC,GAAqB,CAClCA,EAAE,MAAQ,UAAUb,EAAA,CAC1B,EAEA,gBAAS,iBAAiB,UAAWY,CAAS,EACvC,IAAM,SAAS,oBAAoB,UAAWA,CAAS,CAChE,EAAG,CAAC1B,CAAI,CAAC,EAETyB,EAAAA,UAAU,IACD,IAAM,CACPf,EAAW,SAAS,aAAaA,EAAW,OAAO,CACzD,EACC,CAAA,CAAE,EAKHkB,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAC,EAAAA,IAAC,OAAA,CACC,IAAKvB,EACL,UAAU,uBACV,mBAAkBP,EAAOW,EAAK,OAC9B,aAAcE,EACd,aAAcC,EACd,QAASD,EACT,OAAQC,EACR,SAAU,EAET,SAAAlB,CAAA,CAAA,EAGFI,SACE+B,SAAA,CACC,SAAAD,EAAAA,IAAC,MAAA,CACC,IAAKrB,EACL,GAAAE,EACA,KAAK,UACL,iBAAgBN,EAChB,UAAW,qBAAqBR,CAAS,GACzC,MAAO,CACL,SAAU,WACV,IAAKM,EAAO,IACZ,KAAMA,EAAO,IAAA,EAGd,SAAAR,CAAA,CAAA,CACH,CACF,CAAA,EAEJ,CAEJ"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsxs as B, Fragment as X, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { useState as p, useRef as m, useId as j, useCallback as z, useLayoutEffect as F, useEffect as E } from "react";
|
|
3
|
+
/* empty css */
|
|
4
|
+
import { Portal as I } from "../../utils/portal/portal.js";
|
|
5
|
+
function D({
|
|
6
|
+
label: h,
|
|
7
|
+
children: L,
|
|
8
|
+
className: R = "",
|
|
9
|
+
delay: y = 200,
|
|
10
|
+
offset: r = 8
|
|
11
|
+
}) {
|
|
12
|
+
const [t, f] = p(!1), [w, x] = p({ top: 0, left: 0 }), [k, C] = p("top"), i = m(null), s = m(null), n = m(null), v = `tooltip-${j()}`, b = () => {
|
|
13
|
+
n.current = window.setTimeout(() => {
|
|
14
|
+
f(!0);
|
|
15
|
+
}, y);
|
|
16
|
+
}, c = () => {
|
|
17
|
+
n.current && clearTimeout(n.current), f(!1);
|
|
18
|
+
}, o = z(() => {
|
|
19
|
+
if (!i.current || !s.current) return;
|
|
20
|
+
const e = i.current.getBoundingClientRect(), l = s.current.getBoundingClientRect(), P = window.scrollX, u = window.scrollY, T = e.left + P + e.width / 2;
|
|
21
|
+
let d = e.top + u - l.height - r, g = "top";
|
|
22
|
+
d < u + 8 && (d = e.bottom + u + r, g = "bottom"), C(g), x({ top: d, left: T });
|
|
23
|
+
}, [r]);
|
|
24
|
+
return F(() => {
|
|
25
|
+
if (t)
|
|
26
|
+
return o(), window.addEventListener("scroll", o, !0), window.addEventListener("resize", o), () => {
|
|
27
|
+
window.removeEventListener("scroll", o, !0), window.removeEventListener("resize", o);
|
|
28
|
+
};
|
|
29
|
+
}, [t, o]), E(() => {
|
|
30
|
+
if (!t) return;
|
|
31
|
+
const e = (l) => {
|
|
32
|
+
l.key === "Escape" && c();
|
|
33
|
+
};
|
|
34
|
+
return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
|
|
35
|
+
}, [t]), E(() => () => {
|
|
36
|
+
n.current && clearTimeout(n.current);
|
|
37
|
+
}, []), /* @__PURE__ */ B(X, { children: [
|
|
38
|
+
/* @__PURE__ */ a(
|
|
39
|
+
"span",
|
|
40
|
+
{
|
|
41
|
+
ref: i,
|
|
42
|
+
className: "ui-tooltip-container",
|
|
43
|
+
"aria-describedby": t ? v : void 0,
|
|
44
|
+
onMouseEnter: b,
|
|
45
|
+
onMouseLeave: c,
|
|
46
|
+
onFocus: b,
|
|
47
|
+
onBlur: c,
|
|
48
|
+
tabIndex: 0,
|
|
49
|
+
children: L
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
t && /* @__PURE__ */ a(I, { children: /* @__PURE__ */ a(
|
|
53
|
+
"div",
|
|
54
|
+
{
|
|
55
|
+
ref: s,
|
|
56
|
+
id: v,
|
|
57
|
+
role: "tooltip",
|
|
58
|
+
"data-placement": k,
|
|
59
|
+
className: `ui-tooltip-bubble ${R}`,
|
|
60
|
+
style: {
|
|
61
|
+
position: "absolute",
|
|
62
|
+
top: w.top,
|
|
63
|
+
left: w.left
|
|
64
|
+
},
|
|
65
|
+
children: h
|
|
66
|
+
}
|
|
67
|
+
) })
|
|
68
|
+
] });
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
D as Tooltip
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=Tooltip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.js","sources":["../../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import React, {\r\n useState,\r\n useRef,\r\n useLayoutEffect,\r\n useEffect,\r\n useCallback,\r\n useId,\r\n} from 'react';\r\nimport './Tooltip.css';\r\nimport { Portal } from '../../utils/portal/portal';\r\n\r\ntype Placement = 'top' | 'bottom';\r\n\r\nexport interface TooltipProps {\r\n label: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n delay?: number;\r\n offset?: number;\r\n}\r\n\r\nexport function Tooltip({\r\n label,\r\n children,\r\n className = '',\r\n delay = 200,\r\n offset = 8,\r\n}: TooltipProps) {\r\n const [open, setOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const [placement, setPlacement] = useState<Placement>('top');\r\n\r\n const triggerRef = useRef<HTMLSpanElement | null>(null);\r\n const tooltipRef = useRef<HTMLDivElement | null>(null);\r\nconst timeoutRef = useRef<number | null>(null);\r\n\r\n const id = `tooltip-${useId()}`;\r\n\r\n /* ---------------- Visibility ---------------- */\r\n\r\n const show = () => {\r\n timeoutRef.current = window.setTimeout(() => {\r\n setOpen(true);\r\n }, delay);\r\n };\r\n\r\n const hide = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setOpen(false);\r\n };\r\n\r\n /* ---------------- Positioning ---------------- */\r\n\r\n const updatePosition = useCallback(() => {\r\n if (!triggerRef.current || !tooltipRef.current) return;\r\n\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\r\n\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n\r\n const centerX =\r\n triggerRect.left + scrollX + triggerRect.width / 2;\r\n\r\n // Try top first\r\n let top =\r\n triggerRect.top +\r\n scrollY -\r\n tooltipRect.height -\r\n offset;\r\n\r\n let nextPlacement: Placement = 'top';\r\n\r\n // Flip to bottom if clipped\r\n if (top < scrollY + 8) {\r\n top =\r\n triggerRect.bottom +\r\n scrollY +\r\n offset;\r\n nextPlacement = 'bottom';\r\n }\r\n\r\n setPlacement(nextPlacement);\r\n setCoords({ top, left: centerX });\r\n }, [offset]);\r\n\r\n /* ---------------- Effects ---------------- */\r\n\r\n useLayoutEffect(() => {\r\n if (!open) return;\r\n\r\n updatePosition();\r\n\r\n window.addEventListener('scroll', updatePosition, true);\r\n window.addEventListener('resize', updatePosition);\r\n\r\n return () => {\r\n window.removeEventListener('scroll', updatePosition, true);\r\n window.removeEventListener('resize', updatePosition);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') hide();\r\n };\r\n\r\n document.addEventListener('keydown', onKeyDown);\r\n return () => document.removeEventListener('keydown', onKeyDown);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n /* ---------------- Render ---------------- */\r\n\r\n return (\r\n <>\r\n <span\r\n ref={triggerRef}\r\n className=\"ui-tooltip-container\"\r\n aria-describedby={open ? id : undefined}\r\n onMouseEnter={show}\r\n onMouseLeave={hide}\r\n onFocus={show}\r\n onBlur={hide}\r\n tabIndex={0}\r\n >\r\n {children}\r\n </span>\r\n\r\n {open && (\r\n <Portal>\r\n <div\r\n ref={tooltipRef}\r\n id={id}\r\n role=\"tooltip\"\r\n data-placement={placement}\r\n className={`ui-tooltip-bubble ${className}`}\r\n style={{\r\n position: 'absolute',\r\n top: coords.top,\r\n left: coords.left,\r\n }}\r\n >\r\n {label}\r\n </div>\r\n </Portal>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["Tooltip","label","children","className","delay","offset","open","setOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","id","useId","show","hide","updatePosition","useCallback","triggerRect","tooltipRect","scrollX","scrollY","centerX","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","e","jsxs","Fragment","jsx","Portal"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),x=require("react");;/* empty css */function j({data:f,selectedId:w,onSelect:h,className:g=""}){const[d,y]=x.useState(new Set),[A,o]=x.useState(null),u=e=>{y(i=>{const r=new Set(i);return r.has(e)?r.delete(e):r.add(e),r})},p=(e,i=[])=>(e.forEach(r=>{i.push(r);const t=d.has(r.id);r.children&&r.children.length>0&&t&&p(r.children,i)}),i),N=(e,i,r)=>{const t=e.key;if(t==="Enter"||t===" "){e.preventDefault(),h&&h(i.id);return}if(t==="ArrowLeft"){e.preventDefault();const n=i.children&&i.children.length>0,s=d.has(i.id);if(n&&s){u(i.id);return}r&&o(r.id);return}if(t==="ArrowRight"){e.preventDefault();const n=i.children&&i.children.length>0,s=d.has(i.id);if(n&&!s){u(i.id);return}if(n&&s){const c=Array.isArray(i.children)&&i.children.length>0?i.children[0]:void 0;c&&o(c.id)}return}if(t==="ArrowUp"||t==="ArrowDown"){e.preventDefault();const n=p(f),s=n.findIndex(m=>m.id===i.id);if(s===-1)return;const c=t==="ArrowUp"?s-1:s+1,l=n[c];l&&o(l.id)}},v=(e,i,r)=>{const t=d.has(e.id),n=e.id===w,s=e.id===A,c=Array.isArray(e.children)&&e.children.length>0;return a.jsxs("div",{children:[a.jsxs("div",{role:"treeitem","aria-expanded":c?t:void 0,tabIndex:s?0:-1,className:["ui-tree-node",n?"selected":"",s?"active":""].filter(Boolean).join(" "),style:{paddingLeft:r*16},onClick:()=>{h&&h(e.id),o(e.id),Array.isArray(e.children)&&e.children.length>0&&u(e.id)},onKeyDown:l=>N(l,e,i),children:[c?a.jsx("span",{className:`ui-tree-arrow ${t?"open":""}`,onClick:l=>{l.stopPropagation(),u(e.id)},children:"▶"}):a.jsx("span",{className:"ui-tree-arrow empty",children:"•"}),e.icon&&a.jsx("span",{className:"ui-tree-icon",children:e.icon}),a.jsx("span",{className:"ui-tree-label",children:e.label})]}),c&&t&&e.children&&a.jsx("div",{role:"group",children:e.children.map(l=>v(l,e,r+1))})]},e.id)};return a.jsx("div",{className:`ui-treeview ${g}`,role:"tree",children:f.map(e=>v(e,void 0,0))})}exports.TreeView=j;
|
|
2
|
+
//# sourceMappingURL=TreeView.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TreeView.cjs","sources":["../../../../src/components/treeview/TreeView.tsx"],"sourcesContent":["/**\r\n * TreeView.tsx — FINAL VERSION\r\n * ----------------------------\r\n * Features:\r\n * - Expand/collapse\r\n * - Recursive rendering\r\n * - Arrow key navigation\r\n * - Enter/Space to select\r\n * - ARIA TreeView roles\r\n * - Value controlled OR internal state\r\n */\r\n\r\nimport React, { useState } from 'react';\r\nimport './TreeView.css';\r\n\r\nexport interface TreeNode {\r\n id: string;\r\n label: string;\r\n icon?: React.ReactNode;\r\n children?: TreeNode[];\r\n}\r\n\r\ninterface TreeViewProps {\r\n data: TreeNode[];\r\n selectedId?: string;\r\n onSelect?: (id: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function TreeView({\r\n data,\r\n selectedId,\r\n onSelect,\r\n className = '',\r\n}: TreeViewProps) {\r\n const [openNodes, setOpenNodes] = useState<Set<string>>(new Set());\r\n const [activeNode, setActiveNode] = useState<string | null>(null);\r\n\r\n const toggleNode = (id: string) => {\r\n setOpenNodes((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(id)) next.delete(id);\r\n else next.add(id);\r\n return next;\r\n });\r\n };\r\n\r\n const flatten = (nodes: TreeNode[], acc: TreeNode[] = []): TreeNode[] => {\r\n nodes.forEach((node) => {\r\n acc.push(node);\r\n\r\n const isOpen = openNodes.has(node.id);\r\n if (node.children && node.children.length > 0 && isOpen) {\r\n flatten(node.children, acc);\r\n }\r\n });\r\n return acc;\r\n };\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent,\r\n node: TreeNode,\r\n parent: TreeNode | undefined\r\n ) => {\r\n const key = e.key;\r\n\r\n // Select\r\n if (key === 'Enter' || key === ' ') {\r\n e.preventDefault();\r\n if (onSelect) onSelect(node.id);\r\n return;\r\n }\r\n\r\n // Collapse or go to parent\r\n if (key === 'ArrowLeft') {\r\n e.preventDefault();\r\n\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isOpen = openNodes.has(node.id);\r\n\r\n if (hasChildren && isOpen) {\r\n toggleNode(node.id);\r\n return;\r\n }\r\n\r\n if (parent) {\r\n setActiveNode(parent.id);\r\n }\r\n return;\r\n }\r\n\r\n // Expand or go to first child\r\n if (key === 'ArrowRight') {\r\n e.preventDefault();\r\n\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isOpen = openNodes.has(node.id);\r\n\r\n if (hasChildren && !isOpen) {\r\n toggleNode(node.id);\r\n return;\r\n }\r\n\r\n if (hasChildren && isOpen) {\r\n const firstChild =\r\n Array.isArray(node.children) && node.children.length > 0\r\n ? node.children[0]\r\n : undefined;\r\n\r\n if (firstChild) {\r\n setActiveNode(firstChild.id);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Up/Down navigation\r\n if (key === 'ArrowUp' || key === 'ArrowDown') {\r\n e.preventDefault();\r\n const flat = flatten(data);\r\n const index = flat.findIndex((n) => n.id === node.id);\r\n\r\n if (index === -1) return;\r\n\r\n const nextIndex = key === 'ArrowUp' ? index - 1 : index + 1;\r\n const nextNode = flat[nextIndex];\r\n\r\n if (nextNode) {\r\n setActiveNode(nextNode.id);\r\n }\r\n }\r\n };\r\n\r\n const renderNode = (\r\n node: TreeNode,\r\n parent: TreeNode | undefined,\r\n depth: number\r\n ) => {\r\n const isOpen = openNodes.has(node.id);\r\n const isSelected = node.id === selectedId;\r\n const isActive = node.id === activeNode;\r\n const hasChildren =\r\n Array.isArray(node.children) && node.children.length > 0;\r\n\r\n return (\r\n <div key={node.id}>\r\n <div\r\n role=\"treeitem\"\r\n aria-expanded={hasChildren ? isOpen : undefined}\r\n tabIndex={isActive ? 0 : -1}\r\n className={[\r\n 'ui-tree-node',\r\n isSelected ? 'selected' : '',\r\n isActive ? 'active' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ')}\r\n style={{ paddingLeft: depth * 16 }}\r\n onClick={() => {\r\n if (onSelect) onSelect(node.id);\r\n setActiveNode(node.id);\r\n\r\n const hasChildren =\r\n Array.isArray(node.children) && node.children.length > 0;\r\n\r\n // Clicking node should expand/collapse just like arrow\r\n if (hasChildren) {\r\n toggleNode(node.id);\r\n }\r\n }}\r\n onKeyDown={(e) => handleKeyDown(e, node, parent)}\r\n >\r\n {/* Arrow */}\r\n {hasChildren ? (\r\n <span\r\n className={`ui-tree-arrow ${isOpen ? 'open' : ''}`}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n toggleNode(node.id);\r\n }}\r\n >\r\n ▶\r\n </span>\r\n ) : (\r\n <span className=\"ui-tree-arrow empty\">•</span>\r\n )}\r\n\r\n {/* Icon */}\r\n {node.icon && <span className=\"ui-tree-icon\">{node.icon}</span>}\r\n\r\n <span className=\"ui-tree-label\">{node.label}</span>\r\n </div>\r\n\r\n {/* Children */}\r\n {hasChildren && isOpen && node.children && (\r\n <div role=\"group\">\r\n {node.children.map((child) => renderNode(child, node, depth + 1))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className={`ui-treeview ${className}`} role=\"tree\">\r\n {data.map((node) => renderNode(node, undefined, 0))}\r\n </div>\r\n );\r\n}\r\n"],"names":["TreeView","data","selectedId","onSelect","className","openNodes","setOpenNodes","useState","activeNode","setActiveNode","toggleNode","id","prev","next","flatten","nodes","acc","node","isOpen","handleKeyDown","parent","key","hasChildren","firstChild","flat","index","n","nextIndex","nextNode","renderNode","depth","isSelected","isActive","jsxs","e","jsx","child"],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx as a, jsxs as m } from "react/jsx-runtime";
|
|
2
|
+
import { useState as w } from "react";
|
|
3
|
+
/* empty css */
|
|
4
|
+
function b({
|
|
5
|
+
data: p,
|
|
6
|
+
selectedId: A,
|
|
7
|
+
onSelect: h,
|
|
8
|
+
className: N = ""
|
|
9
|
+
}) {
|
|
10
|
+
const [d, g] = w(/* @__PURE__ */ new Set()), [y, o] = w(null), f = (i) => {
|
|
11
|
+
g((e) => {
|
|
12
|
+
const r = new Set(e);
|
|
13
|
+
return r.has(i) ? r.delete(i) : r.add(i), r;
|
|
14
|
+
});
|
|
15
|
+
}, u = (i, e = []) => (i.forEach((r) => {
|
|
16
|
+
e.push(r);
|
|
17
|
+
const t = d.has(r.id);
|
|
18
|
+
r.children && r.children.length > 0 && t && u(r.children, e);
|
|
19
|
+
}), e), x = (i, e, r) => {
|
|
20
|
+
const t = i.key;
|
|
21
|
+
if (t === "Enter" || t === " ") {
|
|
22
|
+
i.preventDefault(), h && h(e.id);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (t === "ArrowLeft") {
|
|
26
|
+
i.preventDefault();
|
|
27
|
+
const s = e.children && e.children.length > 0, n = d.has(e.id);
|
|
28
|
+
if (s && n) {
|
|
29
|
+
f(e.id);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
r && o(r.id);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (t === "ArrowRight") {
|
|
36
|
+
i.preventDefault();
|
|
37
|
+
const s = e.children && e.children.length > 0, n = d.has(e.id);
|
|
38
|
+
if (s && !n) {
|
|
39
|
+
f(e.id);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (s && n) {
|
|
43
|
+
const c = Array.isArray(e.children) && e.children.length > 0 ? e.children[0] : void 0;
|
|
44
|
+
c && o(c.id);
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (t === "ArrowUp" || t === "ArrowDown") {
|
|
49
|
+
i.preventDefault();
|
|
50
|
+
const s = u(p), n = s.findIndex((C) => C.id === e.id);
|
|
51
|
+
if (n === -1) return;
|
|
52
|
+
const c = t === "ArrowUp" ? n - 1 : n + 1, l = s[c];
|
|
53
|
+
l && o(l.id);
|
|
54
|
+
}
|
|
55
|
+
}, v = (i, e, r) => {
|
|
56
|
+
const t = d.has(i.id), s = i.id === A, n = i.id === y, c = Array.isArray(i.children) && i.children.length > 0;
|
|
57
|
+
return /* @__PURE__ */ m("div", { children: [
|
|
58
|
+
/* @__PURE__ */ m(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
role: "treeitem",
|
|
62
|
+
"aria-expanded": c ? t : void 0,
|
|
63
|
+
tabIndex: n ? 0 : -1,
|
|
64
|
+
className: [
|
|
65
|
+
"ui-tree-node",
|
|
66
|
+
s ? "selected" : "",
|
|
67
|
+
n ? "active" : ""
|
|
68
|
+
].filter(Boolean).join(" "),
|
|
69
|
+
style: { paddingLeft: r * 16 },
|
|
70
|
+
onClick: () => {
|
|
71
|
+
h && h(i.id), o(i.id), Array.isArray(i.children) && i.children.length > 0 && f(i.id);
|
|
72
|
+
},
|
|
73
|
+
onKeyDown: (l) => x(l, i, e),
|
|
74
|
+
children: [
|
|
75
|
+
c ? /* @__PURE__ */ a(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: `ui-tree-arrow ${t ? "open" : ""}`,
|
|
79
|
+
onClick: (l) => {
|
|
80
|
+
l.stopPropagation(), f(i.id);
|
|
81
|
+
},
|
|
82
|
+
children: "▶"
|
|
83
|
+
}
|
|
84
|
+
) : /* @__PURE__ */ a("span", { className: "ui-tree-arrow empty", children: "•" }),
|
|
85
|
+
i.icon && /* @__PURE__ */ a("span", { className: "ui-tree-icon", children: i.icon }),
|
|
86
|
+
/* @__PURE__ */ a("span", { className: "ui-tree-label", children: i.label })
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
c && t && i.children && /* @__PURE__ */ a("div", { role: "group", children: i.children.map((l) => v(l, i, r + 1)) })
|
|
91
|
+
] }, i.id);
|
|
92
|
+
};
|
|
93
|
+
return /* @__PURE__ */ a("div", { className: `ui-treeview ${N}`, role: "tree", children: p.map((i) => v(i, void 0, 0)) });
|
|
94
|
+
}
|
|
95
|
+
export {
|
|
96
|
+
b as TreeView
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=TreeView.js.map
|