@astryxdesign/core 0.1.8 → 0.1.9
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 +100 -0
- 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 +18 -2
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +63 -7
- package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- 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/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
- package/dist/Breadcrumbs/index.d.ts +5 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +9 -1
- 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/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +30 -2
- package/dist/Calendar/dayCellUtils.js +1 -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 +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +24 -4
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- 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 +35 -3
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +1 -1
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +18 -9
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +8 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +3 -1
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- 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/DateInput/DateInput.d.ts +47 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +26 -2
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +10 -1
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +2 -3
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +42 -15
- 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 +7 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- 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 +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- 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/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- 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 +16 -13
- 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 +19 -2
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +3 -2
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- 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 +13 -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/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +87 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -4
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- 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/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- 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/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +2 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +10 -4
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +27 -7
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/astryx.css +28 -18
- package/dist/astryx.umd.js +51 -51
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.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/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- 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 +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +53 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +24 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +18 -0
- package/package.json +1 -1
- 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 +15 -3
- package/src/Avatar/Avatar.test.tsx +156 -1
- package/src/Avatar/Avatar.tsx +96 -4
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +178 -21
- 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/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
- package/src/Breadcrumbs/index.ts +27 -0
- 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/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +193 -0
- package/src/Calendar/Calendar.tsx +38 -16
- package/src/Calendar/dayCellUtils.test.ts +5 -0
- package/src/Calendar/dayCellUtils.ts +1 -1
- 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 +53 -0
- package/src/Carousel/Carousel.tsx +34 -4
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -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 +103 -0
- package/src/Chat/ChatComposerInput.tsx +49 -3
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +4 -1
- package/src/Chat/ChatLayout.tsx +3 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +25 -4
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +3 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +9 -1
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.tsx +3 -1
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- 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 +193 -0
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.test.tsx +108 -0
- package/src/DateInput/DateInput.tsx +68 -3
- package/src/DateInput/index.ts +1 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
- package/src/DateTimeInput/DateTimeInput.tsx +14 -2
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +6 -5
- package/src/Field/FieldLabel.tsx +8 -0
- 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 +3 -2
- package/src/Icon/Icon.tsx +7 -2
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/List/List.test.tsx +9 -8
- 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 +172 -3
- package/src/MultiSelector/MultiSelector.tsx +55 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NumberInput/NumberInput.test.tsx +11 -7
- package/src/NumberInput/NumberInput.tsx +1 -2
- package/src/Outline/Outline.tsx +0 -1
- 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/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
- package/src/PowerSearch/PowerSearch.test.tsx +20 -0
- 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 +29 -16
- package/src/Selector/Selector.test.tsx +69 -0
- package/src/Selector/Selector.tsx +5 -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.tsx +5 -1
- package/src/Slider/Slider.test.tsx +75 -2
- package/src/Slider/Slider.tsx +21 -5
- package/src/Switch/Switch.test.tsx +32 -1
- package/src/Table/BaseTable.tsx +3 -5
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- 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 +19 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +128 -1
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.test.tsx +9 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +141 -41
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.test.tsx +76 -1
- package/src/TimeInput/TimeInput.tsx +19 -6
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -1
- package/src/Tokenizer/Tokenizer.test.tsx +183 -2
- package/src/Tokenizer/Tokenizer.tsx +16 -4
- package/src/TopNav/TopNav.test.tsx +125 -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/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +22 -0
- package/src/TreeList/TreeList.test.tsx +232 -0
- package/src/TreeList/TreeList.tsx +18 -2
- package/src/TreeList/TreeListBranches.tsx +16 -2
- package/src/TreeList/TreeListItem.tsx +51 -11
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/authoring/doc.ts +1 -3
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/resolve.ts +9 -21
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/generateThemeRules.test.ts +65 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/plainDate.test.ts +22 -0
- package/src/utils/plainDate.ts +61 -0
- package/src/utils/types.ts +14 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useTableRowStatus.tsx
|
|
7
|
+
* @input React, StyleX, Icon, Table types
|
|
8
|
+
* @output Exports useTableRowStatus hook + config type
|
|
9
|
+
* @position Row-status plugin; consumed by Table via plugins prop
|
|
10
|
+
*
|
|
11
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
12
|
+
* - /packages/core/src/Table/index.ts (exports)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {useMemo} from 'react';
|
|
16
|
+
import * as stylex from '@stylexjs/stylex';
|
|
17
|
+
import {Icon, type IconColor, type IconName} from '../../../Icon';
|
|
18
|
+
import {Tooltip} from '../../../Tooltip';
|
|
19
|
+
import type {TableColumn, TablePlugin} from '../../types';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Semantic status colors, resolved to the design system's icon color tokens.
|
|
23
|
+
* Prefer these over raw CSS so status colors stay consistent with the theme.
|
|
24
|
+
*/
|
|
25
|
+
export type TableRowStatusColor =
|
|
26
|
+
| 'accent'
|
|
27
|
+
| 'success'
|
|
28
|
+
| 'error'
|
|
29
|
+
| 'warning'
|
|
30
|
+
| 'red'
|
|
31
|
+
| 'orange'
|
|
32
|
+
| 'green'
|
|
33
|
+
| 'yellow'
|
|
34
|
+
| 'blue'
|
|
35
|
+
| 'gray';
|
|
36
|
+
|
|
37
|
+
const SEMANTIC_COLORS: Record<TableRowStatusColor, string> = {
|
|
38
|
+
accent: 'var(--color-icon-accent)',
|
|
39
|
+
success: 'var(--color-icon-green)',
|
|
40
|
+
error: 'var(--color-icon-red)',
|
|
41
|
+
warning: 'var(--color-icon-orange)',
|
|
42
|
+
red: 'var(--color-icon-red)',
|
|
43
|
+
orange: 'var(--color-icon-orange)',
|
|
44
|
+
green: 'var(--color-icon-green)',
|
|
45
|
+
yellow: 'var(--color-icon-yellow)',
|
|
46
|
+
blue: 'var(--color-icon-blue)',
|
|
47
|
+
gray: 'var(--color-icon-gray)',
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Icon colors that map cleanly from a semantic status color. */
|
|
51
|
+
const ICON_COLOR_BY_STATUS: Record<TableRowStatusColor, IconColor> = {
|
|
52
|
+
accent: 'accent',
|
|
53
|
+
success: 'success',
|
|
54
|
+
error: 'error',
|
|
55
|
+
warning: 'warning',
|
|
56
|
+
red: 'red',
|
|
57
|
+
orange: 'warning',
|
|
58
|
+
green: 'green',
|
|
59
|
+
yellow: 'warning',
|
|
60
|
+
blue: 'blue',
|
|
61
|
+
gray: 'gray',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A row's status indicator. `color` accepts a semantic status color
|
|
66
|
+
* (mapped to a theme token) or any raw CSS color string as an escape hatch.
|
|
67
|
+
* By default the plugin renders a colored status dot. Provide `icon` to signal
|
|
68
|
+
* status by shape as well as color, which is more accessible when several
|
|
69
|
+
* statuses coexist. `label` is required so the status is never conveyed by
|
|
70
|
+
* color alone — it names the indicator for assistive technology and shows on
|
|
71
|
+
* hover. Return `null` for rows with no status.
|
|
72
|
+
*/
|
|
73
|
+
export interface TableRowStatus {
|
|
74
|
+
/** Semantic status color (preferred) or a raw CSS color string. */
|
|
75
|
+
color: TableRowStatusColor | (string & {});
|
|
76
|
+
/** Optional icon rendered as the signifier instead of the dot (shape as an a11y differentiator). */
|
|
77
|
+
icon?: IconName;
|
|
78
|
+
/**
|
|
79
|
+
* Accessible name for the status, announced to assistive technology and
|
|
80
|
+
* shown in a tooltip on hover. Required: a status must never be conveyed by
|
|
81
|
+
* color alone.
|
|
82
|
+
*/
|
|
83
|
+
label: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Configuration for {@link useTableRowStatus}. */
|
|
87
|
+
export interface UseTableRowStatusConfig<T extends Record<string, unknown>> {
|
|
88
|
+
/**
|
|
89
|
+
* Derive the status indicator for a row. Return `null` for no indicator.
|
|
90
|
+
* Memoize with `useCallback` for a stable plugin identity across renders.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```
|
|
94
|
+
* getStatus: row =>
|
|
95
|
+
* row.hasError ? {color: 'error', icon: 'error', label: 'Error'} : null
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
getStatus: (item: T) => TableRowStatus | null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The status column holds a small centered dot (or an icon when provided).
|
|
102
|
+
// A fixed narrow width keeps every row's indicator aligned in one gutter.
|
|
103
|
+
const STATUS_COLUMN_WIDTH = {type: 'pixel' as const, value: 28};
|
|
104
|
+
|
|
105
|
+
/** Resolve a semantic color name to a token, or pass a raw CSS color through. */
|
|
106
|
+
function resolveColor(color: string): string {
|
|
107
|
+
return (SEMANTIC_COLORS as Record<string, string>)[color] ?? color;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const styles = stylex.create({
|
|
111
|
+
// Centers the dot or icon within the narrow status column.
|
|
112
|
+
wrap: {
|
|
113
|
+
display: 'flex',
|
|
114
|
+
alignItems: 'center',
|
|
115
|
+
justifyContent: 'center',
|
|
116
|
+
},
|
|
117
|
+
dot: (color: string) => ({
|
|
118
|
+
width: '8px',
|
|
119
|
+
height: '8px',
|
|
120
|
+
borderRadius: '50%',
|
|
121
|
+
backgroundColor: color,
|
|
122
|
+
flexShrink: 0,
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Returns a {@link TablePlugin} that prepends a narrow column signaling per-row
|
|
128
|
+
* status: a colored status dot by default, or an icon when `icon` is provided
|
|
129
|
+
* (shape + color is more accessible than color alone).
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```
|
|
133
|
+
* const rowStatus = useTableRowStatus<Row>({
|
|
134
|
+
* getStatus: row =>
|
|
135
|
+
* row.state === 'error'
|
|
136
|
+
* ? {color: 'error', icon: 'error', label: 'Error'}
|
|
137
|
+
* : null,
|
|
138
|
+
* });
|
|
139
|
+
* <Table data={data} columns={columns} idKey="id" plugins={{rowStatus}} />;
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export function useTableRowStatus<T extends Record<string, unknown>>(
|
|
143
|
+
config: UseTableRowStatusConfig<T>,
|
|
144
|
+
): TablePlugin<T> {
|
|
145
|
+
const {getStatus} = config;
|
|
146
|
+
|
|
147
|
+
return useMemo(
|
|
148
|
+
(): TablePlugin<T> => ({
|
|
149
|
+
transformColumns(columns) {
|
|
150
|
+
const statusColumn: TableColumn<T> = {
|
|
151
|
+
key: '__rowStatus',
|
|
152
|
+
header: '',
|
|
153
|
+
width: STATUS_COLUMN_WIDTH,
|
|
154
|
+
resizable: false,
|
|
155
|
+
renderCell: (item: T) => {
|
|
156
|
+
const status = getStatus(item);
|
|
157
|
+
if (!status) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const signifier = status.icon ? (
|
|
161
|
+
<Icon
|
|
162
|
+
icon={status.icon}
|
|
163
|
+
size="xsm"
|
|
164
|
+
color={
|
|
165
|
+
ICON_COLOR_BY_STATUS[status.color as TableRowStatusColor] ??
|
|
166
|
+
'primary'
|
|
167
|
+
}
|
|
168
|
+
/>
|
|
169
|
+
) : (
|
|
170
|
+
<span {...stylex.props(styles.dot(resolveColor(status.color)))} />
|
|
171
|
+
);
|
|
172
|
+
return (
|
|
173
|
+
<Tooltip content={status.label}>
|
|
174
|
+
<span
|
|
175
|
+
{...stylex.props(styles.wrap)}
|
|
176
|
+
role="img"
|
|
177
|
+
aria-label={status.label}>
|
|
178
|
+
{signifier}
|
|
179
|
+
</span>
|
|
180
|
+
</Tooltip>
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
return [statusColumn, ...columns];
|
|
185
|
+
},
|
|
186
|
+
}),
|
|
187
|
+
[getStatus],
|
|
188
|
+
);
|
|
189
|
+
}
|
|
@@ -40,9 +40,11 @@ const selectableColumns: TableColumn<SelectableUser>[] = [
|
|
|
40
40
|
function SelectionTable({
|
|
41
41
|
getIsItemSelectable,
|
|
42
42
|
getIsItemEnabled,
|
|
43
|
+
getRowLabel,
|
|
43
44
|
}: {
|
|
44
45
|
getIsItemSelectable?: (item: SelectableUser) => boolean;
|
|
45
46
|
getIsItemEnabled?: (item: SelectableUser) => boolean;
|
|
47
|
+
getRowLabel?: (item: SelectableUser) => string;
|
|
46
48
|
}) {
|
|
47
49
|
const [selectedKeys, setSelectedKeys] = useState<Set<string>>(new Set());
|
|
48
50
|
|
|
@@ -75,6 +77,7 @@ function SelectionTable({
|
|
|
75
77
|
},
|
|
76
78
|
getIsItemSelectable,
|
|
77
79
|
getIsItemEnabled,
|
|
80
|
+
getRowLabel,
|
|
78
81
|
});
|
|
79
82
|
|
|
80
83
|
return (
|
|
@@ -109,6 +112,19 @@ describe('useTableSelection', () => {
|
|
|
109
112
|
expect(rowCheckboxes).toHaveLength(3);
|
|
110
113
|
});
|
|
111
114
|
|
|
115
|
+
it('derives per-row accessible names from getRowLabel', () => {
|
|
116
|
+
render(<SelectionTable getRowLabel={item => item.name} />);
|
|
117
|
+
expect(screen.getByLabelText('Select Alice')).toBeInTheDocument();
|
|
118
|
+
expect(screen.getByLabelText('Select Bob')).toBeInTheDocument();
|
|
119
|
+
expect(screen.getByLabelText('Select Charlie')).toBeInTheDocument();
|
|
120
|
+
expect(screen.queryByLabelText('Select row')).not.toBeInTheDocument();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('keeps the "Select all rows" header label when getRowLabel is provided', () => {
|
|
124
|
+
render(<SelectionTable getRowLabel={item => item.name} />);
|
|
125
|
+
expect(screen.getByLabelText('Select all rows')).toBeInTheDocument();
|
|
126
|
+
});
|
|
127
|
+
|
|
112
128
|
it('toggles individual row selection on click', async () => {
|
|
113
129
|
const user = userEvent.setup();
|
|
114
130
|
render(<SelectionTable />);
|
|
@@ -68,6 +68,19 @@ export interface UseTableSelectionConfig<T extends Record<string, unknown>> {
|
|
|
68
68
|
getIsItemSelectable?: (item: T) => boolean;
|
|
69
69
|
/** Is this row's checkbox interactive? Disabled rows show disabled checkbox. @default () => true */
|
|
70
70
|
getIsItemEnabled?: (item: T) => boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Derive a human-readable identity for a row, used in the row checkbox's
|
|
73
|
+
* hidden label as `Select ${getRowLabel(item)}`. Without it, every row
|
|
74
|
+
* checkbox announces an undifferentiated "Select row" to screen readers.
|
|
75
|
+
* With `getRowLabel: item => item.name`, checkbox accessible names become
|
|
76
|
+
* "Select Alice", "Select Bob", and so on.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```
|
|
80
|
+
* getRowLabel: item => item.name
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
getRowLabel?: (item: T) => string;
|
|
71
84
|
}
|
|
72
85
|
|
|
73
86
|
// =============================================================================
|
|
@@ -235,6 +248,7 @@ function SelectionCellContentInner<T extends Record<string, unknown>>({
|
|
|
235
248
|
const isSelected = useIsItemSelected(store, item);
|
|
236
249
|
const selectable = config.getIsItemSelectable?.(item) ?? true;
|
|
237
250
|
const enabled = config.getIsItemEnabled?.(item) ?? true;
|
|
251
|
+
const rowLabel = config.getRowLabel?.(item);
|
|
238
252
|
|
|
239
253
|
if (!selectable) {
|
|
240
254
|
return null;
|
|
@@ -242,7 +256,11 @@ function SelectionCellContentInner<T extends Record<string, unknown>>({
|
|
|
242
256
|
|
|
243
257
|
return (
|
|
244
258
|
<CheckboxInput
|
|
245
|
-
label={
|
|
259
|
+
label={
|
|
260
|
+
rowLabel != null
|
|
261
|
+
? t('@astryx.table.selection.selectRowNamed', {label: rowLabel})
|
|
262
|
+
: t('@astryx.table.selection.selectRow')
|
|
263
|
+
}
|
|
246
264
|
isLabelHidden
|
|
247
265
|
value={isSelected}
|
|
248
266
|
onChange={() =>
|
|
@@ -55,14 +55,18 @@ const columns: TableColumn<FileRow>[] = [
|
|
|
55
55
|
];
|
|
56
56
|
|
|
57
57
|
function TreeTable(
|
|
58
|
-
props: Partial<UseTableTreeStateConfig<FileRow>> & {
|
|
58
|
+
props: Partial<UseTableTreeStateConfig<FileRow>> & {
|
|
59
|
+
data?: FileRow[];
|
|
60
|
+
hasExpandAllControl?: boolean;
|
|
61
|
+
},
|
|
59
62
|
) {
|
|
63
|
+
const {hasExpandAllControl, ...stateProps} = props;
|
|
60
64
|
const {visibleData, treeConfig} = useTableTreeState<FileRow>({
|
|
61
65
|
data: props.data ?? fileTree,
|
|
62
66
|
idKey: 'id',
|
|
63
|
-
...
|
|
67
|
+
...stateProps,
|
|
64
68
|
});
|
|
65
|
-
const tree = useTableTreeData(treeConfig);
|
|
69
|
+
const tree = useTableTreeData({...treeConfig, hasExpandAllControl});
|
|
66
70
|
|
|
67
71
|
return (
|
|
68
72
|
<Table data={visibleData} columns={columns} idKey="id" plugins={{tree}} />
|
|
@@ -592,3 +596,131 @@ describe('useTableTreeData — composition with sorting', () => {
|
|
|
592
596
|
expect(names).toEqual(['src', 'utils.ts', 'components', 'README.md']);
|
|
593
597
|
});
|
|
594
598
|
});
|
|
599
|
+
|
|
600
|
+
// =============================================================================
|
|
601
|
+
// header expand-all control
|
|
602
|
+
// =============================================================================
|
|
603
|
+
|
|
604
|
+
describe('useTableTreeData: expand-all header control', () => {
|
|
605
|
+
/** The header row is the first row; return its expand-all toggle if present. */
|
|
606
|
+
function queryExpandAllButton(): HTMLElement | null {
|
|
607
|
+
const headerRow = screen.getAllByRole('row')[0];
|
|
608
|
+
return (
|
|
609
|
+
within(headerRow).queryByRole('button', {name: /expand all/i}) ??
|
|
610
|
+
within(headerRow).queryByRole('button', {name: /collapse all/i})
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
it('renders no expand-all control by default', () => {
|
|
615
|
+
render(<TreeTable defaultExpandedIds={['src']} />);
|
|
616
|
+
expect(queryExpandAllButton()).toBeNull();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it('renders an "Expand all" toggle in the tree column header when enabled and collapsed', () => {
|
|
620
|
+
render(<TreeTable hasExpandAllControl />);
|
|
621
|
+
const headerRow = screen.getAllByRole('row')[0];
|
|
622
|
+
expect(
|
|
623
|
+
within(headerRow).getByRole('button', {name: /expand all/i}),
|
|
624
|
+
).toBeInTheDocument();
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
it('expands every row when the collapsed toggle is clicked', async () => {
|
|
628
|
+
const user = userEvent.setup();
|
|
629
|
+
render(<TreeTable hasExpandAllControl />);
|
|
630
|
+
|
|
631
|
+
// Collapsed: only roots are visible.
|
|
632
|
+
expect(getBodyRows()).toHaveLength(2);
|
|
633
|
+
|
|
634
|
+
await user.click(
|
|
635
|
+
within(screen.getAllByRole('row')[0]).getByRole('button', {
|
|
636
|
+
name: /expand all/i,
|
|
637
|
+
}),
|
|
638
|
+
);
|
|
639
|
+
|
|
640
|
+
// Every level is now visible.
|
|
641
|
+
expect(
|
|
642
|
+
getBodyRows().map(r => within(r).getByText(/.+/, {selector: 'td *'})),
|
|
643
|
+
).not.toHaveLength(2);
|
|
644
|
+
expect(screen.getByText('Button.tsx')).toBeInTheDocument();
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('relabels the toggle "Collapse all" once everything is expanded', () => {
|
|
648
|
+
render(
|
|
649
|
+
<TreeTable
|
|
650
|
+
hasExpandAllControl
|
|
651
|
+
defaultExpandedIds={['src', 'components']}
|
|
652
|
+
/>,
|
|
653
|
+
);
|
|
654
|
+
const headerRow = screen.getAllByRole('row')[0];
|
|
655
|
+
expect(
|
|
656
|
+
within(headerRow).getByRole('button', {name: /collapse all/i}),
|
|
657
|
+
).toBeInTheDocument();
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
it('collapses back to roots when the expanded toggle is clicked', async () => {
|
|
661
|
+
const user = userEvent.setup();
|
|
662
|
+
render(
|
|
663
|
+
<TreeTable
|
|
664
|
+
hasExpandAllControl
|
|
665
|
+
defaultExpandedIds={['src', 'components']}
|
|
666
|
+
/>,
|
|
667
|
+
);
|
|
668
|
+
expect(screen.getByText('Button.tsx')).toBeInTheDocument();
|
|
669
|
+
|
|
670
|
+
await user.click(
|
|
671
|
+
within(screen.getAllByRole('row')[0]).getByRole('button', {
|
|
672
|
+
name: /collapse all/i,
|
|
673
|
+
}),
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
expect(getBodyRows()).toHaveLength(2);
|
|
677
|
+
expect(screen.queryByText('Button.tsx')).not.toBeInTheDocument();
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it('marks the toggle aria-expanded=false in the indeterminate (partial) state', () => {
|
|
681
|
+
// 'src' expanded but 'components' not: partially expanded.
|
|
682
|
+
render(<TreeTable hasExpandAllControl defaultExpandedIds={['src']} />);
|
|
683
|
+
const headerRow = screen.getAllByRole('row')[0];
|
|
684
|
+
const toggle = within(headerRow).getByRole('button', {
|
|
685
|
+
name: /expand all/i,
|
|
686
|
+
});
|
|
687
|
+
expect(toggle).toHaveAttribute('aria-expanded', 'false');
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
it('does not render the control for flat data even when enabled', () => {
|
|
691
|
+
const flat: FileRow[] = [
|
|
692
|
+
{id: 'a', name: 'A', size: 1},
|
|
693
|
+
{id: 'b', name: 'B', size: 2},
|
|
694
|
+
];
|
|
695
|
+
render(<TreeTable data={flat} hasExpandAllControl />);
|
|
696
|
+
expect(queryExpandAllButton()).toBeNull();
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it('renders the toggle inline with the header label, not stacked above it', () => {
|
|
700
|
+
render(<TreeTable hasExpandAllControl />);
|
|
701
|
+
const headerRow = screen.getAllByRole('row')[0];
|
|
702
|
+
const toggle = within(headerRow).getByRole('button', {
|
|
703
|
+
name: /expand all/i,
|
|
704
|
+
});
|
|
705
|
+
// The tree column's <th> holds the label text ('Name'). The bug was that
|
|
706
|
+
// the toggle went into the `before` slot, which BaseTable renders as a
|
|
707
|
+
// block sibling of the label, stacking the chevron ABOVE the title. The
|
|
708
|
+
// fix wraps the label + toggle in one inline-flex container, so they must
|
|
709
|
+
// share the same immediate parent (the toggle is a sibling of the label,
|
|
710
|
+
// not in a separate stacked slot).
|
|
711
|
+
const th = toggle.closest('th');
|
|
712
|
+
expect(th).not.toBeNull();
|
|
713
|
+
const label = within(th as HTMLElement).getByText('Name');
|
|
714
|
+
const wrapper = label.parentElement as HTMLElement;
|
|
715
|
+
expect(wrapper).toContainElement(toggle);
|
|
716
|
+
// The toggle precedes the label within that shared wrapper (chevron sits
|
|
717
|
+
// to the LEFT of the title). StyleX compiles the inline-flex layout to a
|
|
718
|
+
// class on this wrapper; assert the class is present (real CSS is not
|
|
719
|
+
// applied in jsdom, so we check the class hook, not computed display).
|
|
720
|
+
expect(wrapper.className).not.toBe('');
|
|
721
|
+
const kids = Array.from(wrapper.childNodes);
|
|
722
|
+
expect(kids.indexOf(toggle)).toBeLessThan(
|
|
723
|
+
kids.findIndex(n => n.textContent === 'Name' || n.contains(label)),
|
|
724
|
+
);
|
|
725
|
+
});
|
|
726
|
+
});
|
|
@@ -43,7 +43,12 @@ import * as stylex from '@stylexjs/stylex';
|
|
|
43
43
|
import {colorVars, radiusVars, spacingVars} from '../../../theme/tokens.stylex';
|
|
44
44
|
import {Icon} from '../../../Icon';
|
|
45
45
|
import {mergeRefs} from '../../../utils';
|
|
46
|
-
import type {
|
|
46
|
+
import type {
|
|
47
|
+
TablePlugin,
|
|
48
|
+
TableColumn,
|
|
49
|
+
BodyRowRenderProps,
|
|
50
|
+
HeaderCellRenderProps,
|
|
51
|
+
} from '../../types';
|
|
47
52
|
import {useTranslator} from '../../../i18n';
|
|
48
53
|
|
|
49
54
|
// =============================================================================
|
|
@@ -78,6 +83,22 @@ export interface UseTableTreeDataConfig<T extends Record<string, unknown>> {
|
|
|
78
83
|
* identically to a Table without the plugin.
|
|
79
84
|
*/
|
|
80
85
|
hasExpandableRows: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Aggregate expansion state across every expandable row. When provided
|
|
88
|
+
* together with `onExpandAll`/`onCollapseAll`, the tree column header shows
|
|
89
|
+
* an expand-all toggle. `useTableTreeState` supplies all three.
|
|
90
|
+
*/
|
|
91
|
+
isAllExpanded?: boolean | 'indeterminate';
|
|
92
|
+
/** Expand every expandable row. Wired to the header expand-all control. */
|
|
93
|
+
onExpandAll?: () => void;
|
|
94
|
+
/** Collapse every row. Wired to the header expand-all control. */
|
|
95
|
+
onCollapseAll?: () => void;
|
|
96
|
+
/**
|
|
97
|
+
* Show the expand-all/collapse-all toggle in the tree column header. Needs
|
|
98
|
+
* `isAllExpanded` and `onExpandAll`/`onCollapseAll` to be present.
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
101
|
+
hasExpandAllControl?: boolean;
|
|
81
102
|
/**
|
|
82
103
|
* Indent step per level, as spacing tokens.
|
|
83
104
|
* @default 'md'
|
|
@@ -243,6 +264,13 @@ const treeStyles = stylex.create({
|
|
|
243
264
|
height: '24px',
|
|
244
265
|
flexShrink: '0',
|
|
245
266
|
},
|
|
267
|
+
/** Header expand-all toggle: same affordance as a row expander. */
|
|
268
|
+
headerCell: {
|
|
269
|
+
display: 'inline-flex',
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
gap: spacingVars['--spacing-1'],
|
|
272
|
+
minWidth: 0,
|
|
273
|
+
},
|
|
246
274
|
});
|
|
247
275
|
|
|
248
276
|
// =============================================================================
|
|
@@ -282,6 +310,53 @@ function TreeExpander({
|
|
|
282
310
|
);
|
|
283
311
|
}
|
|
284
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Header expand-all/collapse-all toggle. Rendered in the tree column header
|
|
315
|
+
* when `hasExpandAllControl` is set and the state hook supplies the aggregate
|
|
316
|
+
* `isAllExpanded` plus `onExpandAll`/`onCollapseAll`. Shares the chevron
|
|
317
|
+
* affordance with the per-row expander; the chevron points down (expanded)
|
|
318
|
+
* only when every expandable row is expanded, matching the row expander.
|
|
319
|
+
*/
|
|
320
|
+
function TreeExpandAllToggle({
|
|
321
|
+
isAllExpanded,
|
|
322
|
+
onExpandAll,
|
|
323
|
+
onCollapseAll,
|
|
324
|
+
}: {
|
|
325
|
+
isAllExpanded: boolean | 'indeterminate';
|
|
326
|
+
onExpandAll: () => void;
|
|
327
|
+
onCollapseAll: () => void;
|
|
328
|
+
}) {
|
|
329
|
+
const t = useTranslator();
|
|
330
|
+
const allExpanded = isAllExpanded === true;
|
|
331
|
+
return (
|
|
332
|
+
<button
|
|
333
|
+
type="button"
|
|
334
|
+
{...stylex.props(treeStyles.expanderButton)}
|
|
335
|
+
onClick={e => {
|
|
336
|
+
e.stopPropagation();
|
|
337
|
+
if (allExpanded) {
|
|
338
|
+
onCollapseAll();
|
|
339
|
+
} else {
|
|
340
|
+
onExpandAll();
|
|
341
|
+
}
|
|
342
|
+
}}
|
|
343
|
+
aria-label={
|
|
344
|
+
allExpanded
|
|
345
|
+
? t('@astryx.tableTree.collapseAllRows')
|
|
346
|
+
: t('@astryx.tableTree.expandAllRows')
|
|
347
|
+
}
|
|
348
|
+
aria-expanded={allExpanded}>
|
|
349
|
+
<span
|
|
350
|
+
{...stylex.props(
|
|
351
|
+
treeStyles.chevron,
|
|
352
|
+
allExpanded && treeStyles.chevronExpanded,
|
|
353
|
+
)}>
|
|
354
|
+
<Icon icon="chevronRight" size="xsm" />
|
|
355
|
+
</span>
|
|
356
|
+
</button>
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
285
360
|
function TreeCellContent<T extends Record<string, unknown>>({
|
|
286
361
|
item,
|
|
287
362
|
children,
|
|
@@ -380,6 +455,11 @@ export function useTableTreeData<T extends Record<string, unknown>>(
|
|
|
380
455
|
output: TableColumn<T>[];
|
|
381
456
|
} | null>(null);
|
|
382
457
|
|
|
458
|
+
// The resolved tree column key, written by transformColumns (pipeline step 1)
|
|
459
|
+
// and read by transformHeaderCell (step 4) to place the expand-all toggle on
|
|
460
|
+
// the same column that carries the row expanders.
|
|
461
|
+
const treeKeyRef = useRef<string | undefined>(undefined);
|
|
462
|
+
|
|
383
463
|
// The plugin object is created once per store and never changes shape:
|
|
384
464
|
// every transform reads the live config through the store, and
|
|
385
465
|
// internally no-ops when hasExpandableRows is false. Swapping between
|
|
@@ -426,6 +506,7 @@ export function useTableTreeData<T extends Record<string, unknown>>(
|
|
|
426
506
|
? treeColumnKey
|
|
427
507
|
: (columns.find(c => !c.key.startsWith('__'))?.key ??
|
|
428
508
|
columns[0]?.key);
|
|
509
|
+
treeKeyRef.current = treeKey;
|
|
429
510
|
|
|
430
511
|
// Migration guarantee: flat data renders identically to a Table
|
|
431
512
|
// without the plugin.
|
|
@@ -459,6 +540,52 @@ export function useTableTreeData<T extends Record<string, unknown>>(
|
|
|
459
540
|
return output;
|
|
460
541
|
},
|
|
461
542
|
|
|
543
|
+
transformHeaderCell(
|
|
544
|
+
props: HeaderCellRenderProps,
|
|
545
|
+
column: TableColumn<T>,
|
|
546
|
+
): HeaderCellRenderProps {
|
|
547
|
+
const {
|
|
548
|
+
hasExpandableRows,
|
|
549
|
+
hasExpandAllControl,
|
|
550
|
+
isAllExpanded,
|
|
551
|
+
onExpandAll,
|
|
552
|
+
onCollapseAll,
|
|
553
|
+
} = store.getConfig();
|
|
554
|
+
|
|
555
|
+
// Only the tree column carries the toggle, and only when the control
|
|
556
|
+
// is enabled, the data is actually hierarchical, and the state hook
|
|
557
|
+
// supplied the aggregate state plus both handlers. Otherwise this is a
|
|
558
|
+
// pass-through (flat data stays a no-op).
|
|
559
|
+
if (
|
|
560
|
+
!hasExpandAllControl ||
|
|
561
|
+
!hasExpandableRows ||
|
|
562
|
+
column.key !== treeKeyRef.current ||
|
|
563
|
+
isAllExpanded === undefined ||
|
|
564
|
+
!onExpandAll ||
|
|
565
|
+
!onCollapseAll
|
|
566
|
+
) {
|
|
567
|
+
return props;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Wrap the header label + the toggle in one inline-flex row so the
|
|
571
|
+
// chevron sits to the LEFT of the title on the same line. BaseTable
|
|
572
|
+
// only applies its own flex row for the `after` slot, so a bare
|
|
573
|
+
// `before` would stack above the label in the block-level <th>.
|
|
574
|
+
return {
|
|
575
|
+
...props,
|
|
576
|
+
content: (
|
|
577
|
+
<span {...stylex.props(treeStyles.headerCell)}>
|
|
578
|
+
<TreeExpandAllToggle
|
|
579
|
+
isAllExpanded={isAllExpanded}
|
|
580
|
+
onExpandAll={onExpandAll}
|
|
581
|
+
onCollapseAll={onCollapseAll}
|
|
582
|
+
/>
|
|
583
|
+
{props.content}
|
|
584
|
+
</span>
|
|
585
|
+
),
|
|
586
|
+
};
|
|
587
|
+
},
|
|
588
|
+
|
|
462
589
|
transformBodyRow(props: BodyRowRenderProps, item: T) {
|
|
463
590
|
// Attach a ref that subscribes to the store for imperative row
|
|
464
591
|
// ARIA. The ref returns a cleanup so React unsubscribes on
|