@crewlethq/ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1714 -14
- package/dist/Accordion/Accordion.d.ts +54 -0
- package/dist/Accordion/index.d.ts +4 -0
- package/dist/Accordion/index.js +6 -0
- package/dist/Accordion-ZI2WLD5C.css +87 -0
- package/dist/AddPill/AddPill.d.ts +114 -0
- package/dist/AddPill/index.d.ts +3 -0
- package/dist/AddPill/index.js +3 -0
- package/dist/AddPill-DFWXYLIQ.css +434 -0
- package/dist/Announcer/Announcer.d.ts +15 -0
- package/dist/Announcer/index.d.ts +2 -0
- package/dist/Announcer/index.js +3 -0
- package/dist/AppShell/AppShell.d.ts +193 -0
- package/dist/AppShell/index.d.ts +3 -0
- package/dist/AppShell/index.js +6 -0
- package/dist/AppShell-NVE6LHNI.css +395 -0
- package/dist/Avatar/Avatar.d.ts +104 -0
- package/dist/Avatar/index.d.ts +3 -0
- package/dist/Avatar/index.js +2 -0
- package/dist/Avatar-P2KRQM2B.css +156 -0
- package/dist/BrandLockup/BrandLockup.d.ts +41 -0
- package/dist/BrandLockup/index.d.ts +3 -0
- package/dist/BrandLockup/index.js +2 -0
- package/dist/BrandLockup-6ISDEHPJ.css +108 -0
- package/dist/Button/Button.d.ts +88 -0
- package/dist/Button/index.d.ts +3 -0
- package/dist/Button/index.js +3 -0
- package/dist/Button-D4J6B4MA.css +302 -0
- package/dist/CalendarGrid/CalendarGrid.d.ts +87 -0
- package/dist/CalendarGrid/index.d.ts +3 -0
- package/dist/CalendarGrid/index.js +2 -0
- package/dist/CalendarGrid-V6TQ5QKS.css +128 -0
- package/dist/Callout/Callout.d.ts +47 -0
- package/dist/Callout/index.d.ts +3 -0
- package/dist/Callout/index.js +2 -0
- package/dist/Callout-S7QDWHDL.css +111 -0
- package/dist/Canvas/Canvas.d.ts +234 -0
- package/dist/Canvas/geometry.d.ts +249 -0
- package/dist/Canvas/index.d.ts +5 -0
- package/dist/Canvas/index.js +8 -0
- package/dist/Canvas/layerNode.d.ts +20 -0
- package/dist/Canvas-Q6JETCWR.css +315 -0
- package/dist/Card/Card.d.ts +142 -0
- package/dist/Card/headerSlot.d.ts +65 -0
- package/dist/Card/index.d.ts +5 -0
- package/dist/Card/index.js +6 -0
- package/dist/Card-AHX3Q2JD.css +428 -0
- package/dist/Charts/ActivityStrip.d.ts +45 -0
- package/dist/Charts/BarList.d.ts +51 -0
- package/dist/Charts/Legend.d.ts +32 -0
- package/dist/Charts/StackedBar.d.ts +38 -0
- package/dist/Charts/TimeSeries.d.ts +92 -0
- package/dist/Charts/dataColor.d.ts +20 -0
- package/dist/Charts/index.d.ts +12 -0
- package/dist/Charts/index.js +3 -0
- package/dist/Charts-D7G2BSXH.css +277 -0
- package/dist/Checkbox/Checkbox.d.ts +45 -0
- package/dist/Checkbox/index.d.ts +3 -0
- package/dist/Checkbox/index.js +2 -0
- package/dist/Checkbox-VGW26YLQ.css +111 -0
- package/dist/CodeBlock/CodeBlock.d.ts +60 -0
- package/dist/CodeBlock/index.d.ts +3 -0
- package/dist/CodeBlock/index.js +7 -0
- package/dist/CodeBlock-U2W6NNVC.css +153 -0
- package/dist/Combobox/Combobox.d.ts +89 -0
- package/dist/Combobox/index.d.ts +3 -0
- package/dist/Combobox/index.js +8 -0
- package/dist/Combobox-4FUVYIE7.css +80 -0
- package/dist/CommandPalette/CommandPalette.d.ts +77 -0
- package/dist/CommandPalette/index.d.ts +3 -0
- package/dist/CommandPalette/index.js +11 -0
- package/dist/CommandPalette-CSJDUCQA.css +115 -0
- package/dist/Container/Container.d.ts +17 -0
- package/dist/Container/index.d.ts +3 -0
- package/dist/Container/index.js +2 -0
- package/dist/Container-3TSKMGNI.css +52 -0
- package/dist/Copyable/CopyButton.d.ts +54 -0
- package/dist/Copyable/Copyable.d.ts +34 -0
- package/dist/Copyable/index.d.ts +5 -0
- package/dist/Copyable/index.js +6 -0
- package/dist/Copyable-5PNRFOLS.css +125 -0
- package/dist/Count/Count.d.ts +24 -0
- package/dist/Count/index.d.ts +3 -0
- package/dist/Count/index.js +3 -0
- package/dist/Count-ZVCJ6VPD.css +20 -0
- package/dist/DataTable/CopyableCell.d.ts +12 -0
- package/dist/DataTable/DataTable.d.ts +615 -0
- package/dist/DataTable/RowActionsMenu.d.ts +7 -0
- package/dist/DataTable/index.d.ts +7 -0
- package/dist/DataTable/index.js +14 -0
- package/dist/DataTable-ITNACQ2X.css +2020 -0
- package/dist/DataView/DataView.d.ts +109 -0
- package/dist/DataView/DataViewToolbar.d.ts +87 -0
- package/dist/DataView/FilterAxisBar.d.ts +103 -0
- package/dist/DataView/columns.d.ts +35 -0
- package/dist/DataView/filters.d.ts +184 -0
- package/dist/DataView/index.d.ts +11 -0
- package/dist/DataView/index.js +25 -0
- package/dist/DataView-256YF32J.css +441 -0
- package/dist/DateTimePicker/DateTimePicker.d.ts +91 -0
- package/dist/DateTimePicker/index.d.ts +3 -0
- package/dist/DateTimePicker/index.js +9 -0
- package/dist/DateTimePicker-22VNXRWC.css +199 -0
- package/dist/DescriptionList/DescriptionList.d.ts +36 -0
- package/dist/DescriptionList/index.d.ts +3 -0
- package/dist/DescriptionList/index.js +2 -0
- package/dist/DescriptionList-YYY3V3O6.css +59 -0
- package/dist/DiffList/DiffList.d.ts +47 -0
- package/dist/DiffList/index.d.ts +3 -0
- package/dist/DiffList/index.js +3 -0
- package/dist/DiffList-3EX64AAE.css +94 -0
- package/dist/Disclosure/Disclosure.d.ts +56 -0
- package/dist/Disclosure/anatomy.d.ts +43 -0
- package/dist/Disclosure/index.d.ts +5 -0
- package/dist/Disclosure/index.js +6 -0
- package/dist/Disclosure-VKBJJIZ7.css +176 -0
- package/dist/EmptyState/EmptyState.d.ts +39 -0
- package/dist/EmptyState/index.d.ts +3 -0
- package/dist/EmptyState/index.js +3 -0
- package/dist/EmptyState-C6HRBGT7.css +73 -0
- package/dist/EmptyValue/EmptyValue.d.ts +31 -0
- package/dist/EmptyValue/index.d.ts +3 -0
- package/dist/EmptyValue/index.js +3 -0
- package/dist/EmptyValue-4B6ODXHT.css +12 -0
- package/dist/EntityChip/EntityChip.d.ts +40 -0
- package/dist/EntityChip/index.d.ts +3 -0
- package/dist/EntityChip/index.js +3 -0
- package/dist/EntityChip-LUCPZBBG.css +64 -0
- package/dist/ErrorBoundary/ErrorBoundary.d.ts +58 -0
- package/dist/ErrorBoundary/index.d.ts +3 -0
- package/dist/ErrorBoundary/index.js +4 -0
- package/dist/ErrorBoundary-ME36CQTA.css +59 -0
- package/dist/Eyebrow/Eyebrow.d.ts +18 -0
- package/dist/Eyebrow/index.d.ts +3 -0
- package/dist/Eyebrow/index.js +2 -0
- package/dist/Eyebrow-5NREGHQH.css +46 -0
- package/dist/FilterChip/FilterChip.d.ts +68 -0
- package/dist/FilterChip/index.d.ts +3 -0
- package/dist/FilterChip/index.js +3 -0
- package/dist/FilterChip-GTGLLOXE.css +107 -0
- package/dist/Fullscreen/index.d.ts +2 -0
- package/dist/Fullscreen/index.js +1 -0
- package/dist/Fullscreen/useFullscreen.d.ts +32 -0
- package/dist/IconButton/IconButton.d.ts +45 -0
- package/dist/IconButton/index.d.ts +3 -0
- package/dist/IconButton/index.js +3 -0
- package/dist/IconButton-VQGNMJDI.css +158 -0
- package/dist/ImageUpload/ImageUpload.d.ts +37 -0
- package/dist/ImageUpload/index.d.ts +3 -0
- package/dist/ImageUpload/index.js +3 -0
- package/dist/ImageUpload-HKFIZR6D.css +193 -0
- package/dist/InlineCode/InlineCode.d.ts +37 -0
- package/dist/InlineCode/index.d.ts +3 -0
- package/dist/InlineCode/index.js +2 -0
- package/dist/InlineCode-6WSR5COL.css +65 -0
- package/dist/Input/FormField.d.ts +61 -0
- package/dist/Input/FormRow.d.ts +6 -0
- package/dist/Input/FormSection.d.ts +28 -0
- package/dist/Input/Input.d.ts +98 -0
- package/dist/Input/Label.d.ts +31 -0
- package/dist/Input/ReadOnlyField.d.ts +30 -0
- package/dist/Input/Textarea.d.ts +16 -0
- package/dist/Input/index.d.ts +15 -0
- package/dist/Input/index.js +5 -0
- package/dist/Input-2PU5CPKK.css +616 -0
- package/dist/Kbd/Kbd.d.ts +40 -0
- package/dist/Kbd/index.d.ts +3 -0
- package/dist/Kbd/index.js +3 -0
- package/dist/Kbd-W66MXQI5.css +61 -0
- package/dist/Layer/LayerHost.d.ts +23 -0
- package/dist/Layer/index.d.ts +7 -0
- package/dist/Layer/index.js +3 -0
- package/dist/Layer/place.d.ts +63 -0
- package/dist/Layer/stack.d.ts +159 -0
- package/dist/Layer-NAFSGCFA.css +23 -0
- package/dist/Layout/Layout.d.ts +104 -0
- package/dist/Layout/index.d.ts +3 -0
- package/dist/Layout/index.js +2 -0
- package/dist/Layout-2ZCV3IGF.css +171 -0
- package/dist/Link/Link.d.ts +45 -0
- package/dist/Link/index.d.ts +3 -0
- package/dist/Link/index.js +3 -0
- package/dist/Link-6BEFNMN2.css +80 -0
- package/dist/List/List.d.ts +73 -0
- package/dist/List/index.d.ts +3 -0
- package/dist/List/index.js +3 -0
- package/dist/List-XTHESXLR.css +161 -0
- package/dist/ListInput/ListInput.d.ts +68 -0
- package/dist/ListInput/index.d.ts +3 -0
- package/dist/ListInput/index.js +10 -0
- package/dist/ListInput-O7LJKOIG.css +147 -0
- package/dist/Listbox/index.d.ts +5 -0
- package/dist/Listbox/index.js +2 -0
- package/dist/Listbox/useListbox.d.ts +97 -0
- package/dist/Listbox/useOptionKeys.d.ts +64 -0
- package/dist/Listbox-X2DOTSQA.css +110 -0
- package/dist/Menu/Menu.d.ts +118 -0
- package/dist/Menu/index.d.ts +3 -0
- package/dist/Menu/index.js +7 -0
- package/dist/Menu-6DE7I66I.css +222 -0
- package/dist/Meter/Meter.d.ts +49 -0
- package/dist/Meter/index.d.ts +3 -0
- package/dist/Meter/index.js +3 -0
- package/dist/Meter-SKOOXQBC.css +87 -0
- package/dist/Modal/ConfirmModal.d.ts +74 -0
- package/dist/Modal/Modal.d.ts +154 -0
- package/dist/Modal/index.d.ts +5 -0
- package/dist/Modal/index.js +8 -0
- package/dist/Modal-XYQJ4BL6.css +484 -0
- package/dist/NewItemsNotice/NewItemsNotice.d.ts +28 -0
- package/dist/NewItemsNotice/index.d.ts +3 -0
- package/dist/NewItemsNotice/index.js +4 -0
- package/dist/NewItemsNotice-T4DSSPVV.css +60 -0
- package/dist/OrgLabel/OrgLabel.d.ts +117 -0
- package/dist/OrgLabel/index.d.ts +3 -0
- package/dist/OrgLabel/index.js +2 -0
- package/dist/OrgLabel-D7U6QJZD.css +293 -0
- package/dist/OrgNode/OrgNode.d.ts +103 -0
- package/dist/OrgNode/index.d.ts +3 -0
- package/dist/OrgNode/index.js +3 -0
- package/dist/OrgNode-BT7T2Q2X.css +214 -0
- package/dist/OrgTable/OrgTable.d.ts +113 -0
- package/dist/OrgTable/index.d.ts +3 -0
- package/dist/OrgTable/index.js +11 -0
- package/dist/OrgTable-VWMFC3TB.css +360 -0
- package/dist/PageHeader/PageHeader.d.ts +35 -0
- package/dist/PageHeader/index.d.ts +3 -0
- package/dist/PageHeader/index.js +3 -0
- package/dist/PageHeader-6EYWQXRE.css +88 -0
- package/dist/Popover/Popover.d.ts +91 -0
- package/dist/Popover/index.d.ts +3 -0
- package/dist/Popover/index.js +4 -0
- package/dist/Popover-WJGCF3ZQ.css +185 -0
- package/dist/PricingCard/PricingCard.d.ts +56 -0
- package/dist/PricingCard/index.d.ts +3 -0
- package/dist/PricingCard/index.js +4 -0
- package/dist/PricingCard-JFI7RYXP.css +278 -0
- package/dist/Prose/Prose.d.ts +33 -0
- package/dist/Prose/index.d.ts +3 -0
- package/dist/Prose/index.js +2 -0
- package/dist/Prose-BTXNFT2Q.css +99 -0
- package/dist/RelativeTime/RelativeTime.d.ts +31 -0
- package/dist/RelativeTime/clock.d.ts +9 -0
- package/dist/RelativeTime/format.d.ts +38 -0
- package/dist/RelativeTime/index.d.ts +6 -0
- package/dist/RelativeTime/index.js +4 -0
- package/dist/RelativeTime-EBAQPGO2.css +10 -0
- package/dist/SearchTrigger/SearchTrigger.d.ts +29 -0
- package/dist/SearchTrigger/index.d.ts +3 -0
- package/dist/SearchTrigger/index.js +2 -0
- package/dist/SearchTrigger-QXOYAUUY.css +79 -0
- package/dist/Section/Section.d.ts +41 -0
- package/dist/Section/index.d.ts +3 -0
- package/dist/Section/index.js +3 -0
- package/dist/Section-QRUPRIQ2.css +127 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +68 -0
- package/dist/SegmentedControl/index.d.ts +4 -0
- package/dist/SegmentedControl/index.js +5 -0
- package/dist/SegmentedControl-X3BI3XU4.css +68 -0
- package/dist/Select/Select.d.ts +138 -0
- package/dist/Select/index.d.ts +3 -0
- package/dist/Select/index.js +5 -0
- package/dist/Select-2X77FSWR.css +350 -0
- package/dist/Shortcut/index.d.ts +2 -0
- package/dist/Shortcut/index.js +4 -0
- package/dist/Shortcut/useShortcut.d.ts +68 -0
- package/dist/SidebarNav/SidebarNav.d.ts +117 -0
- package/dist/SidebarNav/index.d.ts +3 -0
- package/dist/SidebarNav/index.js +3 -0
- package/dist/SidebarNav-QGSFKZYA.css +319 -0
- package/dist/Skeleton/Skeleton.d.ts +50 -0
- package/dist/Skeleton/index.d.ts +3 -0
- package/dist/Skeleton/index.js +3 -0
- package/dist/Skeleton-V735HRGM.css +421 -0
- package/dist/StatCard/StatCard.d.ts +56 -0
- package/dist/StatCard/index.d.ts +3 -0
- package/dist/StatCard/index.js +3 -0
- package/dist/StatCard-KYPKZUWX.css +111 -0
- package/dist/StatGroup/StatGroup.d.ts +20 -0
- package/dist/StatGroup/index.d.ts +3 -0
- package/dist/StatGroup/index.js +2 -0
- package/dist/StatGroup-TGB6AEKM.css +80 -0
- package/dist/StatusDot/StatusDot.d.ts +25 -0
- package/dist/StatusDot/index.d.ts +3 -0
- package/dist/StatusDot/index.js +2 -0
- package/dist/StatusDot-HA2L2FSX.css +84 -0
- package/dist/Switch/Switch.d.ts +38 -0
- package/dist/Switch/index.d.ts +3 -0
- package/dist/Switch/index.js +2 -0
- package/dist/Switch-U4OWK4CL.css +169 -0
- package/dist/Table/Table.d.ts +51 -0
- package/dist/Table/index.d.ts +3 -0
- package/dist/Table/index.js +3 -0
- package/dist/Table-MDOLVUAW.css +159 -0
- package/dist/Tabs/Tabs.d.ts +97 -0
- package/dist/Tabs/index.d.ts +3 -0
- package/dist/Tabs/index.js +4 -0
- package/dist/Tabs/roving.d.ts +36 -0
- package/dist/Tabs-VLICJFVB.css +275 -0
- package/dist/Tag/Tag.d.ts +107 -0
- package/dist/Tag/index.d.ts +3 -0
- package/dist/Tag/index.js +3 -0
- package/dist/Tag-VNZEYLB6.css +406 -0
- package/dist/TagGroup/TagGroup.d.ts +41 -0
- package/dist/TagGroup/index.d.ts +3 -0
- package/dist/TagGroup/index.js +4 -0
- package/dist/TagGroup-APC2EFH4.css +75 -0
- package/dist/TagsInput/TagsInput.d.ts +112 -0
- package/dist/TagsInput/index.d.ts +3 -0
- package/dist/TagsInput/index.js +10 -0
- package/dist/TagsInput-W4P36PRJ.css +168 -0
- package/dist/Text/Text.d.ts +67 -0
- package/dist/Text/index.d.ts +3 -0
- package/dist/Text/index.js +2 -0
- package/dist/Text-XIPYYZX2.css +154 -0
- package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +47 -0
- package/dist/ThemeSwitcher/index.d.ts +4 -0
- package/dist/ThemeSwitcher/index.js +6 -0
- package/dist/ThemeSwitcher/preferences.d.ts +51 -0
- package/dist/TimeWindowPicker/TimeWindowPicker.d.ts +231 -0
- package/dist/TimeWindowPicker/index.d.ts +3 -0
- package/dist/TimeWindowPicker/index.js +13 -0
- package/dist/TimeWindowPicker/mask.d.ts +82 -0
- package/dist/TimeWindowPicker-7I7KWCMU.css +403 -0
- package/dist/Timeline/Timeline.d.ts +51 -0
- package/dist/Timeline/index.d.ts +3 -0
- package/dist/Timeline/index.js +3 -0
- package/dist/Timeline-27SYKOFX.css +144 -0
- package/dist/Toaster/Toaster.d.ts +108 -0
- package/dist/Toaster/index.d.ts +3 -0
- package/dist/Toaster/index.js +5 -0
- package/dist/Toaster-NVDCEIP5.css +306 -0
- package/dist/Toolbar/Toolbar.d.ts +62 -0
- package/dist/Toolbar/index.d.ts +3 -0
- package/dist/Toolbar/index.js +4 -0
- package/dist/Toolbar-IP6LXN45.css +48 -0
- package/dist/Tooltip/Tooltip.d.ts +51 -0
- package/dist/Tooltip/index.d.ts +3 -0
- package/dist/Tooltip/index.js +4 -0
- package/dist/Tooltip-LKQF7CE4.css +71 -0
- package/dist/Tree/index.d.ts +8 -0
- package/dist/Tree/index.js +1 -0
- package/dist/Tree/layout.d.ts +160 -0
- package/dist/Tree/model.d.ts +110 -0
- package/dist/Tree/useMeasuredSizes.d.ts +61 -0
- package/dist/Tree/useTreeState.d.ts +89 -0
- package/dist/TreeCanvas/TreeCanvas.d.ts +384 -0
- package/dist/TreeCanvas/index.d.ts +3 -0
- package/dist/TreeCanvas/index.js +10 -0
- package/dist/TreeCanvas/motion.d.ts +59 -0
- package/dist/TreeCanvas-WBNQPHC7.css +1098 -0
- package/dist/TreeGrid/TreeGrid.d.ts +142 -0
- package/dist/TreeGrid/index.d.ts +3 -0
- package/dist/TreeGrid/index.js +8 -0
- package/dist/TreeGrid-NSW7VMOX.css +132 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +23 -0
- package/dist/VisuallyHidden/index.d.ts +3 -0
- package/dist/VisuallyHidden/index.js +2 -0
- package/dist/VisuallyHidden-L552H7OA.css +21 -0
- package/dist/chunk-22O7LAW2.js +41 -0
- package/dist/chunk-23DHIMJA.js +38 -0
- package/dist/chunk-2EOKFKHX.js +263 -0
- package/dist/chunk-2PRH365R.js +74 -0
- package/dist/chunk-2ZQMA2WB.js +57 -0
- package/dist/chunk-3CZ7XAVY.js +139 -0
- package/dist/chunk-3EYF6HKB.js +135 -0
- package/dist/chunk-3ZP55QZE.js +40 -0
- package/dist/chunk-53DVJCVW.js +14 -0
- package/dist/chunk-5C5YMZQU.js +51 -0
- package/dist/chunk-5EKIWVOR.js +132 -0
- package/dist/chunk-5IMACPJS.js +495 -0
- package/dist/chunk-5KPQ6D7N.js +54 -0
- package/dist/chunk-5SDBMKUO.js +297 -0
- package/dist/chunk-5WS6L6FA.js +114 -0
- package/dist/chunk-7EM5T4ME.js +39 -0
- package/dist/chunk-7FZ53WDJ.js +163 -0
- package/dist/chunk-7HPRF5XN.js +525 -0
- package/dist/chunk-7RPGY3JE.js +43 -0
- package/dist/chunk-A2UXBCLO.js +48 -0
- package/dist/chunk-ARMRX2YV.js +96 -0
- package/dist/chunk-AV2DXAEL.js +27 -0
- package/dist/chunk-BHHIIK3M.js +17 -0
- package/dist/chunk-BZFWDIV6.js +9 -0
- package/dist/chunk-BZYDZBAN.js +123 -0
- package/dist/chunk-CMEE37QJ.js +628 -0
- package/dist/chunk-D3OADIM6.js +112 -0
- package/dist/chunk-DD5BBGBE.js +162 -0
- package/dist/chunk-EHMQQHYR.js +1652 -0
- package/dist/chunk-EN6K2IFA.js +256 -0
- package/dist/chunk-EPOOQZYA.js +118 -0
- package/dist/chunk-ESCO4XYW.js +144 -0
- package/dist/chunk-EUCC37WY.js +14 -0
- package/dist/chunk-EV6IMYJ6.js +62 -0
- package/dist/chunk-F27EPQ7D.js +68 -0
- package/dist/chunk-F4PJZ4ED.js +245 -0
- package/dist/chunk-F6OE5FH3.js +49 -0
- package/dist/chunk-FBZAKNSX.js +263 -0
- package/dist/chunk-FEFTGVMF.js +46 -0
- package/dist/chunk-G2QFRTJ2.js +823 -0
- package/dist/chunk-GHYY2WPF.js +907 -0
- package/dist/chunk-GTOUGQQK.js +147 -0
- package/dist/chunk-GUIF6Q6N.js +143 -0
- package/dist/chunk-GXQ3B46I.js +216 -0
- package/dist/chunk-H4FBTAYS.js +130 -0
- package/dist/chunk-HOXGBLEY.js +37 -0
- package/dist/chunk-HQNHV7D6.js +54 -0
- package/dist/chunk-HTDFCRJZ.js +92 -0
- package/dist/chunk-HZ5XZNPS.js +98 -0
- package/dist/chunk-IAJLHVUA.js +28 -0
- package/dist/chunk-IJ7QXNIJ.js +1 -0
- package/dist/chunk-ITHXJHBB.js +280 -0
- package/dist/chunk-JCSA3XVH.js +32 -0
- package/dist/chunk-KLJCCMF3.js +97 -0
- package/dist/chunk-LGCPQIOZ.js +49 -0
- package/dist/chunk-LWKJQTOM.js +77 -0
- package/dist/chunk-MNAXYY3R.js +215 -0
- package/dist/chunk-NN62JQLR.js +29 -0
- package/dist/chunk-NPZY6YYL.js +251 -0
- package/dist/chunk-NTRZGNEX.js +529 -0
- package/dist/chunk-O6232G37.js +273 -0
- package/dist/chunk-O67VF5MS.js +58 -0
- package/dist/chunk-ODEQTPFM.js +6 -0
- package/dist/chunk-PNFASD6F.js +98 -0
- package/dist/chunk-PQADV6P6.js +19 -0
- package/dist/chunk-PZSWF74H.js +15 -0
- package/dist/chunk-Q4ZPPART.js +26 -0
- package/dist/chunk-QNCVHRZL.js +17 -0
- package/dist/chunk-QVE4GJAT.js +15 -0
- package/dist/chunk-QYOFACSP.js +36 -0
- package/dist/chunk-RA2ULG6H.js +29 -0
- package/dist/chunk-RDGD7Z7I.js +350 -0
- package/dist/chunk-RK4XPHVG.js +16 -0
- package/dist/chunk-RSAQOKH3.js +38 -0
- package/dist/chunk-S2XHHEW4.js +84 -0
- package/dist/chunk-S4GZWSKR.js +137 -0
- package/dist/chunk-SFZOKW2G.js +52 -0
- package/dist/chunk-T7FKOJKW.js +221 -0
- package/dist/chunk-UG46QBLT.js +325 -0
- package/dist/chunk-UOGSZKLT.js +134 -0
- package/dist/chunk-V2XMNLMS.js +52 -0
- package/dist/chunk-V663QU4R.js +51 -0
- package/dist/chunk-W4ENKCXJ.js +40 -0
- package/dist/chunk-W5J7R5EB.js +107 -0
- package/dist/chunk-WNI2WSJF.js +27 -0
- package/dist/chunk-XDTYBF2F.js +36 -0
- package/dist/chunk-XN4JBAN3.js +32 -0
- package/dist/chunk-XV6WRMBC.js +211 -0
- package/dist/chunk-YLYOWZ4V.js +33 -0
- package/dist/chunk-YMWONFSI.js +170 -0
- package/dist/chunk-ZCR6YGQ4.js +1 -0
- package/dist/generated/index.d.ts +83 -0
- package/dist/generated/index.js +91 -0
- package/dist/index.d.ts +1 -1217
- package/dist/index.js +91 -4518
- package/dist/styles.css +14841 -4274
- package/dist/utils/cx.d.ts +10 -0
- package/dist/utils/headingLevel.d.ts +16 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/tone.d.ts +25 -0
- package/dist/utils/useClipboard.d.ts +30 -0
- package/package.json +18 -10
- package/scripts/bundle-css.mjs +25 -0
- package/scripts/check-css-literals.mjs +166 -0
- package/scripts/check-css-variables.mjs +184 -0
- package/scripts/check-css.mjs +27 -0
- package/scripts/css-source.mjs +67 -0
- package/scripts/write-barrel.mjs +60 -0
- package/dist/Accordion-NIMJQIOI.css +0 -88
- package/dist/AppShell-ZW3NSFBP.css +0 -51
- package/dist/Avatar-V6NG6Q45.css +0 -67
- package/dist/Button-XGCTXXYP.css +0 -174
- package/dist/Callout-LEGDIMAM.css +0 -52
- package/dist/Card-BOZGBML7.css +0 -86
- package/dist/Checkbox-OCUICIIZ.css +0 -58
- package/dist/CodeBlock-IEMBNIQC.css +0 -90
- package/dist/Container-LTKBA2FW.css +0 -21
- package/dist/Copyable-IB57OTHZ.css +0 -123
- package/dist/DataTable-3GALZUW2.css +0 -1593
- package/dist/DateTimePicker-NMSSGVPK.css +0 -312
- package/dist/Eyebrow-AVBORAS2.css +0 -30
- package/dist/IconButton-GB4PJDG2.css +0 -82
- package/dist/ImageUpload-3HQDF2KC.css +0 -158
- package/dist/Input-ZHUTN7CU.css +0 -210
- package/dist/Kbd-Q77CDZY7.css +0 -23
- package/dist/Modal-FJVG66S4.css +0 -138
- package/dist/Popover-FUFULUE2.css +0 -123
- package/dist/PricingCard-NKYV3JHA.css +0 -238
- package/dist/Section-665ZIPG6.css +0 -20
- package/dist/Select-GPRF7PRB.css +0 -294
- package/dist/Skeleton-3WEFLRDN.css +0 -378
- package/dist/StatCard-RTJIVTRB.css +0 -50
- package/dist/Table-AR3TRY2E.css +0 -89
- package/dist/Tabs-XZ4JIH3E.css +0 -153
- package/dist/Tag-R5QDJLYJ.css +0 -163
- package/dist/TimeWindowPicker-L3G5Q7UT.css +0 -629
- package/dist/Toaster-2O65VOR4.css +0 -264
|
@@ -0,0 +1,1652 @@
|
|
|
1
|
+
import { Menu } from './chunk-FBZAKNSX.js';
|
|
2
|
+
import { EmptyValue } from './chunk-EUCC37WY.js';
|
|
3
|
+
import { Modal } from './chunk-2EOKFKHX.js';
|
|
4
|
+
import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
|
|
5
|
+
import { Checkbox } from './chunk-2PRH365R.js';
|
|
6
|
+
import { useClipboard } from './chunk-V663QU4R.js';
|
|
7
|
+
import { IconButton } from './chunk-F27EPQ7D.js';
|
|
8
|
+
import { Button } from './chunk-BZYDZBAN.js';
|
|
9
|
+
import { VisuallyHidden } from './chunk-BZFWDIV6.js';
|
|
10
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
11
|
+
import './DataTable-ITNACQ2X.css';
|
|
12
|
+
import React, { useState, useCallback, useMemo, useRef, useLayoutEffect, useEffect, useId } from 'react';
|
|
13
|
+
import { createPortal } from 'react-dom';
|
|
14
|
+
import { CheckGlyph, ErrorGlyph, ContentCopyGlyph, KeyboardDoubleArrowLeftGlyph, ChevronLeftGlyph, ChevronRightGlyph, KeyboardDoubleArrowRightGlyph, SettingsGlyph, DragIndicatorGlyph, KeyboardArrowUpGlyph, KeyboardArrowDownGlyph, DeleteGlyph, ArrowUpwardGlyph, ArrowDownwardGlyph, UnfoldMoreGlyph, SettingsBackupRestoreGlyph } from '@crewlethq/icons/glyphs';
|
|
15
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
16
|
+
|
|
17
|
+
var CopyableCell = ({
|
|
18
|
+
value,
|
|
19
|
+
children,
|
|
20
|
+
ariaLabel,
|
|
21
|
+
copiedLabel = "Copied",
|
|
22
|
+
failedLabel = "Copy failed"
|
|
23
|
+
}) => {
|
|
24
|
+
const text = value === void 0 || value === null ? "" : String(value);
|
|
25
|
+
const clipboard = useClipboard();
|
|
26
|
+
const onCopy = (event) => {
|
|
27
|
+
event.stopPropagation();
|
|
28
|
+
if (!text) return;
|
|
29
|
+
void clipboard.copy(text);
|
|
30
|
+
};
|
|
31
|
+
return /* @__PURE__ */ jsxs("span", { className: "crewlet-data-table__copy-cell", children: [
|
|
32
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-data-table__copy-cell-value", children }),
|
|
33
|
+
text && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
"button",
|
|
36
|
+
{
|
|
37
|
+
type: "button",
|
|
38
|
+
className: `crewlet-data-table__copy-cell-button${clipboard.state === "copied" ? " is-copied" : ""}${clipboard.state === "failed" ? " is-failed" : ""}`,
|
|
39
|
+
onClick: onCopy,
|
|
40
|
+
"aria-label": ariaLabel || "Copy to clipboard",
|
|
41
|
+
title: ariaLabel || "Copy to clipboard",
|
|
42
|
+
children: clipboard.state === "copied" ? /* @__PURE__ */ jsx(CheckGlyph, { size: "sm" }) : clipboard.state === "failed" ? /* @__PURE__ */ jsx(ErrorGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(ContentCopyGlyph, { size: "sm" })
|
|
43
|
+
}
|
|
44
|
+
),
|
|
45
|
+
/* @__PURE__ */ jsx("span", { role: "status", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: clipboard.state === "copied" ? copiedLabel : clipboard.state === "failed" ? failedLabel : "" }) })
|
|
46
|
+
] })
|
|
47
|
+
] });
|
|
48
|
+
};
|
|
49
|
+
function entriesFor(action, index) {
|
|
50
|
+
const key = `${index}:${action.label}`;
|
|
51
|
+
const item = {
|
|
52
|
+
key,
|
|
53
|
+
label: action.label,
|
|
54
|
+
icon: action.icon,
|
|
55
|
+
// An action with nothing to do still draws, because `disabled` is what
|
|
56
|
+
// says why it cannot be pressed; an empty handler is never called.
|
|
57
|
+
onSelect: action.onClick ?? (() => {
|
|
58
|
+
}),
|
|
59
|
+
disabled: action.disabled,
|
|
60
|
+
danger: action.danger,
|
|
61
|
+
description: action.description
|
|
62
|
+
};
|
|
63
|
+
return [
|
|
64
|
+
...action.divider === "before" ? [{ kind: "separator", key: `${key}:before` }] : [],
|
|
65
|
+
item,
|
|
66
|
+
...action.divider === "after" ? [{ kind: "separator", key: `${key}:after` }] : []
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
var RowActionsMenu = ({ actions, label = "Row actions" }) => {
|
|
70
|
+
const items = (actions || []).filter((action) => !!action && action.visible !== false).flatMap(entriesFor);
|
|
71
|
+
if (items.length === 0) return null;
|
|
72
|
+
return /* @__PURE__ */ jsx(Menu, { label, items, align: "end", className: "crewlet-data-table__row-actions" });
|
|
73
|
+
};
|
|
74
|
+
function cellValue(row, key) {
|
|
75
|
+
return row?.[key];
|
|
76
|
+
}
|
|
77
|
+
function readStored(storageKey, name) {
|
|
78
|
+
if (!storageKey) return null;
|
|
79
|
+
try {
|
|
80
|
+
return globalThis.localStorage?.getItem(`${storageKey}_${name}`) ?? null;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function writeStored(storageKey, name, value) {
|
|
86
|
+
if (!storageKey) return;
|
|
87
|
+
try {
|
|
88
|
+
globalThis.localStorage?.setItem(`${storageKey}_${name}`, value);
|
|
89
|
+
} catch {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function removeStored(storageKey, name) {
|
|
93
|
+
if (!storageKey) return;
|
|
94
|
+
try {
|
|
95
|
+
globalThis.localStorage?.removeItem(`${storageKey}_${name}`);
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function readStoredJson(storageKey, name, valid) {
|
|
100
|
+
const raw = readStored(storageKey, name);
|
|
101
|
+
if (raw === null) return null;
|
|
102
|
+
try {
|
|
103
|
+
const parsed = JSON.parse(raw);
|
|
104
|
+
return valid(parsed) ? parsed : null;
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function isPlainObject(value) {
|
|
110
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
111
|
+
}
|
|
112
|
+
function isNumberRecord(value) {
|
|
113
|
+
return isPlainObject(value) && Object.values(value).every((entry) => typeof entry === "number");
|
|
114
|
+
}
|
|
115
|
+
function isBooleanRecord(value) {
|
|
116
|
+
return isPlainObject(value) && Object.values(value).every((entry) => typeof entry === "boolean");
|
|
117
|
+
}
|
|
118
|
+
function isStringArray(value) {
|
|
119
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
120
|
+
}
|
|
121
|
+
function isAbsent(value) {
|
|
122
|
+
return value === null || value === void 0 || typeof value === "number" && Number.isNaN(value);
|
|
123
|
+
}
|
|
124
|
+
function compareValues(a, b) {
|
|
125
|
+
if (typeof a === "number" && typeof b === "number") return a < b ? -1 : a > b ? 1 : 0;
|
|
126
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
|
|
127
|
+
return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
|
|
128
|
+
}
|
|
129
|
+
function reconcileOrder(current, declared) {
|
|
130
|
+
const known = new Set(declared);
|
|
131
|
+
const kept = current.filter((key) => known.has(key));
|
|
132
|
+
if (kept.length === declared.length) return kept;
|
|
133
|
+
const out = [...kept];
|
|
134
|
+
declared.forEach((key, index) => {
|
|
135
|
+
if (out.includes(key)) return;
|
|
136
|
+
let at = 0;
|
|
137
|
+
for (let earlier = index - 1; earlier >= 0; earlier -= 1) {
|
|
138
|
+
const where = out.indexOf(declared[earlier]);
|
|
139
|
+
if (where >= 0) {
|
|
140
|
+
at = where + 1;
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
out.splice(at, 0, key);
|
|
145
|
+
});
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
var ALL_ITEMS = "all";
|
|
149
|
+
var DATA_TABLE_LABELS = {
|
|
150
|
+
settings: "Table settings",
|
|
151
|
+
/*
|
|
152
|
+
* THE WORDS THE PRODUCT ALREADY SHIPS. The frame's title, its column
|
|
153
|
+
* section, that section's hint and the reset button are the four strings an
|
|
154
|
+
* operator reads on every table in the product today, so they are spelt here
|
|
155
|
+
* exactly as they are spelt there. `Reset to Default` is also the more
|
|
156
|
+
* accurate of the two: the button puts the page size, the wrapping, the sort
|
|
157
|
+
* and the widths back as well as the columns, which `Reset columns` says
|
|
158
|
+
* less than half of.
|
|
159
|
+
*/
|
|
160
|
+
resetColumns: "Reset to Default",
|
|
161
|
+
resetConfirmed: "Settings reset to default",
|
|
162
|
+
cancel: "Cancel",
|
|
163
|
+
apply: "Apply",
|
|
164
|
+
settingsTitle: "Table Settings",
|
|
165
|
+
itemsPerPage: "Items per page",
|
|
166
|
+
allItems: "All",
|
|
167
|
+
allItemsCount: (rows) => `${rows.toLocaleString()} rows`,
|
|
168
|
+
wrapLines: "Wrap lines",
|
|
169
|
+
wrapLinesHint: "Wrap the content of a cell instead of truncating it.",
|
|
170
|
+
columnsSection: "Column Order & Visibility",
|
|
171
|
+
/*
|
|
172
|
+
* THE HINT IS THE POINTER'S, AND THE KEYBOARD'S PATH IS ON THE CONTROLS
|
|
173
|
+
* THEMSELVES. Naming Move up and Move down here read as the only way in for
|
|
174
|
+
* somebody who could see the row, and said nothing to a reader who cannot:
|
|
175
|
+
* a paragraph above a list is not where a screen reader looks for what a
|
|
176
|
+
* control does. The handle's own name and `reorderHint` carry it now, so
|
|
177
|
+
* the keyboard path arrives at the control it belongs to.
|
|
178
|
+
*/
|
|
179
|
+
columnsHint: "Drag to reorder, check/uncheck to show/hide",
|
|
180
|
+
moveUp: (column) => `Move ${column} up`,
|
|
181
|
+
moveDown: (column) => `Move ${column} down`,
|
|
182
|
+
atTop: (column) => `${column} is already first`,
|
|
183
|
+
atBottom: (column) => `${column} is already last`,
|
|
184
|
+
reorder: (column) => `Reorder ${column}`,
|
|
185
|
+
reorderHint: "Press the up or down arrow key to move this column.",
|
|
186
|
+
columnMoved: (column, position, of) => `${column} moved to position ${position} of ${of}`,
|
|
187
|
+
columnAlwaysShown: "This column is always shown.",
|
|
188
|
+
columnLastShown: "At least one column stays shown.",
|
|
189
|
+
pagination: "Pagination",
|
|
190
|
+
firstPage: "First page",
|
|
191
|
+
previousPage: "Previous page",
|
|
192
|
+
nextPage: "Next page",
|
|
193
|
+
lastPage: "Last page",
|
|
194
|
+
page: (page, of) => `Page ${page} of ${of}`,
|
|
195
|
+
pageRange: (from, to, total) => `Rows ${from} to ${to} of ${total}`,
|
|
196
|
+
expandRow: "Expand row",
|
|
197
|
+
collapseRow: "Collapse row",
|
|
198
|
+
expandAll: "Expand all rows",
|
|
199
|
+
collapseAll: "Collapse all rows",
|
|
200
|
+
resize: (column) => `Resize ${column}`,
|
|
201
|
+
resizeWidth: (pixels) => `${pixels} pixels`,
|
|
202
|
+
copyCell: (column) => `Copy ${column}`,
|
|
203
|
+
rowActions: "Row actions",
|
|
204
|
+
actions: "Actions",
|
|
205
|
+
archivedRow: (label) => `This row is ${label}`,
|
|
206
|
+
absent: "Not reported",
|
|
207
|
+
loading: "Loading rows",
|
|
208
|
+
tone: { info: "Active", warning: "Needs attention", danger: "Failed" }
|
|
209
|
+
};
|
|
210
|
+
var DataTable = ({
|
|
211
|
+
data = [],
|
|
212
|
+
columns = {},
|
|
213
|
+
storageKey,
|
|
214
|
+
defaultColumnOrder = null,
|
|
215
|
+
columnOrder: columnOrderProp,
|
|
216
|
+
onColumnOrderChange,
|
|
217
|
+
defaultItemsPerPage = 10,
|
|
218
|
+
itemsPerPage: itemsPerPageProp,
|
|
219
|
+
onItemsPerPageChange,
|
|
220
|
+
page: pageProp,
|
|
221
|
+
onPageChange,
|
|
222
|
+
pageCount,
|
|
223
|
+
minColumnWidth = 80,
|
|
224
|
+
resizable = true,
|
|
225
|
+
itemsPerPageOptions = [5, 10, 20, 50, 100],
|
|
226
|
+
onRowAction = null,
|
|
227
|
+
actionLabel = "Delete",
|
|
228
|
+
actionIcon = /* @__PURE__ */ jsx(DeleteGlyph, { size: "md" }),
|
|
229
|
+
getRowKey,
|
|
230
|
+
rowKey,
|
|
231
|
+
emptyMessage = "No data available",
|
|
232
|
+
endMessage,
|
|
233
|
+
showActions = true,
|
|
234
|
+
className = "",
|
|
235
|
+
variant = "default",
|
|
236
|
+
density = "compact",
|
|
237
|
+
maxBodyHeight,
|
|
238
|
+
sort: sortProp,
|
|
239
|
+
onSortChange,
|
|
240
|
+
defaultSort = null,
|
|
241
|
+
sortCycle = "asc-desc-none",
|
|
242
|
+
stableOrder = false,
|
|
243
|
+
rowActions,
|
|
244
|
+
archivedPredicate,
|
|
245
|
+
archivedLabel = "archived",
|
|
246
|
+
loading = false,
|
|
247
|
+
skeletonRows = 5,
|
|
248
|
+
error = null,
|
|
249
|
+
paginated = true,
|
|
250
|
+
showSettings = true,
|
|
251
|
+
onRowClick,
|
|
252
|
+
getRowHref,
|
|
253
|
+
rowTone,
|
|
254
|
+
isSelected,
|
|
255
|
+
renderAccessoryRow,
|
|
256
|
+
renderToolbar,
|
|
257
|
+
renderFilterBar,
|
|
258
|
+
onClearFilters,
|
|
259
|
+
filtersActive = false,
|
|
260
|
+
clearFiltersLabel = "Clear filters",
|
|
261
|
+
filterKey,
|
|
262
|
+
visibleColumns: visibleColumnsProp,
|
|
263
|
+
onVisibleColumnsChange,
|
|
264
|
+
renderExpandedRow,
|
|
265
|
+
defaultExpandedKey = null,
|
|
266
|
+
hasMore = false,
|
|
267
|
+
onLoadMore,
|
|
268
|
+
loadingMore = false,
|
|
269
|
+
loadMoreLabel = "Load more",
|
|
270
|
+
title,
|
|
271
|
+
description,
|
|
272
|
+
icon,
|
|
273
|
+
defaultWrapLines,
|
|
274
|
+
labels: labelOverrides
|
|
275
|
+
}) => {
|
|
276
|
+
const labels = labelOverrides ? { ...DATA_TABLE_LABELS, ...labelOverrides, tone: { ...DATA_TABLE_LABELS.tone, ...labelOverrides.tone } } : DATA_TABLE_LABELS;
|
|
277
|
+
const effectiveDefaultWrapLines = defaultWrapLines ?? true;
|
|
278
|
+
const resolveRowKey = (row) => {
|
|
279
|
+
if (getRowKey) return getRowKey(row);
|
|
280
|
+
if (rowKey) return cellValue(row, rowKey);
|
|
281
|
+
return cellValue(row, "id");
|
|
282
|
+
};
|
|
283
|
+
const isCompact = variant === "compact";
|
|
284
|
+
const hasActionColumn = !!rowActions || showActions && !!onRowAction;
|
|
285
|
+
const expandable = !!renderExpandedRow;
|
|
286
|
+
const settingsEnabled = showSettings;
|
|
287
|
+
const paginationEnabled = paginated;
|
|
288
|
+
const settingsInHeader = settingsEnabled && !isCompact;
|
|
289
|
+
const hasChromeColumn = hasActionColumn || settingsInHeader;
|
|
290
|
+
const generateDefaultColumnWidths = () => {
|
|
291
|
+
const widths = {};
|
|
292
|
+
Object.keys(columns).forEach((key) => {
|
|
293
|
+
const col = columns[key];
|
|
294
|
+
const rawExplicit = col?.width ?? col?.defaultWidth;
|
|
295
|
+
let px = null;
|
|
296
|
+
if (rawExplicit != null) {
|
|
297
|
+
const parsed = typeof rawExplicit === "number" ? rawExplicit : parseInt(String(rawExplicit), 10);
|
|
298
|
+
if (Number.isFinite(parsed)) px = parsed;
|
|
299
|
+
}
|
|
300
|
+
if (px == null) {
|
|
301
|
+
const labelStr = typeof col?.label === "string" ? col.label : key;
|
|
302
|
+
const estimated = Math.ceil(labelStr.length * 7.5) + 56;
|
|
303
|
+
px = Math.max(120, estimated);
|
|
304
|
+
}
|
|
305
|
+
widths[key] = Math.max(minColumnWidth, px);
|
|
306
|
+
});
|
|
307
|
+
if (showActions) {
|
|
308
|
+
widths.__actions = 60;
|
|
309
|
+
}
|
|
310
|
+
return widths;
|
|
311
|
+
};
|
|
312
|
+
const generateDefaultVisibleColumns = () => {
|
|
313
|
+
const visible = {};
|
|
314
|
+
Object.keys(columns).forEach((key) => {
|
|
315
|
+
visible[key] = columns[key]?.defaultVisible !== false;
|
|
316
|
+
});
|
|
317
|
+
return visible;
|
|
318
|
+
};
|
|
319
|
+
const generateDefaultColumnOrder = () => {
|
|
320
|
+
return defaultColumnOrder || Object.keys(columns);
|
|
321
|
+
};
|
|
322
|
+
const defaultColumnWidths = generateDefaultColumnWidths();
|
|
323
|
+
const defaultVisibleColumns = generateDefaultVisibleColumns();
|
|
324
|
+
const defaultOrder = generateDefaultColumnOrder();
|
|
325
|
+
const readResizedColumns = () => {
|
|
326
|
+
const saved = readStoredJson(storageKey, "resizedColumns", isNumberRecord);
|
|
327
|
+
if (!saved) return {};
|
|
328
|
+
const kept = {};
|
|
329
|
+
Object.entries(saved).forEach(([key, px]) => {
|
|
330
|
+
if (!Number.isFinite(px)) return;
|
|
331
|
+
const col = columns[key];
|
|
332
|
+
if (!col || col.width != null) return;
|
|
333
|
+
kept[key] = Math.max(minColumnWidth, px);
|
|
334
|
+
});
|
|
335
|
+
return kept;
|
|
336
|
+
};
|
|
337
|
+
const [columnWidths, setColumnWidths] = useState(
|
|
338
|
+
() => ({ ...defaultColumnWidths, ...readResizedColumns() })
|
|
339
|
+
);
|
|
340
|
+
const [resizedColumns, setResizedColumns] = useState(
|
|
341
|
+
() => Object.fromEntries(Object.keys(readResizedColumns()).map((key) => [key, true]))
|
|
342
|
+
);
|
|
343
|
+
const markResized = useCallback((columnKey) => {
|
|
344
|
+
setResizedColumns((was) => was[columnKey] ? was : { ...was, [columnKey]: true });
|
|
345
|
+
}, []);
|
|
346
|
+
const [ownItemsPerPage, setOwnItemsPerPage] = useState(() => {
|
|
347
|
+
if (itemsPerPageProp !== void 0) return defaultItemsPerPage;
|
|
348
|
+
const saved = readStored(storageKey, "itemsPerPage");
|
|
349
|
+
if (saved === ALL_ITEMS) return ALL_ITEMS;
|
|
350
|
+
const count = Number.parseInt(saved ?? "", 10);
|
|
351
|
+
return Number.isFinite(count) && count > 0 ? count : defaultItemsPerPage;
|
|
352
|
+
});
|
|
353
|
+
const itemsPerPage = itemsPerPageProp ?? ownItemsPerPage;
|
|
354
|
+
const commitItemsPerPage = (next) => {
|
|
355
|
+
if (itemsPerPageProp === void 0) setOwnItemsPerPage(next);
|
|
356
|
+
onItemsPerPageChange?.(next);
|
|
357
|
+
};
|
|
358
|
+
const [ownVisibleColumns, setOwnVisibleColumns] = useState(() => {
|
|
359
|
+
const saved = visibleColumnsProp === void 0 ? readStoredJson(storageKey, "visibleColumns", isBooleanRecord) : null;
|
|
360
|
+
if (!saved) return defaultVisibleColumns;
|
|
361
|
+
const valid = {};
|
|
362
|
+
Object.keys(columns).forEach((key) => {
|
|
363
|
+
valid[key] = Object.prototype.hasOwnProperty.call(saved, key) ? saved[key] : columns[key]?.defaultVisible !== false;
|
|
364
|
+
});
|
|
365
|
+
return valid;
|
|
366
|
+
});
|
|
367
|
+
const visibleColumns = visibleColumnsProp ?? ownVisibleColumns;
|
|
368
|
+
const isColumnVisible = (key) => visibleColumns[key] !== false;
|
|
369
|
+
const commitVisibleColumns = (next) => {
|
|
370
|
+
if (visibleColumnsProp === void 0) setOwnVisibleColumns(next);
|
|
371
|
+
onVisibleColumnsChange?.(next);
|
|
372
|
+
};
|
|
373
|
+
const [ownColumnOrder, setOwnColumnOrder] = useState(() => {
|
|
374
|
+
const saved = columnOrderProp === void 0 ? readStoredJson(storageKey, "columnOrder", isStringArray) : null;
|
|
375
|
+
if (!saved) return defaultOrder;
|
|
376
|
+
const validOrder = saved.filter((key) => Object.prototype.hasOwnProperty.call(columns, key));
|
|
377
|
+
const newColumns = defaultOrder.filter((key) => !validOrder.includes(key));
|
|
378
|
+
return validOrder.length > 0 ? [...validOrder, ...newColumns] : defaultOrder;
|
|
379
|
+
});
|
|
380
|
+
const declaredOrder = defaultOrder.join("\0");
|
|
381
|
+
const arrangedOrder = columnOrderProp ?? ownColumnOrder;
|
|
382
|
+
const columnOrder = useMemo(
|
|
383
|
+
() => reconcileOrder(arrangedOrder, declaredOrder === "" ? [] : declaredOrder.split("\0")),
|
|
384
|
+
[arrangedOrder, declaredOrder]
|
|
385
|
+
);
|
|
386
|
+
const commitColumnOrder = (next) => {
|
|
387
|
+
if (columnOrderProp === void 0) setOwnColumnOrder(next);
|
|
388
|
+
onColumnOrderChange?.(next);
|
|
389
|
+
};
|
|
390
|
+
const [sortConfig, setSortConfig] = useState(
|
|
391
|
+
() => ({ key: defaultSort?.key ?? null, direction: defaultSort?.direction ?? null })
|
|
392
|
+
);
|
|
393
|
+
const [tableSettingsOpen, setTableSettingsOpen] = useState(false);
|
|
394
|
+
const [wrapLines, setWrapLines] = useState(() => {
|
|
395
|
+
if (!storageKey) return effectiveDefaultWrapLines;
|
|
396
|
+
const saved = readStored(storageKey, "wrapLines");
|
|
397
|
+
return saved == null ? effectiveDefaultWrapLines : saved === "true";
|
|
398
|
+
});
|
|
399
|
+
const [draftItemsPerPage, setDraftItemsPerPage] = useState(0);
|
|
400
|
+
const [draftWrapLines, setDraftWrapLines] = useState(effectiveDefaultWrapLines);
|
|
401
|
+
const [draftColumnWidths, setDraftColumnWidths] = useState({});
|
|
402
|
+
const [draftVisibleColumns, setDraftVisibleColumns] = useState({});
|
|
403
|
+
const [draftColumnOrder, setDraftColumnOrder] = useState([]);
|
|
404
|
+
const [draftSortConfig, setDraftSortConfig] = useState(
|
|
405
|
+
{ key: null, direction: null }
|
|
406
|
+
);
|
|
407
|
+
const [resetConfirmed, setResetConfirmed] = useState(false);
|
|
408
|
+
const resetConfirmTimer = useRef(null);
|
|
409
|
+
const pendingFitOnApplyRef = useRef(false);
|
|
410
|
+
const [expandedKeys, setExpandedKeys] = useState(
|
|
411
|
+
() => defaultExpandedKey != null ? /* @__PURE__ */ new Set([defaultExpandedKey]) : /* @__PURE__ */ new Set()
|
|
412
|
+
);
|
|
413
|
+
const toggleExpanded = (key) => {
|
|
414
|
+
setExpandedKeys((prev) => {
|
|
415
|
+
const next = new Set(prev);
|
|
416
|
+
if (next.has(key)) {
|
|
417
|
+
next.delete(key);
|
|
418
|
+
} else {
|
|
419
|
+
next.add(key);
|
|
420
|
+
}
|
|
421
|
+
return next;
|
|
422
|
+
});
|
|
423
|
+
};
|
|
424
|
+
const [draggedColumn, setDraggedColumn] = useState(null);
|
|
425
|
+
const [resizingColumn, setResizingColumn] = useState(null);
|
|
426
|
+
const [startX, setStartX] = useState(0);
|
|
427
|
+
const [startWidth, setStartWidth] = useState(0);
|
|
428
|
+
const dragTimeoutRef = useRef(null);
|
|
429
|
+
const settingsButtonRef = useRef(null);
|
|
430
|
+
const scrollRef = useRef(null);
|
|
431
|
+
const [fitRequests, setFitRequests] = useState(0);
|
|
432
|
+
const requestFit = useCallback(() => setFitRequests((n) => n + 1), []);
|
|
433
|
+
const emptyCellRef = useRef(null);
|
|
434
|
+
const [emptySaid, setEmptySaid] = useState("");
|
|
435
|
+
const resetToDefault = () => {
|
|
436
|
+
const newDefaultWidths = generateDefaultColumnWidths();
|
|
437
|
+
const newDefaultVisible = generateDefaultVisibleColumns();
|
|
438
|
+
const newDefaultOrder = generateDefaultColumnOrder();
|
|
439
|
+
setColumnWidths(newDefaultWidths);
|
|
440
|
+
setResizedColumns({});
|
|
441
|
+
commitVisibleColumns(newDefaultVisible);
|
|
442
|
+
commitColumnOrder(newDefaultOrder);
|
|
443
|
+
commitItemsPerPage(defaultItemsPerPage);
|
|
444
|
+
setSortConfig({ key: defaultSort?.key ?? null, direction: defaultSort?.direction ?? null });
|
|
445
|
+
requestFit();
|
|
446
|
+
for (const name of ["resizedColumns", "visibleColumns", "columnOrder", "itemsPerPage"]) {
|
|
447
|
+
removeStored(storageKey, name);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
const fitInputs = useRef({
|
|
451
|
+
columns,
|
|
452
|
+
columnOrder,
|
|
453
|
+
visibleColumns,
|
|
454
|
+
columnWidths,
|
|
455
|
+
resizedColumns,
|
|
456
|
+
expandable,
|
|
457
|
+
hasChromeColumn,
|
|
458
|
+
isCompact,
|
|
459
|
+
minColumnWidth
|
|
460
|
+
});
|
|
461
|
+
fitInputs.current = {
|
|
462
|
+
columns,
|
|
463
|
+
columnOrder,
|
|
464
|
+
visibleColumns,
|
|
465
|
+
columnWidths,
|
|
466
|
+
resizedColumns,
|
|
467
|
+
expandable,
|
|
468
|
+
hasChromeColumn,
|
|
469
|
+
isCompact,
|
|
470
|
+
minColumnWidth
|
|
471
|
+
};
|
|
472
|
+
useLayoutEffect(() => {
|
|
473
|
+
const { columns: columns2, columnOrder: columnOrder2, visibleColumns: visibleColumns2, columnWidths: columnWidths2, resizedColumns: resizedColumns2, expandable: expandable2, hasChromeColumn: hasChromeColumn2, isCompact: isCompact2, minColumnWidth: minColumnWidth2 } = fitInputs.current;
|
|
474
|
+
const el = scrollRef.current;
|
|
475
|
+
if (!el) return;
|
|
476
|
+
const box = el.getBoundingClientRect();
|
|
477
|
+
const edges = Math.max(0, el.offsetWidth - el.clientWidth);
|
|
478
|
+
const measured = box.width - edges;
|
|
479
|
+
const containerWidth = measured > 0 ? Math.floor(measured) : el.clientWidth;
|
|
480
|
+
if (containerWidth <= 0) return;
|
|
481
|
+
const visibleAllKeys = columnOrder2.filter((key) => visibleColumns2[key] !== false);
|
|
482
|
+
const isFixedWidthColumn = (key) => {
|
|
483
|
+
const col = columns2[key];
|
|
484
|
+
if (!col) return false;
|
|
485
|
+
if (col.sticky === "right") return false;
|
|
486
|
+
return col.width != null || resizedColumns2[key] === true;
|
|
487
|
+
};
|
|
488
|
+
const visibleStickyKeys = visibleAllKeys.filter((key) => columns2[key]?.sticky === "right");
|
|
489
|
+
const visibleFixedKeys = visibleAllKeys.filter((key) => isFixedWidthColumn(key));
|
|
490
|
+
const visibleDataKeys = visibleAllKeys.filter(
|
|
491
|
+
(key) => columns2[key]?.sticky !== "right" && !isFixedWidthColumn(key)
|
|
492
|
+
);
|
|
493
|
+
if (visibleDataKeys.length === 0) return;
|
|
494
|
+
let chromeWidth = 0;
|
|
495
|
+
if (expandable2) chromeWidth += 32;
|
|
496
|
+
if (hasChromeColumn2) chromeWidth += isCompact2 ? 48 : columnWidths2.__actions ?? 60;
|
|
497
|
+
chromeWidth += visibleStickyKeys.reduce(
|
|
498
|
+
(sum, key) => sum + (columnWidths2[key] ?? minColumnWidth2),
|
|
499
|
+
0
|
|
500
|
+
);
|
|
501
|
+
chromeWidth += visibleFixedKeys.reduce(
|
|
502
|
+
(sum, key) => sum + (columnWidths2[key] ?? minColumnWidth2),
|
|
503
|
+
0
|
|
504
|
+
);
|
|
505
|
+
if (visibleStickyKeys.length > 0) {
|
|
506
|
+
const spacer = el.querySelector(".crewlet-data-table__th--spacer");
|
|
507
|
+
const drawn = spacer ? spacer.getBoundingClientRect().width : 0;
|
|
508
|
+
chromeWidth += drawn > 0 ? drawn : 24;
|
|
509
|
+
}
|
|
510
|
+
const dataTotal = visibleDataKeys.reduce(
|
|
511
|
+
(sum, key) => sum + (columnWidths2[key] ?? minColumnWidth2),
|
|
512
|
+
0
|
|
513
|
+
);
|
|
514
|
+
const available = containerWidth - chromeWidth;
|
|
515
|
+
const leftover = available - dataTotal;
|
|
516
|
+
if (leftover >= 0 && leftover <= 1) return;
|
|
517
|
+
const next = { ...columnWidths2 };
|
|
518
|
+
const widthOf = (key) => next[key] ?? minColumnWidth2;
|
|
519
|
+
visibleDataKeys.forEach((key) => {
|
|
520
|
+
next[key] = widthOf(key);
|
|
521
|
+
});
|
|
522
|
+
let outstanding = leftover;
|
|
523
|
+
let pool = visibleDataKeys;
|
|
524
|
+
while (pool.length > 0 && outstanding !== 0) {
|
|
525
|
+
const poolTotal = pool.reduce((sum, key) => sum + widthOf(key), 0);
|
|
526
|
+
if (poolTotal <= 0) break;
|
|
527
|
+
const roomLeft = [];
|
|
528
|
+
let moved = 0;
|
|
529
|
+
pool.forEach((key, idx) => {
|
|
530
|
+
const current = widthOf(key);
|
|
531
|
+
const rawShare = idx === pool.length - 1 ? outstanding - moved : Math.round(outstanding * (current / poolTotal));
|
|
532
|
+
const clamped = Math.max(minColumnWidth2, current + rawShare);
|
|
533
|
+
moved += clamped - current;
|
|
534
|
+
next[key] = clamped;
|
|
535
|
+
if (clamped > minColumnWidth2) roomLeft.push(key);
|
|
536
|
+
});
|
|
537
|
+
if (moved === 0) break;
|
|
538
|
+
outstanding -= moved;
|
|
539
|
+
pool = roomLeft;
|
|
540
|
+
}
|
|
541
|
+
setColumnWidths(next);
|
|
542
|
+
}, [fitRequests]);
|
|
543
|
+
const fittedColumnKeys = columnOrder.filter((key) => visibleColumns[key] !== false).join(",");
|
|
544
|
+
const fittedColumnKeysRef = useRef(fittedColumnKeys);
|
|
545
|
+
useLayoutEffect(() => {
|
|
546
|
+
if (fittedColumnKeysRef.current === fittedColumnKeys) return;
|
|
547
|
+
fittedColumnKeysRef.current = fittedColumnKeys;
|
|
548
|
+
requestFit();
|
|
549
|
+
}, [fittedColumnKeys, requestFit]);
|
|
550
|
+
useEffect(() => {
|
|
551
|
+
const el = scrollRef.current;
|
|
552
|
+
if (!el) return;
|
|
553
|
+
let lastWidth = el.clientWidth;
|
|
554
|
+
const observer = new ResizeObserver(() => {
|
|
555
|
+
const w = el.clientWidth;
|
|
556
|
+
if (w > 0 && w !== lastWidth) {
|
|
557
|
+
lastWidth = w;
|
|
558
|
+
requestFit();
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
observer.observe(el);
|
|
562
|
+
return () => observer.disconnect();
|
|
563
|
+
}, [requestFit]);
|
|
564
|
+
useEffect(() => {
|
|
565
|
+
const chosen = Object.keys(resizedColumns);
|
|
566
|
+
if (chosen.length === 0) {
|
|
567
|
+
removeStored(storageKey, "resizedColumns");
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
writeStored(storageKey, "resizedColumns", JSON.stringify(
|
|
571
|
+
Object.fromEntries(chosen.map((key) => [key, columnWidths[key] ?? minColumnWidth]))
|
|
572
|
+
));
|
|
573
|
+
}, [columnWidths, resizedColumns, storageKey, minColumnWidth]);
|
|
574
|
+
useEffect(() => {
|
|
575
|
+
removeStored(storageKey, "columnWidths");
|
|
576
|
+
}, [storageKey]);
|
|
577
|
+
useEffect(() => {
|
|
578
|
+
if (itemsPerPageProp === void 0) {
|
|
579
|
+
writeStored(storageKey, "itemsPerPage", String(ownItemsPerPage));
|
|
580
|
+
}
|
|
581
|
+
}, [ownItemsPerPage, storageKey, itemsPerPageProp]);
|
|
582
|
+
useEffect(() => {
|
|
583
|
+
if (visibleColumnsProp === void 0) {
|
|
584
|
+
writeStored(storageKey, "visibleColumns", JSON.stringify(ownVisibleColumns));
|
|
585
|
+
}
|
|
586
|
+
}, [ownVisibleColumns, storageKey, visibleColumnsProp]);
|
|
587
|
+
useEffect(() => {
|
|
588
|
+
if (columnOrderProp === void 0) {
|
|
589
|
+
writeStored(storageKey, "columnOrder", JSON.stringify(columnOrder));
|
|
590
|
+
}
|
|
591
|
+
}, [columnOrder, storageKey, columnOrderProp]);
|
|
592
|
+
useEffect(() => {
|
|
593
|
+
writeStored(storageKey, "wrapLines", String(wrapLines));
|
|
594
|
+
}, [wrapLines, storageKey]);
|
|
595
|
+
const handleMouseDownResize = (e, columnKey) => {
|
|
596
|
+
e.preventDefault();
|
|
597
|
+
e.stopPropagation();
|
|
598
|
+
setResizingColumn(columnKey);
|
|
599
|
+
setStartX(e.clientX);
|
|
600
|
+
setStartWidth(columnWidths[columnKey] ?? minColumnWidth);
|
|
601
|
+
};
|
|
602
|
+
const KEYBOARD_RESIZE_STEP = 16;
|
|
603
|
+
const resizerState = (columnKey) => {
|
|
604
|
+
const width = Math.round(columnWidths[columnKey] ?? minColumnWidth);
|
|
605
|
+
return {
|
|
606
|
+
role: "separator",
|
|
607
|
+
"aria-orientation": "vertical",
|
|
608
|
+
"aria-label": labels.resize(columnName(columnKey)),
|
|
609
|
+
"aria-valuenow": width,
|
|
610
|
+
"aria-valuemin": minColumnWidth,
|
|
611
|
+
"aria-valuetext": labels.resizeWidth(width)
|
|
612
|
+
};
|
|
613
|
+
};
|
|
614
|
+
const nudgeColumnWidth = (e, columnKey) => {
|
|
615
|
+
const step = e.key === "ArrowLeft" ? -KEYBOARD_RESIZE_STEP : e.key === "ArrowRight" ? KEYBOARD_RESIZE_STEP : 0;
|
|
616
|
+
if (step === 0) return;
|
|
617
|
+
e.preventDefault();
|
|
618
|
+
e.stopPropagation();
|
|
619
|
+
setColumnWidths((was) => ({
|
|
620
|
+
...was,
|
|
621
|
+
[columnKey]: Math.max(minColumnWidth, (was[columnKey] ?? minColumnWidth) + step)
|
|
622
|
+
}));
|
|
623
|
+
markResized(columnKey);
|
|
624
|
+
};
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
const handleMouseMove = (e) => {
|
|
627
|
+
if (resizingColumn) {
|
|
628
|
+
const diff = e.clientX - startX;
|
|
629
|
+
const newWidth = Math.max(minColumnWidth, startWidth + diff);
|
|
630
|
+
setColumnWidths((prev) => ({
|
|
631
|
+
...prev,
|
|
632
|
+
[resizingColumn]: newWidth
|
|
633
|
+
}));
|
|
634
|
+
markResized(resizingColumn);
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
const handleMouseUp = () => {
|
|
638
|
+
if (resizingColumn) {
|
|
639
|
+
setResizingColumn(null);
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
if (resizingColumn) {
|
|
643
|
+
document.body.classList.add("crewlet-data-table-resizing");
|
|
644
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
645
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
646
|
+
return () => {
|
|
647
|
+
document.body.classList.remove("crewlet-data-table-resizing");
|
|
648
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
649
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
return void 0;
|
|
653
|
+
}, [resizingColumn, startX, startWidth, minColumnWidth, markResized]);
|
|
654
|
+
const controlledSort = sortProp !== void 0;
|
|
655
|
+
const effectiveSort = controlledSort ? sortProp ? { key: sortProp.key, direction: sortProp.direction } : { key: null, direction: null } : sortConfig;
|
|
656
|
+
const handleSort = (columnKey) => {
|
|
657
|
+
const column = columns[columnKey];
|
|
658
|
+
if (column?.sortable === false) return;
|
|
659
|
+
const first = column?.firstDirection ?? "asc";
|
|
660
|
+
const other = first === "asc" ? "desc" : "asc";
|
|
661
|
+
let next;
|
|
662
|
+
if (effectiveSort.key !== columnKey || effectiveSort.direction === null) {
|
|
663
|
+
next = { key: columnKey, direction: first };
|
|
664
|
+
} else if (effectiveSort.direction === first) {
|
|
665
|
+
next = { key: columnKey, direction: other };
|
|
666
|
+
} else {
|
|
667
|
+
next = sortCycle === "asc-desc" ? { key: columnKey, direction: first } : null;
|
|
668
|
+
}
|
|
669
|
+
if (controlledSort) {
|
|
670
|
+
onSortChange?.(next);
|
|
671
|
+
} else {
|
|
672
|
+
setSortConfig({ key: next?.key ?? null, direction: next?.direction ?? null });
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
const heldOrder = useRef(null);
|
|
676
|
+
const getSortedData = () => {
|
|
677
|
+
const sortKey = effectiveSort.key;
|
|
678
|
+
const direction = effectiveSort.direction;
|
|
679
|
+
if (!sortKey || !direction) {
|
|
680
|
+
heldOrder.current = null;
|
|
681
|
+
return [...data];
|
|
682
|
+
}
|
|
683
|
+
const column = columns[sortKey];
|
|
684
|
+
const accessor = column?.sortValue ?? ((row) => cellValue(row, sortKey));
|
|
685
|
+
const sorted = data.map((row, index) => ({ row, index })).sort((left, right) => {
|
|
686
|
+
const a = accessor(left.row);
|
|
687
|
+
const b = accessor(right.row);
|
|
688
|
+
const aAbsent = isAbsent(a);
|
|
689
|
+
const bAbsent = isAbsent(b);
|
|
690
|
+
if (aAbsent || bAbsent) {
|
|
691
|
+
if (aAbsent && bAbsent) return left.index - right.index;
|
|
692
|
+
return aAbsent ? 1 : -1;
|
|
693
|
+
}
|
|
694
|
+
const difference = compareValues(a, b);
|
|
695
|
+
if (difference !== 0) return direction === "asc" ? difference : -difference;
|
|
696
|
+
return left.index - right.index;
|
|
697
|
+
}).map((decorated) => decorated.row);
|
|
698
|
+
if (!stableOrder) {
|
|
699
|
+
heldOrder.current = null;
|
|
700
|
+
return sorted;
|
|
701
|
+
}
|
|
702
|
+
const signature = `${sortKey}:${direction}`;
|
|
703
|
+
const held = heldOrder.current;
|
|
704
|
+
if (!held || held.signature !== signature) {
|
|
705
|
+
heldOrder.current = {
|
|
706
|
+
signature,
|
|
707
|
+
rank: new Map(sorted.map((row, index) => [resolveRowKey(row), index]))
|
|
708
|
+
};
|
|
709
|
+
return sorted;
|
|
710
|
+
}
|
|
711
|
+
const { rank } = held;
|
|
712
|
+
return sorted.map((row, index) => ({ row, index })).sort((left, right) => {
|
|
713
|
+
const a = rank.get(resolveRowKey(left.row));
|
|
714
|
+
const b = rank.get(resolveRowKey(right.row));
|
|
715
|
+
if (a === void 0 && b === void 0) return left.index - right.index;
|
|
716
|
+
if (a === void 0) return 1;
|
|
717
|
+
if (b === void 0) return -1;
|
|
718
|
+
return a - b;
|
|
719
|
+
}).map((decorated) => decorated.row);
|
|
720
|
+
};
|
|
721
|
+
const [ownPage, setOwnPage] = useState(1);
|
|
722
|
+
const currentPage = pageProp ?? ownPage;
|
|
723
|
+
const goToPage = (next) => {
|
|
724
|
+
if (pageProp === void 0) setOwnPage(next);
|
|
725
|
+
onPageChange?.(next);
|
|
726
|
+
};
|
|
727
|
+
const sortedDataMemo = getSortedData();
|
|
728
|
+
const totalPages = paginationEnabled ? itemsPerPage === ALL_ITEMS ? 1 : Math.max(1, Math.ceil(sortedDataMemo.length / Math.max(1, itemsPerPage))) : Math.max(1, pageCount ?? 1);
|
|
729
|
+
const pageBoundKnown = paginationEnabled || pageCount !== void 0;
|
|
730
|
+
useEffect(() => {
|
|
731
|
+
if (!pageBoundKnown) return;
|
|
732
|
+
if (currentPage > totalPages) goToPage(totalPages);
|
|
733
|
+
else if (currentPage < 1) goToPage(1);
|
|
734
|
+
}, [totalPages, currentPage, pageBoundKnown]);
|
|
735
|
+
const pagedFrom = useRef(null);
|
|
736
|
+
useEffect(() => {
|
|
737
|
+
const signature = `${effectiveSort.key}:${effectiveSort.direction}:${String(filterKey)}:${filtersActive}`;
|
|
738
|
+
const was = pagedFrom.current;
|
|
739
|
+
pagedFrom.current = signature;
|
|
740
|
+
if (was === null || was === signature) return;
|
|
741
|
+
if (currentPage !== 1) goToPage(1);
|
|
742
|
+
}, [effectiveSort.key, effectiveSort.direction, filterKey, filtersActive]);
|
|
743
|
+
const getDisplayedData = () => {
|
|
744
|
+
if (!paginationEnabled || itemsPerPage === ALL_ITEMS) return sortedDataMemo;
|
|
745
|
+
const start = (currentPage - 1) * itemsPerPage;
|
|
746
|
+
return sortedDataMemo.slice(start, start + itemsPerPage);
|
|
747
|
+
};
|
|
748
|
+
const columnName = (columnKey) => {
|
|
749
|
+
const label = columns[columnKey]?.label;
|
|
750
|
+
return typeof label === "string" && label.trim() !== "" ? label : columnKey;
|
|
751
|
+
};
|
|
752
|
+
const whyFixed = (columnKey, shown) => {
|
|
753
|
+
if (columns[columnKey]?.hideable === false) return labels.columnAlwaysShown;
|
|
754
|
+
const others = Object.keys(columns).filter((key) => key !== columnKey && shown[key] !== false);
|
|
755
|
+
return others.length === 0 ? labels.columnLastShown : null;
|
|
756
|
+
};
|
|
757
|
+
const [settingsSaid, setSettingsSaid] = useState("");
|
|
758
|
+
const instanceId = useId();
|
|
759
|
+
const reorderHintId = `${instanceId}-reorder`;
|
|
760
|
+
const columnLabelId = (columnKey) => (
|
|
761
|
+
// Whitespace out of the key: `aria-labelledby` is a SPACE-SEPARATED list
|
|
762
|
+
// of ids, so a column keyed "created at" would point the cell at two ids
|
|
763
|
+
// that do not exist and leave the header with no name at all.
|
|
764
|
+
`${instanceId}-col-${columnKey.replace(/\s+/g, "_")}`
|
|
765
|
+
);
|
|
766
|
+
const handleToggleColumn = (columnKey) => {
|
|
767
|
+
if (whyFixed(columnKey, draftVisibleColumns) !== null && draftVisibleColumns[columnKey] !== false) return;
|
|
768
|
+
setDraftVisibleColumns((prev) => ({ ...prev, [columnKey]: !prev[columnKey] }));
|
|
769
|
+
};
|
|
770
|
+
const moveColumn = (columnKey, by) => {
|
|
771
|
+
const at = draftColumnOrder.indexOf(columnKey);
|
|
772
|
+
const to = at + by;
|
|
773
|
+
if (at < 0 || to < 0 || to >= draftColumnOrder.length) return;
|
|
774
|
+
const next = [...draftColumnOrder];
|
|
775
|
+
next.splice(at, 1);
|
|
776
|
+
next.splice(to, 0, columnKey);
|
|
777
|
+
setDraftColumnOrder(next);
|
|
778
|
+
setSettingsSaid(labels.columnMoved(columnName(columnKey), to + 1, next.length));
|
|
779
|
+
};
|
|
780
|
+
const handleItemsPerPageChange = (value) => {
|
|
781
|
+
setDraftItemsPerPage(value);
|
|
782
|
+
};
|
|
783
|
+
const handleResetTableSettings = () => {
|
|
784
|
+
setDraftColumnWidths(generateDefaultColumnWidths());
|
|
785
|
+
setDraftItemsPerPage(defaultItemsPerPage);
|
|
786
|
+
setDraftVisibleColumns(generateDefaultVisibleColumns());
|
|
787
|
+
setDraftColumnOrder(generateDefaultColumnOrder());
|
|
788
|
+
setDraftWrapLines(effectiveDefaultWrapLines);
|
|
789
|
+
setDraftSortConfig({ key: defaultSort?.key ?? null, direction: defaultSort?.direction ?? null });
|
|
790
|
+
pendingFitOnApplyRef.current = true;
|
|
791
|
+
setResetConfirmed(true);
|
|
792
|
+
setSettingsSaid(labels.resetConfirmed);
|
|
793
|
+
if (resetConfirmTimer.current) clearTimeout(resetConfirmTimer.current);
|
|
794
|
+
resetConfirmTimer.current = setTimeout(() => setResetConfirmed(false), 1500);
|
|
795
|
+
};
|
|
796
|
+
const openTableSettings = () => {
|
|
797
|
+
setDraftColumnWidths({ ...columnWidths });
|
|
798
|
+
setDraftItemsPerPage(itemsPerPage);
|
|
799
|
+
setDraftVisibleColumns({ ...visibleColumns });
|
|
800
|
+
setDraftColumnOrder([...columnOrder]);
|
|
801
|
+
setDraftWrapLines(wrapLines);
|
|
802
|
+
setDraftSortConfig({ key: effectiveSort.key, direction: effectiveSort.direction });
|
|
803
|
+
setResetConfirmed(false);
|
|
804
|
+
setSettingsSaid("");
|
|
805
|
+
pendingFitOnApplyRef.current = false;
|
|
806
|
+
if (resetConfirmTimer.current) {
|
|
807
|
+
clearTimeout(resetConfirmTimer.current);
|
|
808
|
+
resetConfirmTimer.current = null;
|
|
809
|
+
}
|
|
810
|
+
setTableSettingsOpen(true);
|
|
811
|
+
};
|
|
812
|
+
const applyTableSettings = () => {
|
|
813
|
+
setColumnWidths(draftColumnWidths);
|
|
814
|
+
commitItemsPerPage(draftItemsPerPage);
|
|
815
|
+
commitVisibleColumns(draftVisibleColumns);
|
|
816
|
+
commitColumnOrder(draftColumnOrder);
|
|
817
|
+
setWrapLines(draftWrapLines);
|
|
818
|
+
if (controlledSort) {
|
|
819
|
+
onSortChange?.(
|
|
820
|
+
draftSortConfig.key && draftSortConfig.direction ? { key: draftSortConfig.key, direction: draftSortConfig.direction } : null
|
|
821
|
+
);
|
|
822
|
+
} else {
|
|
823
|
+
setSortConfig(draftSortConfig);
|
|
824
|
+
}
|
|
825
|
+
if (pendingFitOnApplyRef.current) {
|
|
826
|
+
pendingFitOnApplyRef.current = false;
|
|
827
|
+
setResizedColumns({});
|
|
828
|
+
requestFit();
|
|
829
|
+
}
|
|
830
|
+
setTableSettingsOpen(false);
|
|
831
|
+
};
|
|
832
|
+
const cancelTableSettings = () => {
|
|
833
|
+
pendingFitOnApplyRef.current = false;
|
|
834
|
+
setTableSettingsOpen(false);
|
|
835
|
+
};
|
|
836
|
+
const handleDragStart = (e, columnKey) => {
|
|
837
|
+
setDraggedColumn(columnKey);
|
|
838
|
+
e.dataTransfer.effectAllowed = "move";
|
|
839
|
+
};
|
|
840
|
+
const handleDragOver = (e, columnKey) => {
|
|
841
|
+
e.preventDefault();
|
|
842
|
+
e.dataTransfer.dropEffect = "move";
|
|
843
|
+
if (columnKey && draggedColumn && draggedColumn !== columnKey) {
|
|
844
|
+
if (dragTimeoutRef.current) {
|
|
845
|
+
clearTimeout(dragTimeoutRef.current);
|
|
846
|
+
}
|
|
847
|
+
dragTimeoutRef.current = setTimeout(() => {
|
|
848
|
+
setDraftColumnOrder((prev) => {
|
|
849
|
+
const newOrder = [...prev];
|
|
850
|
+
const draggedIndex = newOrder.indexOf(draggedColumn);
|
|
851
|
+
const targetIndex = newOrder.indexOf(columnKey);
|
|
852
|
+
if (draggedIndex === -1 || targetIndex === -1 || draggedIndex === targetIndex) {
|
|
853
|
+
return prev;
|
|
854
|
+
}
|
|
855
|
+
newOrder.splice(draggedIndex, 1);
|
|
856
|
+
newOrder.splice(targetIndex, 0, draggedColumn);
|
|
857
|
+
return newOrder;
|
|
858
|
+
});
|
|
859
|
+
}, 5);
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
const handleDrop = (e, _targetColumnKey) => {
|
|
863
|
+
e.preventDefault();
|
|
864
|
+
setDraggedColumn(null);
|
|
865
|
+
};
|
|
866
|
+
const handleDragEnd = () => {
|
|
867
|
+
if (dragTimeoutRef.current) {
|
|
868
|
+
clearTimeout(dragTimeoutRef.current);
|
|
869
|
+
}
|
|
870
|
+
setDraggedColumn(null);
|
|
871
|
+
};
|
|
872
|
+
const renderCellContent = (row, columnKey) => {
|
|
873
|
+
const column = columns[columnKey];
|
|
874
|
+
const value = cellValue(row, columnKey);
|
|
875
|
+
if (column?.render) {
|
|
876
|
+
return column.render(row, value);
|
|
877
|
+
}
|
|
878
|
+
return value !== null && value !== void 0 ? value : /* @__PURE__ */ jsx(EmptyValue, { label: labels.absent });
|
|
879
|
+
};
|
|
880
|
+
const columnClasses = (column) => cx(
|
|
881
|
+
column.align === "right" && "crewlet-data-table__cell--right",
|
|
882
|
+
column.align === "center" && "crewlet-data-table__cell--center",
|
|
883
|
+
column.shrink && "crewlet-data-table__cell--shrink"
|
|
884
|
+
);
|
|
885
|
+
const renderBodyCell = (row, columnKey, lead = {}) => {
|
|
886
|
+
const column = columns[columnKey];
|
|
887
|
+
if (!column) return null;
|
|
888
|
+
const style = {};
|
|
889
|
+
if (isCompact) {
|
|
890
|
+
if (columnWidths[columnKey] != null) {
|
|
891
|
+
style.width = `${columnWidths[columnKey]}px`;
|
|
892
|
+
}
|
|
893
|
+
} else {
|
|
894
|
+
style.width = `${columnWidths[columnKey]}px`;
|
|
895
|
+
}
|
|
896
|
+
const rendered = renderCellContent(row, columnKey);
|
|
897
|
+
let content = rendered;
|
|
898
|
+
if (lead.href) {
|
|
899
|
+
content = /* @__PURE__ */ jsx("a", { className: "crewlet-data-table__row-link", href: lead.href, children: content });
|
|
900
|
+
}
|
|
901
|
+
if (isCompact && column.copyable) {
|
|
902
|
+
const raw = column.copyValue ? column.copyValue(row) : cellValue(row, columnKey);
|
|
903
|
+
const copyText = raw !== void 0 && raw !== null ? String(raw) : "";
|
|
904
|
+
content = /* @__PURE__ */ jsx(CopyableCell, { value: copyText, ariaLabel: labels.copyCell(columnName(columnKey)), children: rendered });
|
|
905
|
+
}
|
|
906
|
+
const tdClassName = cx(
|
|
907
|
+
columnClasses(column),
|
|
908
|
+
column.mono && "crewlet-data-table__cell--mono",
|
|
909
|
+
isCompact && column.sticky === "right" && "crewlet-data-table__td--sticky-right"
|
|
910
|
+
);
|
|
911
|
+
return /* @__PURE__ */ jsxs("td", { style, className: tdClassName || void 0, children: [
|
|
912
|
+
lead.tone,
|
|
913
|
+
content
|
|
914
|
+
] }, columnKey);
|
|
915
|
+
};
|
|
916
|
+
const renderHeaderCell = (columnKey) => {
|
|
917
|
+
if (!isColumnVisible(columnKey)) return null;
|
|
918
|
+
const column = columns[columnKey];
|
|
919
|
+
if (!column) return null;
|
|
920
|
+
const isSortable = column.sortable !== false;
|
|
921
|
+
const isActive = effectiveSort.key === columnKey && effectiveSort.direction !== null;
|
|
922
|
+
const arrow = !isSortable ? null : isActive ? effectiveSort.direction === "asc" ? /* @__PURE__ */ jsx(ArrowUpwardGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(ArrowDownwardGlyph, { size: "sm" }) : /* @__PURE__ */ jsx(UnfoldMoreGlyph, { size: "sm" });
|
|
923
|
+
const ariaSort = isActive ? effectiveSort.direction === "asc" ? "ascending" : "descending" : void 0;
|
|
924
|
+
const isSticky = column.sticky === "right";
|
|
925
|
+
if (isCompact) {
|
|
926
|
+
const style = {};
|
|
927
|
+
if (columnWidths[columnKey] != null) {
|
|
928
|
+
style.width = `${columnWidths[columnKey]}px`;
|
|
929
|
+
}
|
|
930
|
+
const visibleStickyExists = columnOrder.some(
|
|
931
|
+
(k) => columns[k]?.sticky === "right" && isColumnVisible(k)
|
|
932
|
+
);
|
|
933
|
+
const suppressResizer = !resizable || isSticky || visibleStickyExists;
|
|
934
|
+
const resizer = suppressResizer ? null : /* @__PURE__ */ jsx(
|
|
935
|
+
"button",
|
|
936
|
+
{
|
|
937
|
+
type: "button",
|
|
938
|
+
className: "crewlet-data-table__resizer",
|
|
939
|
+
...resizerState(columnKey),
|
|
940
|
+
onMouseDown: (e) => {
|
|
941
|
+
e.stopPropagation();
|
|
942
|
+
handleMouseDownResize(e, columnKey);
|
|
943
|
+
},
|
|
944
|
+
onClick: (e) => e.stopPropagation(),
|
|
945
|
+
onKeyDown: (e) => nudgeColumnWidth(e, columnKey)
|
|
946
|
+
}
|
|
947
|
+
);
|
|
948
|
+
const thClass = cx(
|
|
949
|
+
columnClasses(column),
|
|
950
|
+
isSortable && "crewlet-data-table__th--sortable",
|
|
951
|
+
isSortable && isActive && "is-active",
|
|
952
|
+
isSticky && "crewlet-data-table__th--sticky-right"
|
|
953
|
+
);
|
|
954
|
+
return /* @__PURE__ */ jsxs(
|
|
955
|
+
"th",
|
|
956
|
+
{
|
|
957
|
+
scope: "col",
|
|
958
|
+
style,
|
|
959
|
+
"aria-sort": ariaSort,
|
|
960
|
+
"aria-labelledby": columnLabelId(columnKey),
|
|
961
|
+
className: thClass || void 0,
|
|
962
|
+
children: [
|
|
963
|
+
isSortable ? /* @__PURE__ */ jsxs(
|
|
964
|
+
"button",
|
|
965
|
+
{
|
|
966
|
+
type: "button",
|
|
967
|
+
className: "crewlet-data-table__sort-button",
|
|
968
|
+
onClick: () => handleSort(columnKey),
|
|
969
|
+
children: [
|
|
970
|
+
/* @__PURE__ */ jsx("span", { id: columnLabelId(columnKey), children: column.label }),
|
|
971
|
+
arrow
|
|
972
|
+
]
|
|
973
|
+
}
|
|
974
|
+
) : /* @__PURE__ */ jsx("span", { id: columnLabelId(columnKey), children: column.label }),
|
|
975
|
+
resizer
|
|
976
|
+
]
|
|
977
|
+
},
|
|
978
|
+
columnKey
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
return /* @__PURE__ */ jsxs(
|
|
982
|
+
"th",
|
|
983
|
+
{
|
|
984
|
+
scope: "col",
|
|
985
|
+
style: { width: `${columnWidths[columnKey]}px` },
|
|
986
|
+
"aria-sort": ariaSort,
|
|
987
|
+
"aria-labelledby": columnLabelId(columnKey),
|
|
988
|
+
className: cx(columnClasses(column), isSortable && "crewlet-data-table__th--sortable") || void 0,
|
|
989
|
+
children: [
|
|
990
|
+
isSortable ? /* @__PURE__ */ jsxs(
|
|
991
|
+
"button",
|
|
992
|
+
{
|
|
993
|
+
type: "button",
|
|
994
|
+
className: "crewlet-data-table__sort-button crewlet-data-table__header-content",
|
|
995
|
+
onClick: () => handleSort(columnKey),
|
|
996
|
+
children: [
|
|
997
|
+
/* @__PURE__ */ jsx("span", { id: columnLabelId(columnKey), children: column.label }),
|
|
998
|
+
/* @__PURE__ */ jsx("span", { className: cx("crewlet-data-table__sort-icon", isActive && "is-active"), children: arrow })
|
|
999
|
+
]
|
|
1000
|
+
}
|
|
1001
|
+
) : /* @__PURE__ */ jsx("div", { className: "crewlet-data-table__header-content", children: /* @__PURE__ */ jsx("span", { id: columnLabelId(columnKey), children: column.label }) }),
|
|
1002
|
+
resizable && /* @__PURE__ */ jsx(
|
|
1003
|
+
"button",
|
|
1004
|
+
{
|
|
1005
|
+
type: "button",
|
|
1006
|
+
className: "crewlet-data-table__column-resizer",
|
|
1007
|
+
...resizerState(columnKey),
|
|
1008
|
+
onMouseDown: (e) => handleMouseDownResize(e, columnKey),
|
|
1009
|
+
onClick: (e) => e.stopPropagation(),
|
|
1010
|
+
onKeyDown: (e) => nudgeColumnWidth(e, columnKey)
|
|
1011
|
+
}
|
|
1012
|
+
)
|
|
1013
|
+
]
|
|
1014
|
+
},
|
|
1015
|
+
columnKey
|
|
1016
|
+
);
|
|
1017
|
+
};
|
|
1018
|
+
const renderActionsHeader = () => {
|
|
1019
|
+
if (!hasChromeColumn) return null;
|
|
1020
|
+
if (!settingsInHeader) {
|
|
1021
|
+
return /* @__PURE__ */ jsx(
|
|
1022
|
+
"th",
|
|
1023
|
+
{
|
|
1024
|
+
scope: "col",
|
|
1025
|
+
className: "crewlet-data-table__th--chrome crewlet-data-table__th--actions",
|
|
1026
|
+
style: { width: 1 },
|
|
1027
|
+
children: /* @__PURE__ */ jsx(VisuallyHidden, { children: labels.actions })
|
|
1028
|
+
},
|
|
1029
|
+
"__actions"
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
return (
|
|
1033
|
+
/*
|
|
1034
|
+
* NO POSITION HERE. The two buttons above hang off this cell, so it has
|
|
1035
|
+
* to be their containing block, and it used to say so inline. The header
|
|
1036
|
+
* cells are `sticky` now, which is a positioned value and is already
|
|
1037
|
+
* that containing block; the inline `relative` merely OUTRANKED it, so
|
|
1038
|
+
* on a bounded table every column name stayed put while this one column
|
|
1039
|
+
* scrolled its heading away.
|
|
1040
|
+
*/
|
|
1041
|
+
/* @__PURE__ */ jsxs("th", { scope: "col", style: { width: `${columnWidths.__actions}px` }, children: [
|
|
1042
|
+
labels.actions,
|
|
1043
|
+
/* @__PURE__ */ jsx(
|
|
1044
|
+
"button",
|
|
1045
|
+
{
|
|
1046
|
+
type: "button",
|
|
1047
|
+
className: "crewlet-data-table__header-btn crewlet-data-table__header-btn--reset",
|
|
1048
|
+
onClick: (e) => {
|
|
1049
|
+
e.stopPropagation();
|
|
1050
|
+
resetToDefault();
|
|
1051
|
+
},
|
|
1052
|
+
"aria-label": labels.resetColumns,
|
|
1053
|
+
title: labels.resetColumns,
|
|
1054
|
+
children: /* @__PURE__ */ jsx(SettingsBackupRestoreGlyph, { size: "md" })
|
|
1055
|
+
}
|
|
1056
|
+
),
|
|
1057
|
+
/* @__PURE__ */ jsx(
|
|
1058
|
+
"button",
|
|
1059
|
+
{
|
|
1060
|
+
type: "button",
|
|
1061
|
+
ref: settingsButtonRef,
|
|
1062
|
+
className: "crewlet-data-table__header-btn crewlet-data-table__header-btn--settings",
|
|
1063
|
+
onClick: (e) => {
|
|
1064
|
+
e.stopPropagation();
|
|
1065
|
+
openTableSettings();
|
|
1066
|
+
},
|
|
1067
|
+
"aria-label": labels.settings,
|
|
1068
|
+
title: labels.settings,
|
|
1069
|
+
children: /* @__PURE__ */ jsx(SettingsGlyph, { size: "md" })
|
|
1070
|
+
}
|
|
1071
|
+
)
|
|
1072
|
+
] }, "__actions")
|
|
1073
|
+
);
|
|
1074
|
+
};
|
|
1075
|
+
const renderActionsCell = (row) => {
|
|
1076
|
+
if (!hasChromeColumn) return null;
|
|
1077
|
+
if (!hasActionColumn) {
|
|
1078
|
+
return /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__td--actions" }, "__actions");
|
|
1079
|
+
}
|
|
1080
|
+
if (rowActions) {
|
|
1081
|
+
const actions = rowActions(row);
|
|
1082
|
+
return /* @__PURE__ */ jsx(
|
|
1083
|
+
"td",
|
|
1084
|
+
{
|
|
1085
|
+
className: "crewlet-data-table__td--actions",
|
|
1086
|
+
style: { textAlign: "right", width: 1 },
|
|
1087
|
+
children: /* @__PURE__ */ jsx(RowActionsMenu, { actions, label: labels.rowActions })
|
|
1088
|
+
},
|
|
1089
|
+
"__actions"
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
return /* @__PURE__ */ jsx(
|
|
1093
|
+
"td",
|
|
1094
|
+
{
|
|
1095
|
+
className: "crewlet-data-table__td--actions",
|
|
1096
|
+
style: { width: `${columnWidths.__actions}px`, textAlign: "center" },
|
|
1097
|
+
children: /* @__PURE__ */ jsx(
|
|
1098
|
+
IconButton,
|
|
1099
|
+
{
|
|
1100
|
+
size: "sm",
|
|
1101
|
+
className: "crewlet-data-table__action-btn",
|
|
1102
|
+
onClick: () => onRowAction(row),
|
|
1103
|
+
label: actionLabel,
|
|
1104
|
+
title: actionLabel,
|
|
1105
|
+
icon: actionIcon
|
|
1106
|
+
}
|
|
1107
|
+
)
|
|
1108
|
+
},
|
|
1109
|
+
"__actions"
|
|
1110
|
+
);
|
|
1111
|
+
};
|
|
1112
|
+
const displayedData = getDisplayedData();
|
|
1113
|
+
const bodyHoldsRows = loading && displayedData.length === 0 || !error && displayedData.length > 0;
|
|
1114
|
+
const visibleColumnKeys = columnOrder.filter(isColumnVisible);
|
|
1115
|
+
const firstVisibleKey = columnOrder.find(
|
|
1116
|
+
(key) => columns[key]?.sticky !== "right" && isColumnVisible(key)
|
|
1117
|
+
);
|
|
1118
|
+
const spacerCols = isCompact ? 1 : 0;
|
|
1119
|
+
const colSpan = visibleColumnKeys.length + (hasChromeColumn ? 1 : 0) + spacerCols;
|
|
1120
|
+
const wrapLinesClass = wrapLines ? " crewlet-data-table--wrap-lines" : "";
|
|
1121
|
+
const boundedBody = maxBodyHeight !== void 0;
|
|
1122
|
+
const stickyHeadClass = boundedBody ? " crewlet-data-table--sticky-head" : "";
|
|
1123
|
+
const rootClass = isCompact ? `crewlet-data-table crewlet-data-table--compact crewlet-data-table--density-${density}${wrapLinesClass}${stickyHeadClass} ${className}`.trim() : `crewlet-data-table crewlet-data-table--default${wrapLinesClass}${stickyHeadClass} ${className}`.trim();
|
|
1124
|
+
const expandColSpan = colSpan + (expandable ? 1 : 0);
|
|
1125
|
+
const visibleRowKeys = displayedData.map((row) => resolveRowKey(row));
|
|
1126
|
+
const allExpanded = expandable && visibleRowKeys.length > 0 && visibleRowKeys.every((k) => expandedKeys.has(k));
|
|
1127
|
+
const toggleExpandAll = () => {
|
|
1128
|
+
setExpandedKeys(() => allExpanded ? /* @__PURE__ */ new Set() : new Set(visibleRowKeys));
|
|
1129
|
+
};
|
|
1130
|
+
const renderExpandHeader = () => {
|
|
1131
|
+
if (!expandable) return null;
|
|
1132
|
+
return /* @__PURE__ */ jsx(
|
|
1133
|
+
"th",
|
|
1134
|
+
{
|
|
1135
|
+
className: "crewlet-data-table__expand-header",
|
|
1136
|
+
style: { width: 32 },
|
|
1137
|
+
children: /* @__PURE__ */ jsx(
|
|
1138
|
+
"button",
|
|
1139
|
+
{
|
|
1140
|
+
type: "button",
|
|
1141
|
+
className: "crewlet-data-table__expand-all-btn",
|
|
1142
|
+
onClick: toggleExpandAll,
|
|
1143
|
+
"aria-label": allExpanded ? labels.collapseAll : labels.expandAll,
|
|
1144
|
+
"aria-expanded": allExpanded,
|
|
1145
|
+
title: allExpanded ? labels.collapseAll : labels.expandAll,
|
|
1146
|
+
children: /* @__PURE__ */ jsx(
|
|
1147
|
+
ChevronRightGlyph,
|
|
1148
|
+
{
|
|
1149
|
+
className: `crewlet-data-table__chevron${allExpanded ? " is-open" : ""}`,
|
|
1150
|
+
size: "md"
|
|
1151
|
+
}
|
|
1152
|
+
)
|
|
1153
|
+
}
|
|
1154
|
+
)
|
|
1155
|
+
},
|
|
1156
|
+
"__expand"
|
|
1157
|
+
);
|
|
1158
|
+
};
|
|
1159
|
+
const renderExpandCell = (rowIsOpen, canExpand, onToggle) => {
|
|
1160
|
+
if (!expandable) return null;
|
|
1161
|
+
return /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__expand-cell", style: { width: 32 }, children: canExpand && /* @__PURE__ */ jsx(
|
|
1162
|
+
"button",
|
|
1163
|
+
{
|
|
1164
|
+
type: "button",
|
|
1165
|
+
className: "crewlet-data-table__expand-btn",
|
|
1166
|
+
"aria-expanded": rowIsOpen,
|
|
1167
|
+
"aria-label": rowIsOpen ? labels.collapseRow : labels.expandRow,
|
|
1168
|
+
onClick: (event) => {
|
|
1169
|
+
event.stopPropagation();
|
|
1170
|
+
onToggle();
|
|
1171
|
+
},
|
|
1172
|
+
children: /* @__PURE__ */ jsx(ChevronRightGlyph, { className: cx("crewlet-data-table__chevron", rowIsOpen && "is-open"), size: "md" })
|
|
1173
|
+
}
|
|
1174
|
+
) }, "__expand");
|
|
1175
|
+
};
|
|
1176
|
+
const callerPages = onPageChange !== void 0 && pageCount !== void 0;
|
|
1177
|
+
const pagerVisible = paginationEnabled || callerPages;
|
|
1178
|
+
const pageSizeOffered = paginationEnabled || onItemsPerPageChange !== void 0;
|
|
1179
|
+
const pageRange = (() => {
|
|
1180
|
+
const total = sortedDataMemo.length;
|
|
1181
|
+
if (total === 0) return { from: 0, to: 0, total: 0 };
|
|
1182
|
+
const sliced = paginationEnabled && itemsPerPage !== ALL_ITEMS;
|
|
1183
|
+
const from = sliced ? (currentPage - 1) * itemsPerPage + 1 : 1;
|
|
1184
|
+
return { from, to: Math.min(total, from + displayedData.length - 1), total };
|
|
1185
|
+
})();
|
|
1186
|
+
useEffect(() => {
|
|
1187
|
+
setEmptySaid(emptyCellRef.current?.textContent ?? "");
|
|
1188
|
+
}, [emptyMessage, loading, error, displayedData.length]);
|
|
1189
|
+
const cogInChromeRow = settingsEnabled && isCompact;
|
|
1190
|
+
const topControlsVisible = pagerVisible || cogInChromeRow;
|
|
1191
|
+
const headerVisible = title != null || description != null || icon != null;
|
|
1192
|
+
const cardHeader = useCardHeaderSlot(topControlsVisible && !headerVisible);
|
|
1193
|
+
const renderTopControls = topControlsVisible ? /* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__chrome", children: [
|
|
1194
|
+
pagerVisible && /*
|
|
1195
|
+
* A NAMED GROUP, because `aria-label` on a plain div names nothing: a
|
|
1196
|
+
* generic element has no role for a name to attach to, so the label
|
|
1197
|
+
* this cluster has always carried was read by nobody.
|
|
1198
|
+
*
|
|
1199
|
+
* A GROUP AND NOT A LANDMARK. `<nav aria-label="Pagination">` is the
|
|
1200
|
+
* shape a page-level pager takes, and it comes with a rule this
|
|
1201
|
+
* component cannot keep: where there is more than one of them on a
|
|
1202
|
+
* page, each needs a name of its own. A table does not know how many
|
|
1203
|
+
* tables it is on screen with, and the engine draws three on a single
|
|
1204
|
+
* route, so a landmark here fills a reader's landmark list with
|
|
1205
|
+
* identical entries for chrome that belongs inside a table rather than
|
|
1206
|
+
* to the document. A group carries the name and adds nothing to that
|
|
1207
|
+
* list.
|
|
1208
|
+
*/
|
|
1209
|
+
/* @__PURE__ */ jsxs("div", { role: "group", className: "crewlet-data-table__pagination", "aria-label": labels.pagination, children: [
|
|
1210
|
+
/* @__PURE__ */ jsx(
|
|
1211
|
+
IconButton,
|
|
1212
|
+
{
|
|
1213
|
+
size: "sm",
|
|
1214
|
+
className: "crewlet-data-table__page-btn",
|
|
1215
|
+
onClick: () => goToPage(1),
|
|
1216
|
+
disabled: currentPage <= 1,
|
|
1217
|
+
label: labels.firstPage,
|
|
1218
|
+
icon: /* @__PURE__ */ jsx(KeyboardDoubleArrowLeftGlyph, { size: "md" })
|
|
1219
|
+
}
|
|
1220
|
+
),
|
|
1221
|
+
/* @__PURE__ */ jsx(
|
|
1222
|
+
IconButton,
|
|
1223
|
+
{
|
|
1224
|
+
size: "sm",
|
|
1225
|
+
className: "crewlet-data-table__page-btn",
|
|
1226
|
+
onClick: () => goToPage(Math.max(1, currentPage - 1)),
|
|
1227
|
+
disabled: currentPage <= 1,
|
|
1228
|
+
label: labels.previousPage,
|
|
1229
|
+
icon: /* @__PURE__ */ jsx(ChevronLeftGlyph, { size: "md" })
|
|
1230
|
+
}
|
|
1231
|
+
),
|
|
1232
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-data-table__page-number", "aria-live": "polite", children: [
|
|
1233
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: currentPage }),
|
|
1234
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { children: `${labels.page(currentPage, totalPages)}. ${labels.pageRange(
|
|
1235
|
+
pageRange.from,
|
|
1236
|
+
pageRange.to,
|
|
1237
|
+
pageRange.total
|
|
1238
|
+
)}` })
|
|
1239
|
+
] }),
|
|
1240
|
+
/* @__PURE__ */ jsx(
|
|
1241
|
+
IconButton,
|
|
1242
|
+
{
|
|
1243
|
+
size: "sm",
|
|
1244
|
+
className: "crewlet-data-table__page-btn",
|
|
1245
|
+
onClick: () => goToPage(Math.min(totalPages, currentPage + 1)),
|
|
1246
|
+
disabled: currentPage >= totalPages,
|
|
1247
|
+
label: labels.nextPage,
|
|
1248
|
+
icon: /* @__PURE__ */ jsx(ChevronRightGlyph, { size: "md" })
|
|
1249
|
+
}
|
|
1250
|
+
),
|
|
1251
|
+
/* @__PURE__ */ jsx(
|
|
1252
|
+
IconButton,
|
|
1253
|
+
{
|
|
1254
|
+
size: "sm",
|
|
1255
|
+
className: "crewlet-data-table__page-btn",
|
|
1256
|
+
onClick: () => goToPage(totalPages),
|
|
1257
|
+
disabled: currentPage >= totalPages,
|
|
1258
|
+
label: labels.lastPage,
|
|
1259
|
+
icon: /* @__PURE__ */ jsx(KeyboardDoubleArrowRightGlyph, { size: "md" })
|
|
1260
|
+
}
|
|
1261
|
+
)
|
|
1262
|
+
] }),
|
|
1263
|
+
cogInChromeRow && /* @__PURE__ */ jsx(
|
|
1264
|
+
IconButton,
|
|
1265
|
+
{
|
|
1266
|
+
size: "sm",
|
|
1267
|
+
ref: settingsButtonRef,
|
|
1268
|
+
className: "crewlet-data-table__settings-btn",
|
|
1269
|
+
onClick: openTableSettings,
|
|
1270
|
+
label: labels.settings,
|
|
1271
|
+
title: labels.settings,
|
|
1272
|
+
icon: /* @__PURE__ */ jsx(SettingsGlyph, { size: "md" })
|
|
1273
|
+
}
|
|
1274
|
+
)
|
|
1275
|
+
] }) : null;
|
|
1276
|
+
const chromeInOwnBar = topControlsVisible && !headerVisible && !cardHeader.hosted;
|
|
1277
|
+
const toolbarVisible = renderToolbar != null || chromeInOwnBar;
|
|
1278
|
+
return /* @__PURE__ */ jsxs("div", { className: rootClass, children: [
|
|
1279
|
+
cardHeader.hosted && cardHeader.node !== null ? createPortal(renderTopControls, cardHeader.node) : null,
|
|
1280
|
+
headerVisible && /* @__PURE__ */ jsxs("header", { className: "crewlet-data-table__header", children: [
|
|
1281
|
+
icon != null && /* @__PURE__ */ jsx("span", { className: "crewlet-data-table__header-icon", children: icon }),
|
|
1282
|
+
/* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__header-text", children: [
|
|
1283
|
+
title != null && /* @__PURE__ */ jsx("h3", { className: "crewlet-data-table__title", children: title }),
|
|
1284
|
+
description != null && /* @__PURE__ */ jsx("p", { className: "crewlet-data-table__description", children: description })
|
|
1285
|
+
] }),
|
|
1286
|
+
renderTopControls
|
|
1287
|
+
] }),
|
|
1288
|
+
toolbarVisible && /* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__toolbar", children: [
|
|
1289
|
+
renderToolbar != null && /* @__PURE__ */ jsx("div", { className: "crewlet-data-table__toolbar-start", children: renderToolbar }),
|
|
1290
|
+
onClearFilters != null && filtersActive && /* @__PURE__ */ jsx(
|
|
1291
|
+
"button",
|
|
1292
|
+
{
|
|
1293
|
+
type: "button",
|
|
1294
|
+
className: "crewlet-data-table__clear-filters",
|
|
1295
|
+
onClick: onClearFilters,
|
|
1296
|
+
children: clearFiltersLabel
|
|
1297
|
+
}
|
|
1298
|
+
),
|
|
1299
|
+
chromeInOwnBar && renderTopControls
|
|
1300
|
+
] }),
|
|
1301
|
+
renderFilterBar != null && /* @__PURE__ */ jsx("div", { className: "crewlet-data-table__filter-bar", children: renderFilterBar }),
|
|
1302
|
+
/* @__PURE__ */ jsxs(
|
|
1303
|
+
"div",
|
|
1304
|
+
{
|
|
1305
|
+
className: [
|
|
1306
|
+
"crewlet-data-table__rail",
|
|
1307
|
+
/*
|
|
1308
|
+
* When the table carries a sticky-right action column the
|
|
1309
|
+
* row is treated as a frozen, screen-fitting surface: the
|
|
1310
|
+
* fit pass redistributes regular columns to consume only
|
|
1311
|
+
* the room left after the sticky pane and the gutter, the
|
|
1312
|
+
* resize handles are suppressed, and the scroll container
|
|
1313
|
+
* locks horizontal overflow. The modifier class flips that
|
|
1314
|
+
* behaviour on so the CSS can also drop the scrollbar mask
|
|
1315
|
+
* that would otherwise float over rows when no scrollbar
|
|
1316
|
+
* is present.
|
|
1317
|
+
*/
|
|
1318
|
+
isCompact && columnOrder.some(
|
|
1319
|
+
(k) => columns[k]?.sticky === "right" && isColumnVisible(k)
|
|
1320
|
+
) ? "crewlet-data-table__rail--frozen" : void 0
|
|
1321
|
+
].filter(Boolean).join(" "),
|
|
1322
|
+
style: isCompact ? {
|
|
1323
|
+
"--crewlet-data-table-sticky-pane-width": `${columnOrder.filter((key) => columns[key]?.sticky === "right" && isColumnVisible(key)).reduce((sum, key) => sum + (columnWidths[key] ?? minColumnWidth), 0)}px`
|
|
1324
|
+
} : void 0,
|
|
1325
|
+
children: [
|
|
1326
|
+
/* @__PURE__ */ jsx("span", { role: "status", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: loading ? labels.loading : emptySaid }) }),
|
|
1327
|
+
/* @__PURE__ */ jsx(
|
|
1328
|
+
"div",
|
|
1329
|
+
{
|
|
1330
|
+
className: "crewlet-data-table__scroll",
|
|
1331
|
+
ref: scrollRef,
|
|
1332
|
+
style: boundedBody ? { maxHeight: maxBodyHeight } : void 0,
|
|
1333
|
+
children: /* @__PURE__ */ jsxs(
|
|
1334
|
+
"table",
|
|
1335
|
+
{
|
|
1336
|
+
className: cx(
|
|
1337
|
+
"crewlet-data-table__table",
|
|
1338
|
+
!bodyHoldsRows && "crewlet-data-table__table--rowless"
|
|
1339
|
+
),
|
|
1340
|
+
"aria-busy": loading || void 0,
|
|
1341
|
+
children: [
|
|
1342
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1343
|
+
renderExpandHeader(),
|
|
1344
|
+
columnOrder.filter((key) => columns[key]?.sticky !== "right").map((columnKey) => renderHeaderCell(columnKey)),
|
|
1345
|
+
isCompact && /* @__PURE__ */ jsx(
|
|
1346
|
+
"th",
|
|
1347
|
+
{
|
|
1348
|
+
className: "crewlet-data-table__th--chrome crewlet-data-table__th--spacer",
|
|
1349
|
+
"aria-hidden": true
|
|
1350
|
+
},
|
|
1351
|
+
"__spacer"
|
|
1352
|
+
),
|
|
1353
|
+
columnOrder.filter((key) => columns[key]?.sticky === "right").map((columnKey) => renderHeaderCell(columnKey)),
|
|
1354
|
+
renderActionsHeader()
|
|
1355
|
+
] }) }),
|
|
1356
|
+
/* @__PURE__ */ jsx("tbody", { children: loading && displayedData.length === 0 ? (
|
|
1357
|
+
/*
|
|
1358
|
+
* Skeleton rows live inside the real <tbody> and reuse the
|
|
1359
|
+
* live column set + widths, so the shimmer lines up exactly
|
|
1360
|
+
* with the data that replaces it. Bar widths cycle a fixed
|
|
1361
|
+
* pattern (not Math.random) so re-renders never reshuffle
|
|
1362
|
+
* the shimmer.
|
|
1363
|
+
*/
|
|
1364
|
+
Array.from({ length: Math.max(1, skeletonRows) }, (_, rowIdx) => {
|
|
1365
|
+
const widths = [72, 46, 84, 58, 64];
|
|
1366
|
+
const visibleKeys = columnOrder.filter(
|
|
1367
|
+
(key) => columns[key]?.sticky !== "right" && isColumnVisible(key)
|
|
1368
|
+
);
|
|
1369
|
+
return /* @__PURE__ */ jsxs("tr", { className: "crewlet-data-table__skeleton-row", "aria-hidden": true, children: [
|
|
1370
|
+
expandable && /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__expand-cell", style: { width: 32 } }, "__expand"),
|
|
1371
|
+
visibleKeys.map((columnKey, colIdx) => /* @__PURE__ */ jsx(
|
|
1372
|
+
"td",
|
|
1373
|
+
{
|
|
1374
|
+
style: columnWidths[columnKey] != null ? { width: `${columnWidths[columnKey]}px` } : void 0,
|
|
1375
|
+
children: /* @__PURE__ */ jsx(
|
|
1376
|
+
"span",
|
|
1377
|
+
{
|
|
1378
|
+
className: "crewlet-data-table__skeleton-bar",
|
|
1379
|
+
style: {
|
|
1380
|
+
width: `${widths[(rowIdx + colIdx) % widths.length]}%`,
|
|
1381
|
+
animationDelay: `${rowIdx * 0.1}s`
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
)
|
|
1385
|
+
},
|
|
1386
|
+
columnKey
|
|
1387
|
+
)),
|
|
1388
|
+
isCompact && /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__td--spacer", "aria-hidden": true }, "__spacer"),
|
|
1389
|
+
columnOrder.filter((key) => columns[key]?.sticky === "right" && isColumnVisible(key)).map((columnKey) => /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__td--sticky-right" }, columnKey)),
|
|
1390
|
+
hasChromeColumn && /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__td--actions" }, "__actions")
|
|
1391
|
+
] }, `__skeleton_${rowIdx}`);
|
|
1392
|
+
})
|
|
1393
|
+
) : error ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
1394
|
+
"td",
|
|
1395
|
+
{
|
|
1396
|
+
colSpan: expandColSpan,
|
|
1397
|
+
className: "crewlet-data-table__empty",
|
|
1398
|
+
children: error
|
|
1399
|
+
}
|
|
1400
|
+
) }) : displayedData.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
1401
|
+
"td",
|
|
1402
|
+
{
|
|
1403
|
+
ref: emptyCellRef,
|
|
1404
|
+
colSpan: expandColSpan,
|
|
1405
|
+
className: "crewlet-data-table__empty",
|
|
1406
|
+
children: emptyMessage
|
|
1407
|
+
}
|
|
1408
|
+
) }) : displayedData.map((row) => {
|
|
1409
|
+
const trKey = resolveRowKey(row);
|
|
1410
|
+
const isArchived = archivedPredicate ? archivedPredicate(row) : false;
|
|
1411
|
+
const expanded = expandable ? expandedKeys.has(trKey) : false;
|
|
1412
|
+
const expandedContent = expandable ? renderExpandedRow(row) : null;
|
|
1413
|
+
const canExpand = expandable && expandedContent != null;
|
|
1414
|
+
const href = getRowHref ? getRowHref(row) : null;
|
|
1415
|
+
const tone = rowTone ? rowTone(row) : null;
|
|
1416
|
+
const selected = isSelected ? isSelected(row) : void 0;
|
|
1417
|
+
const isClickable = !!onRowClick || canExpand || !!href;
|
|
1418
|
+
const trClass = cx(
|
|
1419
|
+
isArchived && "crewlet-data-table__row--archived",
|
|
1420
|
+
isClickable && "crewlet-data-table__row--clickable",
|
|
1421
|
+
canExpand && "crewlet-data-table__row--expandable",
|
|
1422
|
+
expanded && "is-expanded",
|
|
1423
|
+
selected && "crewlet-data-table__row--selected",
|
|
1424
|
+
tone && `crewlet-data-table__row--tone-${tone}`
|
|
1425
|
+
);
|
|
1426
|
+
const accessory = renderAccessoryRow ? renderAccessoryRow(row) : null;
|
|
1427
|
+
const onRowSurfaceClick = canExpand ? () => toggleExpanded(trKey) : onRowClick ? () => onRowClick(row) : void 0;
|
|
1428
|
+
const onSurface = onRowSurfaceClick ? (event) => {
|
|
1429
|
+
const from = event.target;
|
|
1430
|
+
if (from?.closest?.('a,button,input,select,textarea,label,[role="button"],[role="link"],[role="menuitem"]')) {
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
onRowSurfaceClick();
|
|
1434
|
+
} : void 0;
|
|
1435
|
+
const rowLead = {
|
|
1436
|
+
tone: tone ? /* @__PURE__ */ jsx(VisuallyHidden, { children: labels.tone[tone] }) : null,
|
|
1437
|
+
href
|
|
1438
|
+
};
|
|
1439
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
1440
|
+
/* @__PURE__ */ jsxs(
|
|
1441
|
+
"tr",
|
|
1442
|
+
{
|
|
1443
|
+
className: trClass || void 0,
|
|
1444
|
+
title: isArchived ? labels.archivedRow(archivedLabel) : void 0,
|
|
1445
|
+
onClick: onSurface,
|
|
1446
|
+
tabIndex: onRowClick && !href && !canExpand ? 0 : void 0,
|
|
1447
|
+
"aria-selected": selected,
|
|
1448
|
+
onKeyDown: onRowClick && !href && !canExpand ? (e) => {
|
|
1449
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1450
|
+
e.preventDefault();
|
|
1451
|
+
onRowClick(row);
|
|
1452
|
+
}
|
|
1453
|
+
} : void 0,
|
|
1454
|
+
children: [
|
|
1455
|
+
renderExpandCell(expanded, canExpand, () => toggleExpanded(trKey)),
|
|
1456
|
+
columnOrder.filter((columnKey) => columns[columnKey]?.sticky !== "right").map((columnKey) => {
|
|
1457
|
+
if (!isColumnVisible(columnKey)) return null;
|
|
1458
|
+
return renderBodyCell(row, columnKey, columnKey === firstVisibleKey ? rowLead : {});
|
|
1459
|
+
}),
|
|
1460
|
+
isCompact && /* @__PURE__ */ jsx("td", { className: "crewlet-data-table__td--spacer", "aria-hidden": true }, "__spacer"),
|
|
1461
|
+
columnOrder.filter((columnKey) => columns[columnKey]?.sticky === "right").map((columnKey) => {
|
|
1462
|
+
if (!isColumnVisible(columnKey)) return null;
|
|
1463
|
+
return renderBodyCell(row, columnKey);
|
|
1464
|
+
}),
|
|
1465
|
+
renderActionsCell(row)
|
|
1466
|
+
]
|
|
1467
|
+
}
|
|
1468
|
+
),
|
|
1469
|
+
expanded && expandedContent != null && /* @__PURE__ */ jsx(
|
|
1470
|
+
"tr",
|
|
1471
|
+
{
|
|
1472
|
+
className: [
|
|
1473
|
+
"crewlet-data-table__expanded-row",
|
|
1474
|
+
isArchived ? "crewlet-data-table__row--archived" : void 0
|
|
1475
|
+
].filter(Boolean).join(" "),
|
|
1476
|
+
children: /* @__PURE__ */ jsx("td", { colSpan: expandColSpan, className: "crewlet-data-table__expanded-cell", children: expandedContent })
|
|
1477
|
+
}
|
|
1478
|
+
),
|
|
1479
|
+
accessory != null && /* @__PURE__ */ jsx(
|
|
1480
|
+
"tr",
|
|
1481
|
+
{
|
|
1482
|
+
className: [
|
|
1483
|
+
"crewlet-data-table__accessory-row",
|
|
1484
|
+
isArchived ? "crewlet-data-table__row--archived" : void 0
|
|
1485
|
+
].filter(Boolean).join(" "),
|
|
1486
|
+
children: /* @__PURE__ */ jsx("td", { colSpan, className: "crewlet-data-table__accessory-cell", children: accessory })
|
|
1487
|
+
}
|
|
1488
|
+
)
|
|
1489
|
+
] }, trKey ?? JSON.stringify(row));
|
|
1490
|
+
}) })
|
|
1491
|
+
]
|
|
1492
|
+
}
|
|
1493
|
+
)
|
|
1494
|
+
}
|
|
1495
|
+
)
|
|
1496
|
+
]
|
|
1497
|
+
}
|
|
1498
|
+
),
|
|
1499
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx("div", { className: "crewlet-data-table__load-more", children: /* @__PURE__ */ jsx(
|
|
1500
|
+
Button,
|
|
1501
|
+
{
|
|
1502
|
+
variant: "outline",
|
|
1503
|
+
size: "small",
|
|
1504
|
+
onClick: onLoadMore,
|
|
1505
|
+
loading: loadingMore,
|
|
1506
|
+
children: loadMoreLabel
|
|
1507
|
+
}
|
|
1508
|
+
) }),
|
|
1509
|
+
!hasMore && endMessage != null && displayedData.length > 0 && !loading && /* @__PURE__ */ jsx("p", { className: "crewlet-data-table__end", children: endMessage }),
|
|
1510
|
+
/* @__PURE__ */ jsxs(
|
|
1511
|
+
Modal,
|
|
1512
|
+
{
|
|
1513
|
+
open: tableSettingsOpen,
|
|
1514
|
+
onClose: cancelTableSettings,
|
|
1515
|
+
title: labels.settingsTitle,
|
|
1516
|
+
size: "lg",
|
|
1517
|
+
footerStart: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1518
|
+
/* @__PURE__ */ jsx(
|
|
1519
|
+
Button,
|
|
1520
|
+
{
|
|
1521
|
+
variant: "secondary",
|
|
1522
|
+
onClick: handleResetTableSettings,
|
|
1523
|
+
leadingIcon: resetConfirmed ? /* @__PURE__ */ jsx(CheckGlyph, { className: "crewlet-data-table__reset-confirm-icon", size: "sm" }) : void 0,
|
|
1524
|
+
children: labels.resetColumns
|
|
1525
|
+
}
|
|
1526
|
+
),
|
|
1527
|
+
/* @__PURE__ */ jsx("span", { role: "status", children: /* @__PURE__ */ jsx(VisuallyHidden, { children: settingsSaid }) })
|
|
1528
|
+
] }),
|
|
1529
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1530
|
+
/* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: cancelTableSettings, children: labels.cancel }),
|
|
1531
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: applyTableSettings, children: labels.apply })
|
|
1532
|
+
] }),
|
|
1533
|
+
children: [
|
|
1534
|
+
pageSizeOffered ? /* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__settings-section", children: [
|
|
1535
|
+
/* @__PURE__ */ jsx("h3", { className: "crewlet-data-table__settings-section-title", children: labels.itemsPerPage }),
|
|
1536
|
+
/* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__items-per-page-options", children: [
|
|
1537
|
+
itemsPerPageOptions.map((value) => /* @__PURE__ */ jsx(
|
|
1538
|
+
"button",
|
|
1539
|
+
{
|
|
1540
|
+
type: "button",
|
|
1541
|
+
className: cx("crewlet-data-table__items-per-page-btn", draftItemsPerPage === value && "is-active"),
|
|
1542
|
+
"aria-pressed": draftItemsPerPage === value,
|
|
1543
|
+
onClick: () => handleItemsPerPageChange(value),
|
|
1544
|
+
children: value
|
|
1545
|
+
},
|
|
1546
|
+
value
|
|
1547
|
+
)),
|
|
1548
|
+
/* @__PURE__ */ jsxs(
|
|
1549
|
+
"button",
|
|
1550
|
+
{
|
|
1551
|
+
type: "button",
|
|
1552
|
+
className: cx("crewlet-data-table__items-per-page-btn", draftItemsPerPage === ALL_ITEMS && "is-active"),
|
|
1553
|
+
"aria-pressed": draftItemsPerPage === ALL_ITEMS,
|
|
1554
|
+
onClick: () => handleItemsPerPageChange(ALL_ITEMS),
|
|
1555
|
+
children: [
|
|
1556
|
+
labels.allItems,
|
|
1557
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { children: ` ${labels.allItemsCount(sortedDataMemo.length)}` })
|
|
1558
|
+
]
|
|
1559
|
+
}
|
|
1560
|
+
)
|
|
1561
|
+
] })
|
|
1562
|
+
] }) : null,
|
|
1563
|
+
/* @__PURE__ */ jsx("div", { className: "crewlet-data-table__settings-section", children: /* @__PURE__ */ jsx(
|
|
1564
|
+
Checkbox,
|
|
1565
|
+
{
|
|
1566
|
+
label: labels.wrapLines,
|
|
1567
|
+
description: labels.wrapLinesHint,
|
|
1568
|
+
checked: draftWrapLines,
|
|
1569
|
+
onChange: (e) => setDraftWrapLines(e.target.checked)
|
|
1570
|
+
}
|
|
1571
|
+
) }),
|
|
1572
|
+
/* @__PURE__ */ jsxs("div", { className: "crewlet-data-table__settings-section", children: [
|
|
1573
|
+
/* @__PURE__ */ jsx("h3", { className: "crewlet-data-table__settings-section-title", children: labels.columnsSection }),
|
|
1574
|
+
/* @__PURE__ */ jsx("p", { className: "crewlet-data-table__settings-section-hint", children: labels.columnsHint }),
|
|
1575
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { id: reorderHintId, children: labels.reorderHint }),
|
|
1576
|
+
/* @__PURE__ */ jsx("ul", { className: "crewlet-data-table__column-toggles", children: draftColumnOrder.map((key, index) => {
|
|
1577
|
+
const name = columnName(key);
|
|
1578
|
+
const fixed = whyFixed(key, draftVisibleColumns);
|
|
1579
|
+
const shown = draftVisibleColumns[key] !== false;
|
|
1580
|
+
return /* @__PURE__ */ jsxs(
|
|
1581
|
+
"li",
|
|
1582
|
+
{
|
|
1583
|
+
className: cx("crewlet-data-table__column-toggle-item", draggedColumn === key && "is-dragging"),
|
|
1584
|
+
onDragOver: (e) => handleDragOver(e, key),
|
|
1585
|
+
onDrop: (e) => handleDrop(e),
|
|
1586
|
+
children: [
|
|
1587
|
+
/* @__PURE__ */ jsx(
|
|
1588
|
+
IconButton,
|
|
1589
|
+
{
|
|
1590
|
+
size: "sm",
|
|
1591
|
+
className: "crewlet-data-table__column-drag-handle",
|
|
1592
|
+
label: labels.reorder(name),
|
|
1593
|
+
icon: /* @__PURE__ */ jsx(DragIndicatorGlyph, { size: "md" }),
|
|
1594
|
+
"aria-describedby": reorderHintId,
|
|
1595
|
+
draggable: true,
|
|
1596
|
+
onDragStart: (e) => handleDragStart(e, key),
|
|
1597
|
+
onDragEnd: handleDragEnd,
|
|
1598
|
+
onKeyDown: (e) => {
|
|
1599
|
+
if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
|
|
1600
|
+
e.preventDefault();
|
|
1601
|
+
moveColumn(key, e.key === "ArrowUp" ? -1 : 1);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
),
|
|
1605
|
+
/* @__PURE__ */ jsx(
|
|
1606
|
+
Checkbox,
|
|
1607
|
+
{
|
|
1608
|
+
className: cx(
|
|
1609
|
+
"crewlet-data-table__column-toggle",
|
|
1610
|
+
fixed !== null && shown && "is-fixed"
|
|
1611
|
+
),
|
|
1612
|
+
label: name,
|
|
1613
|
+
...fixed !== null && shown ? { description: fixed, "aria-disabled": true } : {},
|
|
1614
|
+
checked: shown,
|
|
1615
|
+
onChange: () => handleToggleColumn(key)
|
|
1616
|
+
}
|
|
1617
|
+
),
|
|
1618
|
+
/* @__PURE__ */ jsxs("span", { className: "crewlet-data-table__column-toggle-actions", children: [
|
|
1619
|
+
/* @__PURE__ */ jsx(
|
|
1620
|
+
IconButton,
|
|
1621
|
+
{
|
|
1622
|
+
size: "sm",
|
|
1623
|
+
label: labels.moveUp(name),
|
|
1624
|
+
icon: /* @__PURE__ */ jsx(KeyboardArrowUpGlyph, { size: "sm" }),
|
|
1625
|
+
...index === 0 ? { disabledReason: labels.atTop(name) } : {},
|
|
1626
|
+
onClick: () => moveColumn(key, -1)
|
|
1627
|
+
}
|
|
1628
|
+
),
|
|
1629
|
+
/* @__PURE__ */ jsx(
|
|
1630
|
+
IconButton,
|
|
1631
|
+
{
|
|
1632
|
+
size: "sm",
|
|
1633
|
+
label: labels.moveDown(name),
|
|
1634
|
+
icon: /* @__PURE__ */ jsx(KeyboardArrowDownGlyph, { size: "sm" }),
|
|
1635
|
+
...index === draftColumnOrder.length - 1 ? { disabledReason: labels.atBottom(name) } : {},
|
|
1636
|
+
onClick: () => moveColumn(key, 1)
|
|
1637
|
+
}
|
|
1638
|
+
)
|
|
1639
|
+
] })
|
|
1640
|
+
]
|
|
1641
|
+
},
|
|
1642
|
+
key
|
|
1643
|
+
);
|
|
1644
|
+
}) })
|
|
1645
|
+
] })
|
|
1646
|
+
]
|
|
1647
|
+
}
|
|
1648
|
+
)
|
|
1649
|
+
] });
|
|
1650
|
+
};
|
|
1651
|
+
|
|
1652
|
+
export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu };
|