@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
|
@@ -351,6 +351,10 @@ export function SideNavHeading({
|
|
|
351
351
|
|
|
352
352
|
const popover = usePopover({
|
|
353
353
|
dialogLabel: t('@astryx.sideNav.heading.dialogLabel'),
|
|
354
|
+
// The popup exposes its own role="menu" semantics; a role="dialog"
|
|
355
|
+
// aria-modal wrapper would announce "dialog, Navigation menu" around a
|
|
356
|
+
// menu (the anti-pattern removed in a478a3dcf).
|
|
357
|
+
role: 'none',
|
|
354
358
|
hasCloseButton: false,
|
|
355
359
|
});
|
|
356
360
|
|
|
@@ -428,7 +432,6 @@ export function SideNavHeading({
|
|
|
428
432
|
{popover.render(
|
|
429
433
|
<div
|
|
430
434
|
ref={menuRef}
|
|
431
|
-
role="menu"
|
|
432
435
|
{...stylex.props(styles.popoverContent)}
|
|
433
436
|
{...contentProps}>
|
|
434
437
|
<button
|
|
@@ -461,9 +464,14 @@ export function SideNavHeading({
|
|
|
461
464
|
)}
|
|
462
465
|
</span>
|
|
463
466
|
</button>
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
+
{/* The menu role is scoped to the actual menu items so the
|
|
468
|
+
heading button above stays a valid sibling, not an invalid
|
|
469
|
+
child of a role="menu" element. */}
|
|
470
|
+
<div role="menu" aria-label={heading}>
|
|
471
|
+
<NavHeadingCloseContext value={closeMenuCtx}>
|
|
472
|
+
{menu}
|
|
473
|
+
</NavHeadingCloseContext>
|
|
474
|
+
</div>
|
|
467
475
|
</div>,
|
|
468
476
|
{placement: 'below', alignment: 'start', xstyle: styles.popover},
|
|
469
477
|
)}
|
|
@@ -620,11 +628,15 @@ export function SideNavHeading({
|
|
|
620
628
|
{popover.render(
|
|
621
629
|
<div
|
|
622
630
|
ref={menuRef}
|
|
623
|
-
role="menu"
|
|
624
631
|
{...stylex.props(styles.popoverContent)}
|
|
625
632
|
{...contentProps}>
|
|
626
633
|
{popoverHeadingContent}
|
|
627
|
-
{menu
|
|
634
|
+
{/* The menu role is scoped to the actual menu items so the
|
|
635
|
+
heading button above stays a valid sibling, not an invalid
|
|
636
|
+
child of a role="menu" element. */}
|
|
637
|
+
<div role="menu" aria-label={heading}>
|
|
638
|
+
{menu}
|
|
639
|
+
</div>
|
|
628
640
|
</div>,
|
|
629
641
|
{
|
|
630
642
|
placement: 'below',
|
|
@@ -683,11 +695,15 @@ export function SideNavHeading({
|
|
|
683
695
|
{popover.render(
|
|
684
696
|
<div
|
|
685
697
|
ref={menuRef}
|
|
686
|
-
role="menu"
|
|
687
698
|
{...stylex.props(styles.popoverContent)}
|
|
688
699
|
{...contentProps}>
|
|
689
700
|
{popoverHeadingContent}
|
|
690
|
-
{menu
|
|
701
|
+
{/* The menu role is scoped to the actual menu items so the
|
|
702
|
+
heading button above stays a valid sibling, not an invalid
|
|
703
|
+
child of a role="menu" element. */}
|
|
704
|
+
<div role="menu" aria-label={heading}>
|
|
705
|
+
{menu}
|
|
706
|
+
</div>
|
|
691
707
|
</div>,
|
|
692
708
|
{
|
|
693
709
|
placement: 'below',
|
|
@@ -628,7 +628,11 @@ export function SideNavItem({
|
|
|
628
628
|
<button
|
|
629
629
|
type="button"
|
|
630
630
|
onClick={handleToggleClick}
|
|
631
|
-
aria-label={
|
|
631
|
+
aria-label={
|
|
632
|
+
isItemCollapsed
|
|
633
|
+
? t('@astryx.sideNavItem.expand', {label})
|
|
634
|
+
: t('@astryx.sideNavItem.collapse', {label})
|
|
635
|
+
}
|
|
632
636
|
aria-expanded={!isItemCollapsed}
|
|
633
637
|
aria-controls={`${id}-children`}
|
|
634
638
|
{...stylex.props(styles.expandToggle)}>
|
|
@@ -85,6 +85,19 @@ describe('Slider', () => {
|
|
|
85
85
|
expect(slider).toHaveAttribute('aria-valuenow', '72');
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it.each([
|
|
89
|
+
{value: 150, expectedValue: 100, expectedPosition: '100%'},
|
|
90
|
+
{value: -50, expectedValue: 0, expectedPosition: '0%'},
|
|
91
|
+
])(
|
|
92
|
+
'clamps a controlled value of $value to $expectedValue',
|
|
93
|
+
({value, expectedValue, expectedPosition}) => {
|
|
94
|
+
render(<Slider label="Volume" value={value} min={0} max={100} />);
|
|
95
|
+
const slider = screen.getByRole('slider');
|
|
96
|
+
expect(slider).toHaveAttribute('aria-valuenow', String(expectedValue));
|
|
97
|
+
expect(slider).toHaveStyle({left: expectedPosition});
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
|
|
88
101
|
it('range mode sets correct aria values on both thumbs', () => {
|
|
89
102
|
render(
|
|
90
103
|
<Slider
|
|
@@ -155,6 +168,60 @@ describe('Slider', () => {
|
|
|
155
168
|
expect(ariaHidden.length).toBeGreaterThanOrEqual(2);
|
|
156
169
|
});
|
|
157
170
|
|
|
171
|
+
// --- Required state ---
|
|
172
|
+
|
|
173
|
+
it('conveys required state through the accessible description', () => {
|
|
174
|
+
render(<Slider label="Volume" value={50} isRequired />);
|
|
175
|
+
const slider = screen.getByRole('slider');
|
|
176
|
+
expect(slider).toHaveAccessibleDescription(/Required/);
|
|
177
|
+
// aria-required is not a supported property of role="slider" in
|
|
178
|
+
// WAI-ARIA 1.2, so it must never appear on the thumb.
|
|
179
|
+
expect(slider).not.toHaveAttribute('aria-required');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('conveys required state on both thumbs of a range slider', () => {
|
|
183
|
+
render(
|
|
184
|
+
<Slider
|
|
185
|
+
label="Price range"
|
|
186
|
+
value={[20, 80] as [number, number]}
|
|
187
|
+
isRequired
|
|
188
|
+
/>,
|
|
189
|
+
);
|
|
190
|
+
const sliders = screen.getAllByRole('slider');
|
|
191
|
+
expect(sliders).toHaveLength(2);
|
|
192
|
+
for (const thumb of sliders) {
|
|
193
|
+
expect(thumb).toHaveAccessibleDescription(/Required/);
|
|
194
|
+
expect(thumb).not.toHaveAttribute('aria-required');
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('combines required with other describedby parts in the description', () => {
|
|
199
|
+
render(
|
|
200
|
+
<Slider
|
|
201
|
+
label="Volume"
|
|
202
|
+
value={50}
|
|
203
|
+
description="Adjust the volume level"
|
|
204
|
+
isRequired
|
|
205
|
+
/>,
|
|
206
|
+
);
|
|
207
|
+
const slider = screen.getByRole('slider');
|
|
208
|
+
expect(slider).toHaveAccessibleDescription(/Adjust the volume level/);
|
|
209
|
+
expect(slider).toHaveAccessibleDescription(/Required/);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('does not mention required without isRequired', () => {
|
|
213
|
+
render(
|
|
214
|
+
<Slider
|
|
215
|
+
label="Volume"
|
|
216
|
+
value={50}
|
|
217
|
+
description="Adjust the volume level"
|
|
218
|
+
/>,
|
|
219
|
+
);
|
|
220
|
+
const slider = screen.getByRole('slider');
|
|
221
|
+
expect(slider).not.toHaveAccessibleDescription(/Required/);
|
|
222
|
+
expect(slider).not.toHaveAttribute('aria-required');
|
|
223
|
+
});
|
|
224
|
+
|
|
158
225
|
// --- Disabled guards ---
|
|
159
226
|
|
|
160
227
|
it('disables thumbs when isDisabled is true', () => {
|
|
@@ -549,7 +616,11 @@ describe('Slider', () => {
|
|
|
549
616
|
it('submits both range values under the same name', () => {
|
|
550
617
|
const {container} = render(
|
|
551
618
|
<form>
|
|
552
|
-
<Slider
|
|
619
|
+
<Slider
|
|
620
|
+
label="Price"
|
|
621
|
+
htmlName="price"
|
|
622
|
+
value={[20, 80] as [number, number]}
|
|
623
|
+
/>
|
|
553
624
|
</form>,
|
|
554
625
|
);
|
|
555
626
|
const data = new FormData(container.querySelector('form')!);
|
|
@@ -562,7 +633,9 @@ describe('Slider', () => {
|
|
|
562
633
|
<Slider label="Volume" htmlName="volume" value={50} isDisabled />
|
|
563
634
|
</form>,
|
|
564
635
|
);
|
|
565
|
-
expect([
|
|
636
|
+
expect([
|
|
637
|
+
...new FormData(container.querySelector('form')!).keys(),
|
|
638
|
+
]).toEqual([]);
|
|
566
639
|
});
|
|
567
640
|
});
|
|
568
641
|
});
|
package/src/Slider/Slider.tsx
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file Slider.tsx
|
|
7
|
-
* @input Uses React, useId, useRef, useCallback, Field, Tooltip, useTooltip
|
|
7
|
+
* @input Uses React, useId, useRef, useCallback, Field, Tooltip, useTooltip, VisuallyHidden
|
|
8
8
|
* @output Exports Slider component, SliderProps, SliderSingleProps, SliderRangeProps, SliderBaseProps
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by Slider.test.tsx
|
|
10
10
|
*
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
import {Field} from '../Field/Field';
|
|
39
39
|
import {Tooltip} from '../Tooltip/Tooltip';
|
|
40
40
|
import {useTooltip} from '../Tooltip';
|
|
41
|
+
import {VisuallyHidden} from '../VisuallyHidden';
|
|
41
42
|
import type {InputStatus} from '../Field/types';
|
|
42
43
|
import {mergeProps, mergeRefs} from '../utils';
|
|
43
44
|
import type {BaseProps} from '../BaseProps';
|
|
@@ -393,6 +394,7 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
393
394
|
const id = useId();
|
|
394
395
|
const descriptionID = useId();
|
|
395
396
|
const statusMessageID = useId();
|
|
397
|
+
const requiredID = useId();
|
|
396
398
|
|
|
397
399
|
const trackRef = useRef<HTMLDivElement>(null);
|
|
398
400
|
const draggingThumbRef = useRef<number | null>(null);
|
|
@@ -412,6 +414,12 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
412
414
|
isEnabled: showsDisabledMessage,
|
|
413
415
|
});
|
|
414
416
|
|
|
417
|
+
// Required state. `aria-required` is not a supported property of
|
|
418
|
+
// role="slider" in WAI-ARIA 1.2, so the thumb instead points its
|
|
419
|
+
// aria-describedby at a visually hidden "Required" span — mirroring the
|
|
420
|
+
// Field label's visible indicator (where isOptional takes precedence).
|
|
421
|
+
const conveysRequired = isRequired && !isOptional;
|
|
422
|
+
|
|
415
423
|
// Build aria-describedby
|
|
416
424
|
const describedByParts: string[] = [];
|
|
417
425
|
if (description) {
|
|
@@ -420,6 +428,9 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
420
428
|
if (status?.message) {
|
|
421
429
|
describedByParts.push(statusMessageID);
|
|
422
430
|
}
|
|
431
|
+
if (conveysRequired) {
|
|
432
|
+
describedByParts.push(requiredID);
|
|
433
|
+
}
|
|
423
434
|
if (showsDisabledMessage) {
|
|
424
435
|
describedByParts.push(disabledMessageTooltip.describedBy);
|
|
425
436
|
}
|
|
@@ -428,10 +439,12 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
428
439
|
|
|
429
440
|
// Value helpers — guard against undefined value (e.g. playground previews
|
|
430
441
|
// that render the component without providing a value prop).
|
|
431
|
-
const values: number[] = useMemo(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
442
|
+
const values: number[] = useMemo(() => {
|
|
443
|
+
const currentValues = Array.isArray(value)
|
|
444
|
+
? value
|
|
445
|
+
: [value != null ? value : min];
|
|
446
|
+
return currentValues.map(currentValue => clamp(currentValue, min, max));
|
|
447
|
+
}, [value, min, max]);
|
|
435
448
|
|
|
436
449
|
const valuesRef = useRef(values);
|
|
437
450
|
valuesRef.current = values;
|
|
@@ -921,6 +934,9 @@ export function Slider({ref, ...props}: SliderProps) {
|
|
|
921
934
|
|
|
922
935
|
{textDisplay}
|
|
923
936
|
</div>
|
|
937
|
+
{conveysRequired && (
|
|
938
|
+
<VisuallyHidden id={requiredID}>Required</VisuallyHidden>
|
|
939
|
+
)}
|
|
924
940
|
{showsDisabledMessage &&
|
|
925
941
|
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
926
942
|
</Field>
|
|
@@ -9,10 +9,15 @@
|
|
|
9
9
|
* SYNC: When Switch.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
13
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {Switch} from './Switch';
|
|
16
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
__resetLiveRegionsForTest();
|
|
20
|
+
});
|
|
16
21
|
|
|
17
22
|
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
18
23
|
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
@@ -324,6 +329,32 @@ describe('Switch', () => {
|
|
|
324
329
|
expect(describedBy).toBeTruthy();
|
|
325
330
|
});
|
|
326
331
|
|
|
332
|
+
// Regression: the status is conditionally mounted, so it must be announced
|
|
333
|
+
// through the persistent useAnnounce live region — a live region born
|
|
334
|
+
// together with its content is not reliably announced.
|
|
335
|
+
it('announces a status message that appears after mount', async () => {
|
|
336
|
+
const {rerender} = render(
|
|
337
|
+
<Switch label="Enable notifications" value={false} onChange={() => {}} />,
|
|
338
|
+
);
|
|
339
|
+
expect(
|
|
340
|
+
document.querySelector('[data-astryx-live-region="assertive"]'),
|
|
341
|
+
).toBeNull();
|
|
342
|
+
|
|
343
|
+
rerender(
|
|
344
|
+
<Switch
|
|
345
|
+
label="Enable notifications"
|
|
346
|
+
value={false}
|
|
347
|
+
onChange={() => {}}
|
|
348
|
+
status={{type: 'error', message: 'Failed to save setting'}}
|
|
349
|
+
/>,
|
|
350
|
+
);
|
|
351
|
+
await waitFor(() => {
|
|
352
|
+
expect(
|
|
353
|
+
document.querySelector('[data-astryx-live-region="assertive"]'),
|
|
354
|
+
).toHaveTextContent('Failed to save setting');
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
327
358
|
it('calls onFocus and onBlur callbacks', async () => {
|
|
328
359
|
const user = userEvent.setup();
|
|
329
360
|
const handleFocus = vi.fn();
|
package/src/Table/BaseTable.tsx
CHANGED
|
@@ -42,6 +42,7 @@ import {TableHeaderCell} from './TableHeaderCell';
|
|
|
42
42
|
import {TableHeader} from './TableHeader';
|
|
43
43
|
import {TableBody} from './TableBody';
|
|
44
44
|
import {mergeProps} from '../utils';
|
|
45
|
+
import {devError} from '../utils/devWarning';
|
|
45
46
|
import {EmptyState} from '../EmptyState';
|
|
46
47
|
import {Text} from '../Text';
|
|
47
48
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -92,10 +93,7 @@ function applyPlugins<TPlugin, TProps, TArgs extends unknown[]>(
|
|
|
92
93
|
try {
|
|
93
94
|
return transform(acc, ...args);
|
|
94
95
|
} catch (error) {
|
|
95
|
-
|
|
96
|
-
`[Table] Plugin at index ${index} threw in transform:`,
|
|
97
|
-
error,
|
|
98
|
-
);
|
|
96
|
+
devError('Table', `Plugin at index ${index} threw in transform:`, error);
|
|
99
97
|
return acc;
|
|
100
98
|
}
|
|
101
99
|
}, initial);
|
|
@@ -593,7 +591,7 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
593
591
|
try {
|
|
594
592
|
tableElement = plugin.transformTableContext(tableElement);
|
|
595
593
|
} catch (error) {
|
|
596
|
-
|
|
594
|
+
devError('Table', 'Plugin threw in transformTableContext:', error);
|
|
597
595
|
}
|
|
598
596
|
}
|
|
599
597
|
}
|
package/src/Table/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ export {useTableColumnResize} from './plugins/columnResize';
|
|
|
28
28
|
export {useTableStickyColumns} from './plugins/stickyColumns';
|
|
29
29
|
export {useTableGroupedRows} from './plugins/groupedRows';
|
|
30
30
|
export {useTableRowIndex} from './plugins/rowIndex';
|
|
31
|
+
export {useTableRowStatus} from './plugins/rowStatus';
|
|
31
32
|
export {
|
|
32
33
|
useTableRowExpansion,
|
|
33
34
|
useTableRowExpansionState,
|
|
@@ -110,6 +111,10 @@ export type {
|
|
|
110
111
|
UseTableGroupedRowsConfig,
|
|
111
112
|
UseTableGroupedRowsResult,
|
|
112
113
|
} from './plugins/groupedRows';
|
|
114
|
+
export type {
|
|
115
|
+
UseTableRowStatusConfig,
|
|
116
|
+
TableRowStatus,
|
|
117
|
+
} from './plugins/rowStatus';
|
|
113
118
|
export type {
|
|
114
119
|
TableTreeRowMeta,
|
|
115
120
|
UseTableTreeDataConfig,
|
|
@@ -325,8 +325,12 @@ export function useTableGroupedRows<T extends Record<string, unknown>>(
|
|
|
325
325
|
}}
|
|
326
326
|
aria-label={
|
|
327
327
|
collapsed
|
|
328
|
-
? t('@astryx.tableGroupedRows.expandGroup', {
|
|
329
|
-
|
|
328
|
+
? t('@astryx.tableGroupedRows.expandGroup', {
|
|
329
|
+
groupKey: header.groupKey,
|
|
330
|
+
})
|
|
331
|
+
: t('@astryx.tableGroupedRows.collapseGroup', {
|
|
332
|
+
groupKey: header.groupKey,
|
|
333
|
+
})
|
|
330
334
|
}
|
|
331
335
|
aria-expanded={!collapsed}>
|
|
332
336
|
<span
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, it, expect} from 'vitest';
|
|
4
|
+
import {render, screen, within} from '@testing-library/react';
|
|
5
|
+
import {Table} from '../../Table';
|
|
6
|
+
import type {TableColumn} from '../../types';
|
|
7
|
+
import {useTableRowStatus, type TableRowStatus} from './useTableRowStatus';
|
|
8
|
+
|
|
9
|
+
interface Row extends Record<string, unknown> {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
state: 'error' | 'warning' | 'ok' | 'done';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const data: Row[] = [
|
|
16
|
+
{id: 'a', name: 'Alice', state: 'error'},
|
|
17
|
+
{id: 'b', name: 'Bob', state: 'ok'},
|
|
18
|
+
{id: 'c', name: 'Carol', state: 'warning'},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const columns: TableColumn<Row>[] = [{key: 'name', header: 'Name'}];
|
|
22
|
+
|
|
23
|
+
function getStatus(item: Row): TableRowStatus | null {
|
|
24
|
+
if (item.state === 'error') {
|
|
25
|
+
return {color: 'red', label: 'Error'};
|
|
26
|
+
}
|
|
27
|
+
if (item.state === 'warning') {
|
|
28
|
+
return {color: 'orange', label: 'Warning'};
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function Harness({
|
|
34
|
+
rows = data,
|
|
35
|
+
statusFn = getStatus,
|
|
36
|
+
}: {
|
|
37
|
+
rows?: Row[];
|
|
38
|
+
statusFn?: (item: Row) => TableRowStatus | null;
|
|
39
|
+
}) {
|
|
40
|
+
const rowStatus = useTableRowStatus<Row>({getStatus: statusFn});
|
|
41
|
+
return (
|
|
42
|
+
<Table data={rows} columns={columns} idKey="id" plugins={{rowStatus}} />
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
describe('useTableRowStatus', () => {
|
|
47
|
+
it('prepends a narrow status column with an empty header', () => {
|
|
48
|
+
render(<Harness />);
|
|
49
|
+
const headers = screen.getAllByRole('columnheader');
|
|
50
|
+
// Status column is first; its header is empty.
|
|
51
|
+
expect(headers[0]).toHaveAttribute('data-column-key', '__rowStatus');
|
|
52
|
+
expect(headers[0].textContent).toBe('');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('renders a labeled dot for rows with a status', () => {
|
|
56
|
+
render(<Harness />);
|
|
57
|
+
expect(screen.getByRole('img', {name: 'Error'})).toBeInTheDocument();
|
|
58
|
+
expect(screen.getByRole('img', {name: 'Warning'})).toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('renders a dot (not an icon) by default', () => {
|
|
62
|
+
render(<Harness />);
|
|
63
|
+
// Default (no icon) renders a plain colored dot: no svg in the indicator.
|
|
64
|
+
const dot = screen.getByRole('img', {name: 'Error'});
|
|
65
|
+
expect(dot.querySelector('svg')).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('renders no indicator for rows returning null', () => {
|
|
69
|
+
render(<Harness />);
|
|
70
|
+
const rows = screen.getAllByRole('row');
|
|
71
|
+
// rows[2] is Bob (state ok): no status indicator in his status cell.
|
|
72
|
+
const bob = rows[2];
|
|
73
|
+
expect(within(bob).getByText('Bob')).toBeInTheDocument();
|
|
74
|
+
expect(within(bob).queryByRole('img')).not.toBeInTheDocument();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('maps a semantic color name to its icon color token', () => {
|
|
78
|
+
render(<Harness />);
|
|
79
|
+
const errorDot = screen.getByRole('img', {name: 'Error'});
|
|
80
|
+
// 'red' resolves to var(--color-icon-red); StyleX emits it on the inline
|
|
81
|
+
// style of the inner dot element.
|
|
82
|
+
const dot = errorDot.querySelector('span');
|
|
83
|
+
expect(dot?.getAttribute('style')).toContain('--color-icon-red');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('passes through a raw CSS color as an escape hatch', () => {
|
|
87
|
+
render(
|
|
88
|
+
<Harness
|
|
89
|
+
statusFn={item =>
|
|
90
|
+
item.state === 'error' ? {color: 'rgb(1, 2, 3)', label: 'Raw'} : null
|
|
91
|
+
}
|
|
92
|
+
/>,
|
|
93
|
+
);
|
|
94
|
+
const indicator = screen.getByRole('img', {name: 'Raw'});
|
|
95
|
+
const dot = indicator.querySelector('span');
|
|
96
|
+
expect(dot?.getAttribute('style')).toContain('rgb(1, 2, 3)');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('renders an icon as the status signifier when icon is provided', () => {
|
|
100
|
+
render(
|
|
101
|
+
<Harness
|
|
102
|
+
statusFn={item =>
|
|
103
|
+
item.state === 'error'
|
|
104
|
+
? {color: 'red', icon: 'error', label: 'Error'}
|
|
105
|
+
: null
|
|
106
|
+
}
|
|
107
|
+
/>,
|
|
108
|
+
);
|
|
109
|
+
// Icon-mode still exposes the accessible label via role=img.
|
|
110
|
+
const indicator = screen.getByRole('img', {name: 'Error'});
|
|
111
|
+
expect(indicator).toBeInTheDocument();
|
|
112
|
+
// An SVG icon is rendered inside the indicator (dot mode has no svg).
|
|
113
|
+
expect(indicator.querySelector('svg')).not.toBeNull();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('exposes the required label as the accessible name in dot mode', () => {
|
|
117
|
+
render(
|
|
118
|
+
<Harness
|
|
119
|
+
statusFn={item =>
|
|
120
|
+
item.state === 'error' ? {color: 'red', label: 'Error'} : null
|
|
121
|
+
}
|
|
122
|
+
/>,
|
|
123
|
+
);
|
|
124
|
+
// Label is required, so every dot is announced via role=img with its name.
|
|
125
|
+
const indicator = screen.getByRole('img', {name: 'Error'});
|
|
126
|
+
expect(indicator).toBeInTheDocument();
|
|
127
|
+
// Dot mode renders no svg (that is icon mode).
|
|
128
|
+
expect(indicator.querySelector('svg')).toBeNull();
|
|
129
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('renders the status header with empty data and no indicators', () => {
|
|
133
|
+
render(<Harness rows={[]} />);
|
|
134
|
+
const headers = screen.getAllByRole('columnheader');
|
|
135
|
+
expect(headers[0]).toHaveAttribute('data-column-key', '__rowStatus');
|
|
136
|
+
expect(screen.queryByRole('img')).not.toBeInTheDocument();
|
|
137
|
+
});
|
|
138
|
+
});
|