@astryxdesign/core 0.1.7 → 0.1.8-canary.0c4d8d7
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/CHANGELOG.md +65 -0
- package/README.md +30 -19
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +10 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -8
- package/dist/Avatar/AvatarSizeContext.d.ts +1 -1
- package/dist/Avatar/AvatarSizeContext.js +1 -1
- package/dist/Avatar/AvatarStatusDot.d.ts +2 -2
- package/dist/Avatar/AvatarStatusDot.js +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +2 -2
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +16 -14
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +31 -2
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +31 -2
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +6 -2
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +55 -5
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +31 -6
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +19 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -3
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -4
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -0
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +8 -1
- package/dist/Collapsible/Collapsible.d.ts +11 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +36 -4
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/ContextMenu/index.d.ts +3 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +7 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +10 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +8 -4
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +88 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +169 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +68 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +10 -1
- package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemRoles.js +15 -0
- package/dist/FieldStatus/FieldStatus.d.ts +8 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +22 -4
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +10 -2
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -2
- package/dist/Icon/Icon.d.ts +43 -13
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +62 -27
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +39 -12
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/Outline/Outline.d.ts +68 -3
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +128 -26
- package/dist/Outline/useScrollSpy.d.ts +27 -7
- package/dist/Outline/useScrollSpy.d.ts.map +1 -1
- package/dist/Outline/useScrollSpy.js +202 -70
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +14 -11
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +4 -2
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +15 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/Table.d.ts +1 -1
- package/dist/Table/Table.js +1 -1
- package/dist/Table/index.d.ts +4 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +24 -2
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +12 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +4 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +18 -7
- package/dist/Table/plugins/tree/index.d.ts +5 -0
- package/dist/Table/plugins/tree/index.d.ts.map +1 -0
- package/dist/Table/plugins/tree/index.js +4 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +38 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeData.js +358 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +51 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeState.js +175 -0
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +6 -3
- package/dist/Thumbnail/Thumbnail.d.ts +8 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +46 -8
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -4
- package/dist/Tokenizer/Tokenizer.d.ts +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +16 -4
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +8 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +5 -14
- package/dist/astryx.css +51 -16
- package/dist/astryx.umd.js +56 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +37 -25
- package/dist/theme/Theme.js +1 -1
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +0 -3
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/docs.mjs +32 -461
- package/locales/en.json +212 -172
- package/locales/fr-FR.json +10 -0
- package/locales/pseudo.json +30 -0
- package/package.json +3 -1
- package/scripts/postinstall.mjs +93 -0
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +6 -6
- package/src/Avatar/Avatar.tsx +16 -11
- package/src/Avatar/AvatarSizeContext.ts +1 -1
- package/src/Avatar/AvatarStatusDot.tsx +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroup.test.tsx +17 -3
- package/src/AvatarGroup/AvatarGroup.tsx +3 -3
- package/src/AvatarGroup/AvatarGroupOverflow.doc.mjs +4 -4
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +21 -5
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +47 -3
- package/src/Button/Button.doc.mjs +9 -0
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +25 -1
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +149 -1
- package/src/Carousel/Carousel.tsx +62 -5
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposer.doc.mjs +9 -0
- package/src/Chat/ChatComposer.test.tsx +35 -0
- package/src/Chat/ChatComposer.tsx +58 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +87 -0
- package/src/Chat/ChatComposerInput.tsx +35 -3
- package/src/Chat/ChatLayout.tsx +3 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessage.tsx +4 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +5 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +13 -1
- package/src/Chat/useTriggerMenu.tsx +3 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxList/CheckboxList.test.tsx +9 -1
- package/src/Citation/Citation.test.tsx +51 -0
- package/src/Citation/Citation.tsx +8 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +11 -1
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +9 -1
- package/src/Collapsible/Collapsible.doc.mjs +7 -0
- package/src/Collapsible/Collapsible.test.tsx +80 -0
- package/src/Collapsible/Collapsible.tsx +58 -5
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/ContextMenu/ContextMenu.test.tsx +75 -1
- package/src/ContextMenu/ContextMenu.tsx +10 -5
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
- package/src/DateTimeInput/DateTimeInput.tsx +14 -2
- package/src/Dialog/Dialog.tsx +12 -2
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +11 -6
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +236 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +7 -1
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +118 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
- package/src/DropdownMenu/index.ts +23 -3
- package/src/DropdownMenu/menuItemRoles.ts +22 -0
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/FieldLabel.doc.mjs +1 -1
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +78 -40
- package/src/FieldStatus/FieldStatus.tsx +22 -4
- package/src/FileInput/FileInput.test.tsx +52 -3
- package/src/FileInput/FileInput.tsx +13 -2
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +24 -2
- package/src/Icon/Icon.doc.mjs +12 -0
- package/src/Icon/Icon.test.tsx +142 -0
- package/src/Icon/Icon.tsx +98 -30
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Layer/useLayer.tsx +8 -0
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +4 -2
- package/src/MultiSelector/MultiSelector.test.tsx +162 -1
- package/src/MultiSelector/MultiSelector.tsx +55 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/NumberInput/NumberInput.test.tsx +11 -7
- package/src/NumberInput/NumberInput.tsx +1 -2
- package/src/Outline/Outline.doc.mjs +123 -3
- package/src/Outline/Outline.test.tsx +735 -0
- package/src/Outline/Outline.tsx +183 -33
- package/src/Outline/useScrollSpy.ts +248 -72
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +27 -14
- package/src/Selector/Selector.test.tsx +69 -0
- package/src/Selector/Selector.tsx +5 -1
- package/src/Selector/SelectorOption.doc.mjs +1 -1
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNavCollapseButton.tsx +6 -1
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.doc.mjs +2 -2
- package/src/SideNav/SideNavItem.tsx +5 -1
- package/src/Slider/Slider.test.tsx +62 -2
- package/src/Slider/Slider.tsx +15 -1
- package/src/Switch/Switch.doc.mjs +1 -1
- package/src/Switch/Switch.test.tsx +32 -1
- package/src/TabList/Tab.tsx +5 -1
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/TabList.tsx +8 -0
- package/src/TabList/TabMenu.tsx +4 -1
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.tsx +1 -1
- package/src/Table/index.ts +12 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +90 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +37 -5
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +18 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +95 -9
- package/src/Table/plugins/sortable/useTableSortable.tsx +23 -7
- package/src/Table/plugins/tree/index.ts +12 -0
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +163 -0
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +594 -0
- package/src/Table/plugins/tree/useTableTreeData.tsx +495 -0
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +636 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +253 -0
- package/src/Table/useBaseTablePlugins.ts +6 -2
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +75 -0
- package/src/Table/useTableTreeState.doc.mjs +98 -0
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.test.tsx +9 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +9 -0
- package/src/Thumbnail/Thumbnail.test.tsx +38 -8
- package/src/Thumbnail/Thumbnail.tsx +28 -1
- package/src/TimeInput/TimeInput.test.tsx +76 -1
- package/src/TimeInput/TimeInput.tsx +19 -6
- package/src/Tokenizer/Tokenizer.doc.mjs +1 -1
- package/src/Tokenizer/Tokenizer.test.tsx +137 -2
- package/src/Tokenizer/Tokenizer.tsx +16 -4
- package/src/Toolbar/Toolbar.tsx +10 -3
- package/src/TopNav/TopNav.test.tsx +80 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.test.tsx +32 -1
- package/src/TreeList/TreeListItem.tsx +19 -10
- package/src/authoring/doc.ts +1 -3
- package/src/docs-script.test.mjs +18 -13
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +77 -33
- package/src/postinstall.test.mjs +71 -0
- package/src/theme/Theme.doc.mjs +4 -4
- package/src/theme/Theme.tsx +1 -1
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/generateThemeRules.test.ts +65 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +0 -4
- package/src/utils/types.ts +14 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +0 -16
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +0 -1
- package/dist/TreeList/treeListItem.markers.stylex.js +0 -22
- package/src/TreeList/treeListItem.markers.stylex.ts +0 -20
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useTableTreeState.tsx
|
|
7
|
+
* @input React
|
|
8
|
+
* @output Exports useTableTreeState hook and config/result types
|
|
9
|
+
* @position Tree state helper; owns the expanded set + flattens nested data.
|
|
10
|
+
* Pairs with useTableTreeData (the headless tree plugin).
|
|
11
|
+
*
|
|
12
|
+
* Modeled after useTableSortableState — a convenience layer that owns state
|
|
13
|
+
* (controlled or uncontrolled) and produces both the visible flattened rows
|
|
14
|
+
* and a ready-to-use config for the headless plugin. Data shaping stays
|
|
15
|
+
* outside the render pipeline: Table always receives exactly the rows it
|
|
16
|
+
* renders, so collapsed subtrees are unmounted, not hidden.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import {useCallback, useMemo, useRef, useState} from 'react';
|
|
20
|
+
import type {
|
|
21
|
+
TableTreeRowMeta,
|
|
22
|
+
UseTableTreeDataConfig,
|
|
23
|
+
} from './useTableTreeData';
|
|
24
|
+
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// Config
|
|
27
|
+
// =============================================================================
|
|
28
|
+
|
|
29
|
+
export interface UseTableTreeStateConfig<T extends Record<string, unknown>> {
|
|
30
|
+
/** Nested data: rows may carry child rows under `childrenKey`. */
|
|
31
|
+
data: T[];
|
|
32
|
+
/** Row ID accessor: property name, or a function returning a unique id. */
|
|
33
|
+
idKey: (keyof T & string) | ((item: T) => string | number);
|
|
34
|
+
/**
|
|
35
|
+
* Property holding each row's children array.
|
|
36
|
+
* @default 'children'
|
|
37
|
+
*/
|
|
38
|
+
childrenKey?: string;
|
|
39
|
+
/** Initial expanded row ids for uncontrolled mode. Ignored when `expandedIds` is provided. */
|
|
40
|
+
defaultExpandedIds?: Iterable<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Controlled set of expanded row ids. When provided, the hook uses this
|
|
43
|
+
* instead of internal state. Pair with `onExpandedIdsChange`.
|
|
44
|
+
*/
|
|
45
|
+
expandedIds?: ReadonlySet<string>;
|
|
46
|
+
/** Called with the next expanded set whenever expansion changes. */
|
|
47
|
+
onExpandedIdsChange?: (ids: ReadonlySet<string>) => void;
|
|
48
|
+
/**
|
|
49
|
+
* Should this row show an expander? Overrides the default
|
|
50
|
+
* "has a non-empty children array" check — use for lazy loading, where a
|
|
51
|
+
* row is expandable before its children have been fetched.
|
|
52
|
+
*/
|
|
53
|
+
isItemExpandable?: (item: T) => boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Sort each sibling group independently during flattening. Children always
|
|
56
|
+
* stay directly under their parent — sorting never crosses levels. Pass
|
|
57
|
+
* `applySort` from `useTableSortableState` to compose with column sorting.
|
|
58
|
+
*/
|
|
59
|
+
sortSiblings?: (siblings: T[]) => T[];
|
|
60
|
+
/** Indent step per level, forwarded to useTableTreeData. */
|
|
61
|
+
indent?: 'sm' | 'md' | 'lg';
|
|
62
|
+
/** Column that carries the tree affordance, forwarded to useTableTreeData. */
|
|
63
|
+
treeColumnKey?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Result
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
export interface UseTableTreeStateResult<T extends Record<string, unknown>> {
|
|
71
|
+
/** The flattened, currently-visible rows. Pass to `<Table data>`. */
|
|
72
|
+
visibleData: T[];
|
|
73
|
+
/** Ready-to-use config for useTableTreeData. */
|
|
74
|
+
treeConfig: UseTableTreeDataConfig<T>;
|
|
75
|
+
/** The current expanded row ids. */
|
|
76
|
+
expandedIds: ReadonlySet<string>;
|
|
77
|
+
/** Expand every expandable row in the tree. */
|
|
78
|
+
expandAll: () => void;
|
|
79
|
+
/** Collapse every row. */
|
|
80
|
+
collapseAll: () => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// =============================================================================
|
|
84
|
+
// Hook
|
|
85
|
+
// =============================================================================
|
|
86
|
+
|
|
87
|
+
export function useTableTreeState<T extends Record<string, unknown>>(
|
|
88
|
+
config: UseTableTreeStateConfig<T>,
|
|
89
|
+
): UseTableTreeStateResult<T> {
|
|
90
|
+
const {
|
|
91
|
+
data,
|
|
92
|
+
idKey,
|
|
93
|
+
childrenKey = 'children',
|
|
94
|
+
defaultExpandedIds,
|
|
95
|
+
expandedIds: controlledExpandedIds,
|
|
96
|
+
onExpandedIdsChange,
|
|
97
|
+
isItemExpandable,
|
|
98
|
+
sortSiblings,
|
|
99
|
+
indent,
|
|
100
|
+
treeColumnKey,
|
|
101
|
+
} = config;
|
|
102
|
+
|
|
103
|
+
const getId = useCallback(
|
|
104
|
+
(item: T): string =>
|
|
105
|
+
typeof idKey === 'function' ? String(idKey(item)) : String(item[idKey]),
|
|
106
|
+
[idKey],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const getChildren = useCallback(
|
|
110
|
+
(item: T): T[] => {
|
|
111
|
+
const children = item[childrenKey];
|
|
112
|
+
return Array.isArray(children) ? (children as T[]) : [];
|
|
113
|
+
},
|
|
114
|
+
[childrenKey],
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const getIsExpandable = useCallback(
|
|
118
|
+
(item: T): boolean =>
|
|
119
|
+
isItemExpandable ? isItemExpandable(item) : getChildren(item).length > 0,
|
|
120
|
+
[isItemExpandable, getChildren],
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Internal state (used in uncontrolled mode)
|
|
124
|
+
const [internalExpandedIds, setInternalExpandedIds] = useState<
|
|
125
|
+
ReadonlySet<string>
|
|
126
|
+
>(() => new Set(defaultExpandedIds));
|
|
127
|
+
|
|
128
|
+
// Resolve controlled vs uncontrolled
|
|
129
|
+
const isControlled = controlledExpandedIds !== undefined;
|
|
130
|
+
const expandedIds = isControlled
|
|
131
|
+
? controlledExpandedIds
|
|
132
|
+
: internalExpandedIds;
|
|
133
|
+
|
|
134
|
+
// Stable refs so callbacks don't churn on inline-prop identity changes
|
|
135
|
+
const expandedIdsRef = useRef(expandedIds);
|
|
136
|
+
expandedIdsRef.current = expandedIds;
|
|
137
|
+
const onExpandedIdsChangeRef = useRef(onExpandedIdsChange);
|
|
138
|
+
onExpandedIdsChangeRef.current = onExpandedIdsChange;
|
|
139
|
+
|
|
140
|
+
const commitExpandedIds = useCallback(
|
|
141
|
+
(next: ReadonlySet<string>) => {
|
|
142
|
+
// Advance the ref immediately so a second commit in the same React
|
|
143
|
+
// batch (e.g. two onToggleItem calls in one event handler) builds
|
|
144
|
+
// on this one instead of the pre-batch set. The ref re-syncs from
|
|
145
|
+
// the resolved state on the next render either way.
|
|
146
|
+
expandedIdsRef.current = next;
|
|
147
|
+
if (!isControlled) {
|
|
148
|
+
setInternalExpandedIds(next);
|
|
149
|
+
}
|
|
150
|
+
onExpandedIdsChangeRef.current?.(next);
|
|
151
|
+
},
|
|
152
|
+
[isControlled],
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// Flatten: depth-first walk emitting only visible rows, collecting per-row
|
|
156
|
+
// meta ({level, hasChildren, isExpanded}) in the same pass. Children mount
|
|
157
|
+
// only when their parent is expanded, so collapsed subtrees stay unmounted.
|
|
158
|
+
// `path` holds the ids on the current ancestor chain: an edge pointing back
|
|
159
|
+
// at an ancestor is skipped instead of recursing forever. Sibling arrays
|
|
160
|
+
// are copied before sortSiblings so an in-place sorter can't reorder the
|
|
161
|
+
// consumer's data.
|
|
162
|
+
const {visibleData, metaMap} = useMemo(() => {
|
|
163
|
+
const rows: T[] = [];
|
|
164
|
+
const meta = new Map<string, TableTreeRowMeta>();
|
|
165
|
+
const path = new Set<string>();
|
|
166
|
+
const walk = (items: T[], level: number) => {
|
|
167
|
+
const siblings = sortSiblings ? sortSiblings([...items]) : items;
|
|
168
|
+
for (const item of siblings) {
|
|
169
|
+
const id = getId(item);
|
|
170
|
+
if (path.has(id)) {
|
|
171
|
+
continue; // cyclic edge — this row is its own ancestor
|
|
172
|
+
}
|
|
173
|
+
const hasChildren = getIsExpandable(item);
|
|
174
|
+
const isExpanded = hasChildren && expandedIds.has(id);
|
|
175
|
+
rows.push(item);
|
|
176
|
+
meta.set(id, {id, level, hasChildren, isExpanded});
|
|
177
|
+
if (isExpanded) {
|
|
178
|
+
path.add(id);
|
|
179
|
+
walk(getChildren(item), level + 1);
|
|
180
|
+
path.delete(id);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
walk(data, 0);
|
|
185
|
+
return {visibleData: rows, metaMap: meta};
|
|
186
|
+
}, [data, expandedIds, getId, getChildren, getIsExpandable, sortSiblings]);
|
|
187
|
+
|
|
188
|
+
// Every expandable row id across the whole tree, including collapsed
|
|
189
|
+
// subtrees (drives expandAll and the migration no-op flag). Same
|
|
190
|
+
// ancestor-chain guard as the flatten walk.
|
|
191
|
+
const allExpandableIds = useMemo(() => {
|
|
192
|
+
const idsAcc: string[] = [];
|
|
193
|
+
const path = new Set<string>();
|
|
194
|
+
const walk = (items: T[]) => {
|
|
195
|
+
for (const item of items) {
|
|
196
|
+
const id = getId(item);
|
|
197
|
+
if (path.has(id)) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (getIsExpandable(item)) {
|
|
201
|
+
idsAcc.push(id);
|
|
202
|
+
}
|
|
203
|
+
path.add(id);
|
|
204
|
+
walk(getChildren(item));
|
|
205
|
+
path.delete(id);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
walk(data);
|
|
209
|
+
return idsAcc;
|
|
210
|
+
}, [data, getId, getChildren, getIsExpandable]);
|
|
211
|
+
|
|
212
|
+
const hasExpandableRows = allExpandableIds.length > 0;
|
|
213
|
+
|
|
214
|
+
const onToggleItem = useCallback(
|
|
215
|
+
(item: T) => {
|
|
216
|
+
const id = getId(item);
|
|
217
|
+
const next = new Set(expandedIdsRef.current);
|
|
218
|
+
if (next.has(id)) {
|
|
219
|
+
next.delete(id);
|
|
220
|
+
} else {
|
|
221
|
+
next.add(id);
|
|
222
|
+
}
|
|
223
|
+
commitExpandedIds(next);
|
|
224
|
+
},
|
|
225
|
+
[getId, commitExpandedIds],
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const expandAll = useCallback(() => {
|
|
229
|
+
commitExpandedIds(new Set(allExpandableIds));
|
|
230
|
+
}, [commitExpandedIds, allExpandableIds]);
|
|
231
|
+
|
|
232
|
+
const collapseAll = useCallback(() => {
|
|
233
|
+
commitExpandedIds(new Set());
|
|
234
|
+
}, [commitExpandedIds]);
|
|
235
|
+
|
|
236
|
+
const getRowMeta = useCallback(
|
|
237
|
+
(item: T): TableTreeRowMeta | undefined => metaMap.get(getId(item)),
|
|
238
|
+
[metaMap, getId],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const treeConfig = useMemo(
|
|
242
|
+
(): UseTableTreeDataConfig<T> => ({
|
|
243
|
+
getRowMeta,
|
|
244
|
+
onToggleItem,
|
|
245
|
+
hasExpandableRows,
|
|
246
|
+
indent,
|
|
247
|
+
treeColumnKey,
|
|
248
|
+
}),
|
|
249
|
+
[getRowMeta, onToggleItem, hasExpandableRows, indent, treeColumnKey],
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
return {visibleData, treeConfig, expandedIds, expandAll, collapseAll};
|
|
253
|
+
}
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
* Canonical order:
|
|
19
19
|
* 1. columnSettings — column filtering (future: transformColumns)
|
|
20
20
|
* 2. sort — header cell sort controls
|
|
21
|
-
* 3.
|
|
22
|
-
* 4.
|
|
21
|
+
* 3. tree — indent + expander on the tree column
|
|
22
|
+
* 4. selection — checkbox column + row selection
|
|
23
|
+
* 5. pagination — pagination controls around the table
|
|
23
24
|
*
|
|
24
25
|
* Rationale:
|
|
25
26
|
* - columnSettings filters columns before sort/selection see them
|
|
26
27
|
* - sort adds header cell UI before selection adds its header column
|
|
28
|
+
* - tree wraps the first *user* column before selection prepends its
|
|
29
|
+
* checkbox column, so the expander never lands in the checkbox column
|
|
27
30
|
* - selection adds its column after sort so the checkbox header
|
|
28
31
|
* doesn't get a sort button
|
|
29
32
|
* - pagination wraps the table in context last (outermost provider)
|
|
@@ -46,6 +49,7 @@ import type {TablePlugin} from './types';
|
|
|
46
49
|
const PLUGIN_ORDER: ReadonlyArray<string> = [
|
|
47
50
|
'columnSettings',
|
|
48
51
|
'sort',
|
|
52
|
+
'tree',
|
|
49
53
|
'selection',
|
|
50
54
|
'pagination',
|
|
51
55
|
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'useTableRowStatus',
|
|
7
|
+
subComponentOf: 'Table',
|
|
8
|
+
displayName: 'useTableRowStatus',
|
|
9
|
+
description:
|
|
10
|
+
'Hook that returns a TablePlugin which prepends a narrow column signaling per-row status: a colored status dot by default, or an icon when provided (shape + color is more accessible than color alone). getStatus maps a row to a semantic color (mapped to a theme token) or raw CSS color, an optional icon, and a required accessible label (shown in a tooltip on hover and announced to assistive technology, so status is never color-only); return null for no indicator. Memoize getStatus with useCallback for a stable plugin identity.',
|
|
11
|
+
props: [
|
|
12
|
+
{
|
|
13
|
+
name: 'getStatus',
|
|
14
|
+
type: "(item: T) => { color: 'accent' | 'success' | 'error' | 'warning' | 'red' | 'orange' | 'green' | 'yellow' | 'blue' | 'gray' | string; icon?: IconName; label: string } | null",
|
|
15
|
+
description:
|
|
16
|
+
'Derive the status indicator for a row: a semantic color (accent, success, error, warning, red, orange, green, yellow, blue, gray — mapped to a theme token) or a raw CSS color as an escape hatch; an optional icon to signal status by shape instead of the dot (recommended when multiple statuses coexist; valid names: close, chevronDown, chevronLeft, chevronRight, check, success, error, warning, info, calendar, clock, externalLink, menu, moreHorizontal, search, arrowUp, arrowDown, arrowsUpDown, funnel, eyeSlash, viewColumns, copy, checkDouble, wrench, stop, microphone); and a required accessible label (announced via role="img" and shown in a tooltip on hover, so a status is never conveyed by color alone). Return null for rows with no status. Memoize with useCallback for a stable plugin identity.',
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** @type {import('../docs-types').TranslationDoc} */
|
|
23
|
+
export const docsDense = {
|
|
24
|
+
description:
|
|
25
|
+
'Returns a TablePlugin that prepends a narrow per-row status column: a colored dot, or an icon when provided (shape + color beats color alone for a11y). getStatus maps a row to {color, icon?, label} or null. color is a semantic name (success/error/warning/etc.) mapped to a theme token, or a raw CSS color. label is required (tooltip + accessible name). Memoize getStatus with useCallback.',
|
|
26
|
+
propDescriptions: {
|
|
27
|
+
getStatus:
|
|
28
|
+
'Map a row to {color, icon?, label} or null. color = semantic status name (mapped to a token) or raw CSS; icon = shape signifier (a11y); label = required accessible name (tooltip + role="img"). Memoize with useCallback.',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -6,7 +6,8 @@ export const docs = {
|
|
|
6
6
|
name: 'useTableSelection',
|
|
7
7
|
subComponentOf: 'Table',
|
|
8
8
|
displayName: 'useTableSelection',
|
|
9
|
-
description:
|
|
9
|
+
description:
|
|
10
|
+
'Hook that returns a TablePlugin implementing row selection with checkboxes, select-all, and aria-selected. Uses React Context for independent checkbox re-renders.',
|
|
10
11
|
props: [
|
|
11
12
|
{
|
|
12
13
|
name: 'getIsItemSelected',
|
|
@@ -17,7 +18,8 @@ export const docs = {
|
|
|
17
18
|
{
|
|
18
19
|
name: 'onSelectItem',
|
|
19
20
|
type: '(event: {item: T; isSelected: boolean}) => void',
|
|
20
|
-
description:
|
|
21
|
+
description:
|
|
22
|
+
'Called when a row checkbox is toggled. isSelected is the new desired state.',
|
|
21
23
|
required: true,
|
|
22
24
|
},
|
|
23
25
|
{
|
|
@@ -29,33 +31,67 @@ export const docs = {
|
|
|
29
31
|
{
|
|
30
32
|
name: 'getIsAllSelected',
|
|
31
33
|
type: '() => boolean',
|
|
32
|
-
description:
|
|
34
|
+
description:
|
|
35
|
+
'Returns whether all selectable items are currently selected.',
|
|
33
36
|
required: true,
|
|
34
37
|
},
|
|
35
38
|
{
|
|
36
39
|
name: 'getIsIndeterminate',
|
|
37
40
|
type: '() => boolean',
|
|
38
|
-
description:
|
|
41
|
+
description:
|
|
42
|
+
'Returns whether selection is partial (some but not all). Renders the select-all checkbox in indeterminate state.',
|
|
39
43
|
},
|
|
40
44
|
{
|
|
41
45
|
name: 'getIsItemSelectable',
|
|
42
46
|
type: '(item: T) => boolean',
|
|
43
|
-
description:
|
|
47
|
+
description:
|
|
48
|
+
'Returns whether a row should show a checkbox. Non-selectable rows render nothing in the selection cell.',
|
|
44
49
|
default: '() => true',
|
|
45
50
|
},
|
|
46
51
|
{
|
|
47
52
|
name: 'getIsItemEnabled',
|
|
48
53
|
type: '(item: T) => boolean',
|
|
49
|
-
description:
|
|
54
|
+
description:
|
|
55
|
+
'Returns whether a row checkbox is interactive. Disabled rows show a disabled checkbox.',
|
|
50
56
|
default: '() => true',
|
|
51
57
|
},
|
|
58
|
+
{
|
|
59
|
+
name: 'getRowLabel',
|
|
60
|
+
type: '(item: T) => string',
|
|
61
|
+
description:
|
|
62
|
+
'Derives a human-readable identity for a row; the row checkbox\'s hidden label becomes `Select ${getRowLabel(item)}` so screen readers announce which row each checkbox selects. Falls back to "Select row" when omitted.',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
examples: [
|
|
66
|
+
{
|
|
67
|
+
label: 'Accessible per-row checkbox names',
|
|
68
|
+
code: `
|
|
69
|
+
const selectionPlugin = useTableSelection({
|
|
70
|
+
getIsItemSelected: item => selectedIds.has(item.id),
|
|
71
|
+
onSelectItem: ({item, isSelected}) => toggle(item.id, isSelected),
|
|
72
|
+
onSelectAll: ({isAllSelected}) => selectAll(isAllSelected),
|
|
73
|
+
getIsAllSelected: () => selectedIds.size === users.length,
|
|
74
|
+
// Screen readers announce "Select Alice", "Select Bob", ...
|
|
75
|
+
// instead of an undifferentiated "Select row" for every checkbox.
|
|
76
|
+
getRowLabel: item => item.name,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
<Table
|
|
80
|
+
data={users}
|
|
81
|
+
columns={columns}
|
|
82
|
+
idKey="id"
|
|
83
|
+
plugins={{selection: selectionPlugin}}
|
|
84
|
+
/>;
|
|
85
|
+
`,
|
|
86
|
+
},
|
|
52
87
|
],
|
|
53
88
|
};
|
|
54
89
|
|
|
55
90
|
export const docsZh = {
|
|
56
91
|
name: 'useTableSelection',
|
|
57
92
|
displayName: 'useTableSelection',
|
|
58
|
-
description:
|
|
93
|
+
description:
|
|
94
|
+
'返回 TablePlugin 的 Hook,实现带复选框、全选和 aria-selected 的行选择功能。使用 React Context 实现独立的复选框重新渲染。',
|
|
59
95
|
props: [
|
|
60
96
|
{
|
|
61
97
|
name: 'getIsItemSelected',
|
|
@@ -84,12 +120,14 @@ export const docsZh = {
|
|
|
84
120
|
{
|
|
85
121
|
name: 'getIsIndeterminate',
|
|
86
122
|
type: '() => boolean',
|
|
87
|
-
description:
|
|
123
|
+
description:
|
|
124
|
+
'返回选择是否为部分选中(部分但非全部)。将全选复选框渲染为不确定状态。',
|
|
88
125
|
},
|
|
89
126
|
{
|
|
90
127
|
name: 'getIsItemSelectable',
|
|
91
128
|
type: '(item: T) => boolean',
|
|
92
|
-
description:
|
|
129
|
+
description:
|
|
130
|
+
'返回行是否应显示复选框。不可选择的行在选择单元格中不渲染任何内容。',
|
|
93
131
|
default: '() => true',
|
|
94
132
|
},
|
|
95
133
|
{
|
|
@@ -98,20 +136,33 @@ export const docsZh = {
|
|
|
98
136
|
description: '返回行复选框是否可交互。禁用的行显示禁用状态的复选框。',
|
|
99
137
|
default: '() => true',
|
|
100
138
|
},
|
|
139
|
+
{
|
|
140
|
+
name: 'getRowLabel',
|
|
141
|
+
type: '(item: T) => string',
|
|
142
|
+
description:
|
|
143
|
+
'为行派生人类可读的标识;行复选框的隐藏标签变为 `Select ${getRowLabel(item)}`,让屏幕阅读器播报每个复选框选择的是哪一行。省略时回退为 "Select row"。',
|
|
144
|
+
},
|
|
101
145
|
],
|
|
102
146
|
};
|
|
103
147
|
|
|
104
148
|
export const docsDense = {
|
|
105
149
|
name: 'useTableSelection',
|
|
106
150
|
displayName: 'useTableSelection',
|
|
107
|
-
description:
|
|
151
|
+
description:
|
|
152
|
+
'Hook returning TablePlugin for row selection w/ checkboxes, select-all, aria-selected. Uses React Context for independent checkbox re-renders.',
|
|
108
153
|
propDescriptions: {
|
|
109
154
|
getIsItemSelected: 'Returns whether item is selected.',
|
|
110
|
-
onSelectItem:
|
|
155
|
+
onSelectItem:
|
|
156
|
+
'Called on row checkbox toggle; isSelected = new desired state.',
|
|
111
157
|
onSelectAll: 'Called on select-all header checkbox toggle.',
|
|
112
158
|
getIsAllSelected: 'Returns whether all selectable items are selected.',
|
|
113
|
-
getIsIndeterminate:
|
|
114
|
-
|
|
115
|
-
|
|
159
|
+
getIsIndeterminate:
|
|
160
|
+
'Returns partial selection state; renders indeterminate checkbox.',
|
|
161
|
+
getIsItemSelectable:
|
|
162
|
+
'Returns whether row shows checkbox; non-selectable rows render nothing.',
|
|
163
|
+
getIsItemEnabled:
|
|
164
|
+
'Returns whether row checkbox is interactive; disabled rows show disabled checkbox.',
|
|
165
|
+
getRowLabel:
|
|
166
|
+
'Derives row identity for the checkbox\'s hidden label: `Select ${getRowLabel(item)}`. Falls back to "Select row" when omitted.',
|
|
116
167
|
},
|
|
117
168
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'useTableTreeData',
|
|
7
|
+
subComponentOf: 'Table',
|
|
8
|
+
displayName: 'useTableTreeData',
|
|
9
|
+
description:
|
|
10
|
+
'Headless tree plugin for Table: renders nested rows with per-level indentation and expand/collapse chevrons in the tree column (the first column by default), and reflects hierarchy on body rows via aria-level and aria-expanded. Composable with the other Table plugins: the canonical plugin order places tree before selection, so the checkbox column lands left of the indented tree column. Feed it the treeConfig from useTableTreeState, or construct the config directly for server-driven or pre-flattened trees. When no row is expandable (flat data), every transform is a pass-through and the table renders identically to one without the plugin. Known limitation: the tree column wraps its cell content, so textOverflow="truncate" tooltips do not apply within the tree column.',
|
|
11
|
+
props: [
|
|
12
|
+
{
|
|
13
|
+
name: 'getRowMeta',
|
|
14
|
+
type: '(item: T) => TableTreeRowMeta | undefined',
|
|
15
|
+
description:
|
|
16
|
+
'Structural meta for a visible row: {id, level (0-based), hasChildren, isExpanded}.',
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'onToggleItem',
|
|
21
|
+
type: '(item: T) => void',
|
|
22
|
+
description: 'Toggle a row\'s expansion.',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'hasExpandableRows',
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
description:
|
|
29
|
+
'Whether any row in the dataset is expandable. When false the plugin is a no-op: no expanders, no indent, no tree ARIA.',
|
|
30
|
+
required: true,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'indent',
|
|
34
|
+
type: "'sm' | 'md' | 'lg'",
|
|
35
|
+
description:
|
|
36
|
+
'Indent step per level, mapped to the spacing-3 / spacing-4 / spacing-6 tokens.',
|
|
37
|
+
default: "'md'",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'treeColumnKey',
|
|
41
|
+
type: 'string',
|
|
42
|
+
description:
|
|
43
|
+
'Column that carries the indent + expander. Defaults to the first column.',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
examples: [
|
|
47
|
+
{
|
|
48
|
+
label: 'File tree with expandable folders',
|
|
49
|
+
code: `const {visibleData, treeConfig} = useTableTreeState({
|
|
50
|
+
data: files, // rows may nest under 'children'
|
|
51
|
+
idKey: 'id',
|
|
52
|
+
defaultExpandedIds: ['src'],
|
|
53
|
+
});
|
|
54
|
+
const tree = useTableTreeData(treeConfig);
|
|
55
|
+
|
|
56
|
+
<Table data={visibleData} columns={columns} idKey="id" plugins={{tree}} />;`,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const docsDense = {
|
|
62
|
+
name: 'useTableTreeData',
|
|
63
|
+
displayName: 'useTableTreeData',
|
|
64
|
+
description:
|
|
65
|
+
'Headless tree plugin: indent + expander chevron on the tree column (first column by default), aria-level/aria-expanded on body rows. Canonical plugin order puts tree before selection (checkbox column lands left of tree column). Consume treeConfig from useTableTreeState, or construct directly for server-driven trees. hasExpandableRows=false => full no-op (flat-data migration).',
|
|
66
|
+
propDescriptions: {
|
|
67
|
+
getRowMeta:
|
|
68
|
+
'structural meta per visible row: {id, level (0-based), hasChildren, isExpanded}',
|
|
69
|
+
onToggleItem: 'toggle row expansion',
|
|
70
|
+
hasExpandableRows: 'false => plugin is a no-op (no expanders/indent/ARIA)',
|
|
71
|
+
indent:
|
|
72
|
+
"indent step per level: 'sm' | 'md' | 'lg' (spacing-3/4/6). Defaults to 'md'.",
|
|
73
|
+
treeColumnKey: 'column carrying indent + expander. Defaults to first column.',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'useTableTreeState',
|
|
7
|
+
subComponentOf: 'Table',
|
|
8
|
+
displayName: 'useTableTreeState',
|
|
9
|
+
description:
|
|
10
|
+
'State management companion for useTableTreeData. Owns the expanded set (controlled or uncontrolled) and flattens nested data into the visible row array; collapsed subtrees are unmounted, not hidden, so the table body contains exactly the visible rows. Returns expandAll/collapseAll helpers and a ready-to-use config for the tree plugin. Note: because collapsed rows unmount, cell-local React state inside collapsed subtrees is lost on collapse; lift state that must survive.',
|
|
11
|
+
props: [
|
|
12
|
+
{
|
|
13
|
+
name: 'data',
|
|
14
|
+
type: 'T[]',
|
|
15
|
+
description:
|
|
16
|
+
'Nested data: rows may carry child rows under childrenKey. Flat data (no children anywhere) makes the plugin a no-op, so it can be adopted before the data becomes hierarchical.',
|
|
17
|
+
required: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'idKey',
|
|
21
|
+
type: '(keyof T & string) | ((item: T) => string | number)',
|
|
22
|
+
description:
|
|
23
|
+
'Row ID accessor: property name or function returning a unique id.',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'childrenKey',
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'Property holding each row\'s children array.',
|
|
30
|
+
default: "'children'",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'defaultExpandedIds',
|
|
34
|
+
type: 'Iterable<string>',
|
|
35
|
+
description:
|
|
36
|
+
'Initial expanded row ids for uncontrolled mode. Ignored when expandedIds is provided.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'expandedIds',
|
|
40
|
+
type: 'ReadonlySet<string>',
|
|
41
|
+
description:
|
|
42
|
+
'Controlled set of expanded row ids. Pair with onExpandedIdsChange.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'onExpandedIdsChange',
|
|
46
|
+
type: '(ids: ReadonlySet<string>) => void',
|
|
47
|
+
description:
|
|
48
|
+
'Called with the next expanded set whenever expansion changes (both modes). In lazy-loading setups, trigger the children fetch here.',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'isItemExpandable',
|
|
52
|
+
type: '(item: T) => boolean',
|
|
53
|
+
description:
|
|
54
|
+
'Should this row show an expander? Overrides the default non-empty-children check; use for lazy loading, where a row is expandable before its children have been fetched.',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'sortSiblings',
|
|
58
|
+
type: '(siblings: T[]) => T[]',
|
|
59
|
+
description:
|
|
60
|
+
'Sort each sibling group independently during flattening; children always stay directly under their parent. Pass applySort from useTableSortableState to compose with column sorting.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'indent',
|
|
64
|
+
type: "'sm' | 'md' | 'lg'",
|
|
65
|
+
description:
|
|
66
|
+
'Indent step per level (spacing-3 / spacing-4 / spacing-6), forwarded to useTableTreeData.',
|
|
67
|
+
default: "'md'",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'treeColumnKey',
|
|
71
|
+
type: 'string',
|
|
72
|
+
description:
|
|
73
|
+
'Column that carries the indent + expander, forwarded to useTableTreeData. Defaults to the first column.',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const docsDense = {
|
|
79
|
+
name: 'useTableTreeState',
|
|
80
|
+
displayName: 'useTableTreeState',
|
|
81
|
+
description:
|
|
82
|
+
'State companion for useTableTreeData. Owns expanded set (controlled or uncontrolled), flattens nested data to visible rows (collapsed subtrees unmounted, not hidden). Returns {visibleData, treeConfig, expandedIds, expandAll, collapseAll}. Cell-local state in collapsed subtrees is lost on collapse; lift state that must survive.',
|
|
83
|
+
propDescriptions: {
|
|
84
|
+
data: 'nested data; rows carry child rows under childrenKey. Flat data => plugin is a no-op.',
|
|
85
|
+
idKey: 'row ID accessor: property name or fn returning unique id',
|
|
86
|
+
childrenKey: "property holding children array. Defaults to 'children'.",
|
|
87
|
+
defaultExpandedIds: 'initial expanded ids (uncontrolled)',
|
|
88
|
+
expandedIds: 'controlled expanded set; pair with onExpandedIdsChange',
|
|
89
|
+
onExpandedIdsChange:
|
|
90
|
+
'called with next expanded set on change (both modes); trigger lazy children fetch here',
|
|
91
|
+
isItemExpandable:
|
|
92
|
+
'overrides non-empty-children expandability check (lazy loading)',
|
|
93
|
+
sortSiblings:
|
|
94
|
+
'sorts each sibling group during flattening; pass applySort from useTableSortableState',
|
|
95
|
+
indent: "indent step per level: 'sm' | 'md' | 'lg'. Defaults to 'md'.",
|
|
96
|
+
treeColumnKey: 'column carrying indent + expander. Defaults to first column.',
|
|
97
|
+
},
|
|
98
|
+
};
|
|
@@ -116,7 +116,7 @@ export const docs = {
|
|
|
116
116
|
name: 'startIcon',
|
|
117
117
|
type: 'IconType',
|
|
118
118
|
description:
|
|
119
|
-
'Icon component rendered inside the leading edge of the textarea wrapper. See `
|
|
119
|
+
'Icon component rendered inside the leading edge of the textarea wrapper. See `astryx docs icons` for valid semantic names.',
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
name: 'hasSpellCheck',
|
|
@@ -10,11 +10,19 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {useState} from 'react';
|
|
13
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
14
14
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
15
15
|
import userEvent from '@testing-library/user-event';
|
|
16
16
|
import {TestIcon} from '../__tests__/TestIcon';
|
|
17
17
|
import {TextArea} from './TextArea';
|
|
18
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
19
|
+
|
|
20
|
+
// FieldStatus announces status messages through the persistent useAnnounce
|
|
21
|
+
// singletons; remove them between tests so role/aria-live queries in this
|
|
22
|
+
// file never match a leftover region.
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
__resetLiveRegionsForTest();
|
|
25
|
+
});
|
|
18
26
|
|
|
19
27
|
// Mock showPopover/hidePopover since jsdom does not implement them. Used by the
|
|
20
28
|
// disabledMessage tooltip.
|
|
@@ -106,7 +106,7 @@ export const docs = {
|
|
|
106
106
|
name: 'startIcon',
|
|
107
107
|
type: 'IconType',
|
|
108
108
|
description:
|
|
109
|
-
'SVG icon component displayed at the start of the input. See `
|
|
109
|
+
'SVG icon component displayed at the start of the input. See `astryx docs icons` for valid semantic names.',
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
112
|
name: 'status',
|