@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
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
import {render, screen, fireEvent, act} from '@testing-library/react';
|
|
14
14
|
import React, {useState} from 'react';
|
|
15
15
|
import {PowerSearch} from './PowerSearch';
|
|
16
|
+
import {PowerSearchEditPopover} from './PowerSearchEditPopover';
|
|
17
|
+
import {useInternalConfig} from './useInternalConfig';
|
|
16
18
|
import type {PowerSearchConfig, PowerSearchFilter} from './types';
|
|
17
19
|
|
|
18
20
|
// =============================================================================
|
|
@@ -216,4 +218,69 @@ describe('PowerSearch', () => {
|
|
|
216
218
|
expect(popoverText).toContain('Priority');
|
|
217
219
|
expect(popoverText).toContain('equals');
|
|
218
220
|
});
|
|
221
|
+
|
|
222
|
+
it('does not save/close edit popover when Enter is consumed by child listbox option selection', () => {
|
|
223
|
+
const multiConfig: PowerSearchConfig = {
|
|
224
|
+
name: 'test-multi',
|
|
225
|
+
fields: [
|
|
226
|
+
{
|
|
227
|
+
key: 'status',
|
|
228
|
+
label: 'Status',
|
|
229
|
+
operators: [
|
|
230
|
+
{
|
|
231
|
+
key: 'any_of',
|
|
232
|
+
label: 'is any of',
|
|
233
|
+
value: {
|
|
234
|
+
type: 'enum_list',
|
|
235
|
+
values: [
|
|
236
|
+
{value: 'open', label: 'Open'},
|
|
237
|
+
{value: 'closed', label: 'Closed'},
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const onSave = vi.fn();
|
|
247
|
+
const onCancel = vi.fn();
|
|
248
|
+
|
|
249
|
+
function MultiSelectHarness() {
|
|
250
|
+
const internalConfig = useInternalConfig(multiConfig);
|
|
251
|
+
return (
|
|
252
|
+
<PowerSearchEditPopover
|
|
253
|
+
config={internalConfig}
|
|
254
|
+
filter={{
|
|
255
|
+
field: 'status',
|
|
256
|
+
operator: 'any_of',
|
|
257
|
+
value: {type: 'enum_list', value: ['open']},
|
|
258
|
+
}}
|
|
259
|
+
mode="edit"
|
|
260
|
+
onSave={onSave}
|
|
261
|
+
onCancel={onCancel}
|
|
262
|
+
/>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const {container} = render(<MultiSelectHarness />);
|
|
267
|
+
|
|
268
|
+
const input = container.querySelector('input');
|
|
269
|
+
expect(input).not.toBeNull();
|
|
270
|
+
|
|
271
|
+
// Fire an Enter event that has been defaultPrevented (e.g. child typeahead option selection)
|
|
272
|
+
const enterEvent = new KeyboardEvent('keydown', {
|
|
273
|
+
key: 'Enter',
|
|
274
|
+
bubbles: true,
|
|
275
|
+
cancelable: true,
|
|
276
|
+
});
|
|
277
|
+
enterEvent.preventDefault();
|
|
278
|
+
|
|
279
|
+
act(() => {
|
|
280
|
+
input?.dispatchEvent(enterEvent);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// onSave should NOT be called because the event was already consumed (defaultPrevented)
|
|
284
|
+
expect(onSave).not.toHaveBeenCalled();
|
|
285
|
+
});
|
|
219
286
|
});
|
|
@@ -702,7 +702,7 @@ export function PowerSearchEditPopover({
|
|
|
702
702
|
// Handle Enter to save, Escape to cancel
|
|
703
703
|
const handleKeyDown = useCallback(
|
|
704
704
|
(e: React.KeyboardEvent) => {
|
|
705
|
-
if (e.key === 'Enter' && !isSaveDisabled) {
|
|
705
|
+
if (e.key === 'Enter' && !isSaveDisabled && !e.defaultPrevented) {
|
|
706
706
|
e.preventDefault();
|
|
707
707
|
handleSave();
|
|
708
708
|
} else if (e.key === 'Escape' && !e.defaultPrevented) {
|
|
@@ -76,8 +76,7 @@ export function usePowerSearchSource(
|
|
|
76
76
|
|
|
77
77
|
// Check each field+operator combo against the query
|
|
78
78
|
for (const op of field.operators) {
|
|
79
|
-
const combinedLabel =
|
|
80
|
-
`${field.label} ${opLabel(op)}`.toLowerCase();
|
|
79
|
+
const combinedLabel = `${field.label} ${opLabel(op)}`.toLowerCase();
|
|
81
80
|
if (combinedLabel.includes(lower)) {
|
|
82
81
|
const id = `${field.key}:${op.key}`;
|
|
83
82
|
if (!seen.has(id)) {
|
|
@@ -27,6 +27,7 @@ export const docs = {
|
|
|
27
27
|
{name: 'children', type: 'ReactNode', description: 'Card content.'},
|
|
28
28
|
{name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: 'Inner padding.', default: '4'},
|
|
29
29
|
{name: 'variant', type: "'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow'", description: 'Background color variant.', default: "'default'"},
|
|
30
|
+
{name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: 'Resting shadow depth. The selection ring composes on top, so a selected card keeps its shadow.', default: "'none'"},
|
|
30
31
|
{name: 'width', type: 'SizeValue', description: 'Card width.'},
|
|
31
32
|
{name: 'height', type: 'SizeValue', description: 'Card height.'},
|
|
32
33
|
{name: 'maxWidth', type: 'SizeValue', description: 'Maximum card width.'},
|
|
@@ -71,6 +72,7 @@ export const docsDense = {
|
|
|
71
72
|
isDisabled: 'disables card',
|
|
72
73
|
padding: 'inner padding',
|
|
73
74
|
variant: 'background color variant',
|
|
75
|
+
elevation: 'resting shadow depth: none|low|med|high; selection ring composes on top',
|
|
74
76
|
width: 'card width',
|
|
75
77
|
height: 'card height',
|
|
76
78
|
maxWidth: 'max card width',
|
|
@@ -85,8 +85,7 @@ describe('SelectableCard', () => {
|
|
|
85
85
|
label="Disabled"
|
|
86
86
|
isSelected={false}
|
|
87
87
|
onChange={handleChange}
|
|
88
|
-
isDisabled
|
|
89
|
-
>
|
|
88
|
+
isDisabled>
|
|
90
89
|
Content
|
|
91
90
|
</SelectableCard>,
|
|
92
91
|
);
|
|
@@ -101,12 +100,55 @@ describe('SelectableCard', () => {
|
|
|
101
100
|
label="Disabled"
|
|
102
101
|
isSelected={false}
|
|
103
102
|
onChange={handleChange}
|
|
104
|
-
isDisabled
|
|
105
|
-
>
|
|
103
|
+
isDisabled>
|
|
106
104
|
<span>Content</span>
|
|
107
105
|
</SelectableCard>,
|
|
108
106
|
);
|
|
109
107
|
fireEvent.click(screen.getByText('Content'));
|
|
110
108
|
expect(handleChange).not.toHaveBeenCalled();
|
|
111
109
|
});
|
|
110
|
+
|
|
111
|
+
describe('elevation', () => {
|
|
112
|
+
const noop = () => {};
|
|
113
|
+
|
|
114
|
+
it('forwards a distinct elevation class to the card for each level', () => {
|
|
115
|
+
const classFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
|
|
116
|
+
const {container} = render(
|
|
117
|
+
<SelectableCard
|
|
118
|
+
label="Card"
|
|
119
|
+
isSelected={false}
|
|
120
|
+
onChange={noop}
|
|
121
|
+
elevation={elevation}>
|
|
122
|
+
Content
|
|
123
|
+
</SelectableCard>,
|
|
124
|
+
);
|
|
125
|
+
return container.firstElementChild!.className;
|
|
126
|
+
};
|
|
127
|
+
const classes = new Set([
|
|
128
|
+
classFor('none'),
|
|
129
|
+
classFor('low'),
|
|
130
|
+
classFor('med'),
|
|
131
|
+
classFor('high'),
|
|
132
|
+
]);
|
|
133
|
+
expect(classes.size).toBe(4);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('still varies elevation while selected (ring composes with elevation)', () => {
|
|
137
|
+
const selectedClassFor = (elevation: 'none' | 'med') => {
|
|
138
|
+
const {container} = render(
|
|
139
|
+
<SelectableCard
|
|
140
|
+
label="Card"
|
|
141
|
+
isSelected
|
|
142
|
+
onChange={noop}
|
|
143
|
+
elevation={elevation}>
|
|
144
|
+
Content
|
|
145
|
+
</SelectableCard>,
|
|
146
|
+
);
|
|
147
|
+
return container.firstElementChild!.className;
|
|
148
|
+
};
|
|
149
|
+
// A selected card at 'med' must differ from a selected card at 'none' —
|
|
150
|
+
// proving the selection ring does not clobber the elevation shadow.
|
|
151
|
+
expect(selectedClassFor('med')).not.toBe(selectedClassFor('none'));
|
|
152
|
+
});
|
|
153
|
+
});
|
|
112
154
|
});
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - /apps/storybook/stories/SelectableCard.stories.tsx (storybook stories)
|
|
15
15
|
* - /packages/cli/templates/blocks/components/Card/SelectableCardShowcase.tsx (showcase block)
|
|
16
16
|
* - /packages/cli/templates/blocks/components/Card/SelectableCardMulti.tsx (block)
|
|
17
|
+
* - /packages/cli/templates/blocks/components/Card/SelectableCardElevated.tsx (block)
|
|
17
18
|
*
|
|
18
19
|
* Composes Card for all visual styling. Adds selection state with
|
|
19
20
|
* an inset box-shadow (zero layout jitter) and useClickableContainer
|
|
@@ -36,7 +37,7 @@ import {
|
|
|
36
37
|
import * as stylex from '@stylexjs/stylex';
|
|
37
38
|
import type {StyleXStyles} from '@stylexjs/stylex';
|
|
38
39
|
import {colorVars, durationVars, easeVars} from '../theme/tokens.stylex';
|
|
39
|
-
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
40
|
+
import type {Elevation, SizeValue, SpacingStep} from '../utils/types';
|
|
40
41
|
import {mergeProps, mergeRefs} from '../utils';
|
|
41
42
|
import {Card} from '../Card/Card';
|
|
42
43
|
import type {CardVariant} from '../Card/Card';
|
|
@@ -78,13 +79,13 @@ const styles = stylex.create({
|
|
|
78
79
|
backgroundColor: 'transparent',
|
|
79
80
|
},
|
|
80
81
|
':active::after': {
|
|
81
|
-
backgroundColor: 'color-
|
|
82
|
+
backgroundColor: colorVars['--color-overlay-pressed'],
|
|
82
83
|
},
|
|
83
84
|
},
|
|
84
85
|
hoverOnPointer: {
|
|
85
86
|
'@media (hover: hover)': {
|
|
86
87
|
':hover::after': {
|
|
87
|
-
backgroundColor: 'color-
|
|
88
|
+
backgroundColor: colorVars['--color-overlay-hover'],
|
|
88
89
|
},
|
|
89
90
|
},
|
|
90
91
|
},
|
|
@@ -103,51 +104,54 @@ const styles = stylex.create({
|
|
|
103
104
|
whiteSpace: 'nowrap',
|
|
104
105
|
borderWidth: 0,
|
|
105
106
|
},
|
|
106
|
-
// Selection indicator — inset
|
|
107
|
-
// jitter) plus borderColor change on the card's
|
|
107
|
+
// Selection indicator — an inset ring drawn via the card's --_card-ring
|
|
108
|
+
// shadow slot (zero layout jitter) plus a borderColor change on the card's
|
|
109
|
+
// own border for a cohesive look. Routing the ring through --_card-ring
|
|
110
|
+
// (rather than box-shadow directly) lets it compose with the card's
|
|
111
|
+
// elevation instead of clobbering it.
|
|
108
112
|
selected: {
|
|
109
113
|
borderColor: colorVars['--color-accent'],
|
|
110
|
-
|
|
114
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-accent']}`,
|
|
111
115
|
},
|
|
112
116
|
selectedBlue: {
|
|
113
117
|
borderColor: colorVars['--color-border-blue'],
|
|
114
|
-
|
|
118
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-blue']}`,
|
|
115
119
|
},
|
|
116
120
|
selectedCyan: {
|
|
117
121
|
borderColor: colorVars['--color-border-cyan'],
|
|
118
|
-
|
|
122
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-cyan']}`,
|
|
119
123
|
},
|
|
120
124
|
selectedGray: {
|
|
121
125
|
borderColor: colorVars['--color-border-gray'],
|
|
122
|
-
|
|
126
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-gray']}`,
|
|
123
127
|
},
|
|
124
128
|
selectedGreen: {
|
|
125
129
|
borderColor: colorVars['--color-border-green'],
|
|
126
|
-
|
|
130
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-green']}`,
|
|
127
131
|
},
|
|
128
132
|
selectedOrange: {
|
|
129
133
|
borderColor: colorVars['--color-border-orange'],
|
|
130
|
-
|
|
134
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-orange']}`,
|
|
131
135
|
},
|
|
132
136
|
selectedPink: {
|
|
133
137
|
borderColor: colorVars['--color-border-pink'],
|
|
134
|
-
|
|
138
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-pink']}`,
|
|
135
139
|
},
|
|
136
140
|
selectedPurple: {
|
|
137
141
|
borderColor: colorVars['--color-border-purple'],
|
|
138
|
-
|
|
142
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-purple']}`,
|
|
139
143
|
},
|
|
140
144
|
selectedRed: {
|
|
141
145
|
borderColor: colorVars['--color-border-red'],
|
|
142
|
-
|
|
146
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-red']}`,
|
|
143
147
|
},
|
|
144
148
|
selectedTeal: {
|
|
145
149
|
borderColor: colorVars['--color-border-teal'],
|
|
146
|
-
|
|
150
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-teal']}`,
|
|
147
151
|
},
|
|
148
152
|
selectedYellow: {
|
|
149
153
|
borderColor: colorVars['--color-border-yellow'],
|
|
150
|
-
|
|
154
|
+
'--_card-ring': `inset 0 0 0 2px ${colorVars['--color-border-yellow']}`,
|
|
151
155
|
},
|
|
152
156
|
});
|
|
153
157
|
|
|
@@ -228,6 +232,13 @@ export interface SelectableCardProps extends Omit<BaseProps, 'onChange'> {
|
|
|
228
232
|
*/
|
|
229
233
|
variant?: CardVariant;
|
|
230
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Resting elevation — the shadow depth the card sits at.
|
|
237
|
+
* The selection ring composes on top, so a selected card keeps its shadow.
|
|
238
|
+
* @default 'none'
|
|
239
|
+
*/
|
|
240
|
+
elevation?: Elevation;
|
|
241
|
+
|
|
231
242
|
/** Width of the card. */
|
|
232
243
|
width?: SizeValue;
|
|
233
244
|
|
|
@@ -278,6 +289,7 @@ export function SelectableCard({
|
|
|
278
289
|
children,
|
|
279
290
|
padding,
|
|
280
291
|
variant = 'default',
|
|
292
|
+
elevation = 'none',
|
|
281
293
|
width,
|
|
282
294
|
height,
|
|
283
295
|
maxWidth,
|
|
@@ -328,6 +340,7 @@ export function SelectableCard({
|
|
|
328
340
|
maxWidth={maxWidth}
|
|
329
341
|
padding={padding}
|
|
330
342
|
variant={variant}
|
|
343
|
+
elevation={elevation}
|
|
331
344
|
{...mergeProps(
|
|
332
345
|
themeProps('selectable-card', {
|
|
333
346
|
variant,
|
|
@@ -503,6 +503,58 @@ describe('Selector', () => {
|
|
|
503
503
|
expect(search).toHaveAttribute('aria-activedescendant');
|
|
504
504
|
});
|
|
505
505
|
|
|
506
|
+
it('PageDown/PageUp jump the highlight to the last/first filtered option', async () => {
|
|
507
|
+
const user = userEvent.setup();
|
|
508
|
+
render(
|
|
509
|
+
<Selector
|
|
510
|
+
label="Fruit"
|
|
511
|
+
options={OPTIONS}
|
|
512
|
+
value="Apple"
|
|
513
|
+
onChange={() => {}}
|
|
514
|
+
hasSearch
|
|
515
|
+
/>,
|
|
516
|
+
);
|
|
517
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
518
|
+
const search = screen.getByRole('combobox', h);
|
|
519
|
+
// Filter to Apple and Banana so "last" means last *visible* option.
|
|
520
|
+
await user.type(search, 'a');
|
|
521
|
+
const options = screen.getAllByRole('option', h);
|
|
522
|
+
expect(options).toHaveLength(2);
|
|
523
|
+
await user.keyboard('{PageDown}');
|
|
524
|
+
expect(search).toHaveAttribute(
|
|
525
|
+
'aria-activedescendant',
|
|
526
|
+
options[options.length - 1].id,
|
|
527
|
+
);
|
|
528
|
+
await user.keyboard('{PageUp}');
|
|
529
|
+
expect(search).toHaveAttribute('aria-activedescendant', options[0].id);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it('Home/End move the search caret, not the option highlight', async () => {
|
|
533
|
+
const user = userEvent.setup();
|
|
534
|
+
render(
|
|
535
|
+
<Selector
|
|
536
|
+
label="Fruit"
|
|
537
|
+
options={OPTIONS}
|
|
538
|
+
value="Apple"
|
|
539
|
+
onChange={() => {}}
|
|
540
|
+
hasSearch
|
|
541
|
+
/>,
|
|
542
|
+
);
|
|
543
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
544
|
+
const search = screen.getByRole<HTMLInputElement>('combobox', h);
|
|
545
|
+
await user.type(search, 'an');
|
|
546
|
+
expect(search.selectionStart).toBe(2);
|
|
547
|
+
const activeBefore = search.getAttribute('aria-activedescendant');
|
|
548
|
+
// Home/End stay on the input for caret movement (APG editable
|
|
549
|
+
// combobox); the option highlight must not move.
|
|
550
|
+
await user.keyboard('{Home}');
|
|
551
|
+
expect(search.selectionStart).toBe(0);
|
|
552
|
+
expect(search.getAttribute('aria-activedescendant')).toBe(activeBefore);
|
|
553
|
+
await user.keyboard('{End}');
|
|
554
|
+
expect(search.selectionStart).toBe(2);
|
|
555
|
+
expect(search.getAttribute('aria-activedescendant')).toBe(activeBefore);
|
|
556
|
+
});
|
|
557
|
+
|
|
506
558
|
it('does not render search input when hasSearch is false', async () => {
|
|
507
559
|
const user = userEvent.setup();
|
|
508
560
|
render(
|
|
@@ -722,6 +774,23 @@ describe('Selector', () => {
|
|
|
722
774
|
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
723
775
|
});
|
|
724
776
|
|
|
777
|
+
it('End/Home jump the highlight to the last/first option (non-search)', async () => {
|
|
778
|
+
const user = userEvent.setup();
|
|
779
|
+
render(<Selector label="Fruit" options={OPTIONS} />);
|
|
780
|
+
|
|
781
|
+
const trigger = screen.getByRole('combobox');
|
|
782
|
+
await user.click(trigger);
|
|
783
|
+
const options = screen.getAllByRole('option', h);
|
|
784
|
+
|
|
785
|
+
await user.keyboard('{End}');
|
|
786
|
+
expect(trigger).toHaveAttribute(
|
|
787
|
+
'aria-activedescendant',
|
|
788
|
+
options[options.length - 1].id,
|
|
789
|
+
);
|
|
790
|
+
await user.keyboard('{Home}');
|
|
791
|
+
expect(trigger).toHaveAttribute('aria-activedescendant', options[0].id);
|
|
792
|
+
});
|
|
793
|
+
|
|
725
794
|
it('opens and selects an option with Enter (no mouse)', async () => {
|
|
726
795
|
const user = userEvent.setup();
|
|
727
796
|
const onChange = vi.fn();
|
|
@@ -858,10 +858,14 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
858
858
|
onChange={handleSearchChange}
|
|
859
859
|
onKeyDown={e => {
|
|
860
860
|
// Arrow keys navigate options; Enter selects; Escape/Tab close.
|
|
861
|
-
// Home/End are left to the input for caret movement
|
|
861
|
+
// Home/End are left to the input for caret movement (APG editable
|
|
862
|
+
// combobox); PageUp/PageDown are the sanctioned substitute for
|
|
863
|
+
// jumping to the first/last option.
|
|
862
864
|
if (
|
|
863
865
|
e.key === 'ArrowDown' ||
|
|
864
866
|
e.key === 'ArrowUp' ||
|
|
867
|
+
e.key === 'PageUp' ||
|
|
868
|
+
e.key === 'PageDown' ||
|
|
865
869
|
e.key === 'Enter' ||
|
|
866
870
|
e.key === 'Escape' ||
|
|
867
871
|
e.key === 'Tab'
|
package/src/Selector/hooks.ts
CHANGED
|
@@ -318,6 +318,23 @@ export function useCombobox({
|
|
|
318
318
|
}
|
|
319
319
|
break;
|
|
320
320
|
|
|
321
|
+
// PageUp/PageDown mirror Home/End. In search mode Home/End stay on
|
|
322
|
+
// the input for caret movement (APG editable combobox), so these are
|
|
323
|
+
// the sanctioned substitute for jumping to the first/last option.
|
|
324
|
+
case 'PageUp':
|
|
325
|
+
e.preventDefault();
|
|
326
|
+
if (isOpen && enabledIndices.length > 0) {
|
|
327
|
+
setHighlightedIndex(enabledIndices[0]);
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
|
|
331
|
+
case 'PageDown':
|
|
332
|
+
e.preventDefault();
|
|
333
|
+
if (isOpen && enabledIndices.length > 0) {
|
|
334
|
+
setHighlightedIndex(enabledIndices[enabledIndices.length - 1]);
|
|
335
|
+
}
|
|
336
|
+
break;
|
|
337
|
+
|
|
321
338
|
case 'Delete':
|
|
322
339
|
case 'Backspace':
|
|
323
340
|
// Keyboard equivalent of the clear button (comboboxes-2): clear the
|
|
@@ -337,7 +337,9 @@ describe('SideNavHeading', () => {
|
|
|
337
337
|
it('whole heading is popover trigger when menu provided without hrefs', () => {
|
|
338
338
|
render(<SideNavHeading heading="My App" menu={<div>Menu</div>} />);
|
|
339
339
|
const button = screen.getByRole('button');
|
|
340
|
-
|
|
340
|
+
// The popup is no longer a dialog (role: 'none' on usePopover), so the
|
|
341
|
+
// trigger advertises a generic popup rather than aria-haspopup="dialog".
|
|
342
|
+
expect(button).toHaveAttribute('aria-haspopup', 'true');
|
|
341
343
|
expect(button).toHaveAttribute('aria-expanded', 'false');
|
|
342
344
|
});
|
|
343
345
|
|
|
@@ -351,7 +353,7 @@ describe('SideNavHeading', () => {
|
|
|
351
353
|
const button = screen.getByRole('button');
|
|
352
354
|
// The trigger button uses aria attributes from usePopover and
|
|
353
355
|
// an onClick handler from useMenuHover for click-to-lock toggle.
|
|
354
|
-
expect(button).toHaveAttribute('aria-haspopup', '
|
|
356
|
+
expect(button).toHaveAttribute('aria-haspopup', 'true');
|
|
355
357
|
expect(button).toHaveAttribute('aria-expanded');
|
|
356
358
|
});
|
|
357
359
|
|
|
@@ -364,13 +366,92 @@ describe('SideNavHeading', () => {
|
|
|
364
366
|
/>,
|
|
365
367
|
);
|
|
366
368
|
const button = screen.getByRole('button', {name: 'Open menu'});
|
|
367
|
-
expect(button).toHaveAttribute('aria-haspopup', '
|
|
369
|
+
expect(button).toHaveAttribute('aria-haspopup', 'true');
|
|
368
370
|
});
|
|
369
371
|
|
|
370
372
|
it('passes data-testid', () => {
|
|
371
373
|
render(<SideNavHeading heading="My App" data-testid="nav-header" />);
|
|
372
374
|
expect(screen.getByTestId('nav-header')).toBeInTheDocument();
|
|
373
375
|
});
|
|
376
|
+
|
|
377
|
+
// ===========================================================================
|
|
378
|
+
// Menu popover semantics — the popup must not be announced as a modal
|
|
379
|
+
// dialog, and role="menu" must be scoped to the actual menu items so the
|
|
380
|
+
// heading button is not an invalid child of the menu.
|
|
381
|
+
// ===========================================================================
|
|
382
|
+
|
|
383
|
+
// The popover layer keeps `popover` content display:none in jsdom even
|
|
384
|
+
// when open, hiding it from role queries — so these tests assert the
|
|
385
|
+
// popup's ARIA semantics at the DOM level instead.
|
|
386
|
+
describe('menu popover semantics', () => {
|
|
387
|
+
const menuItems = (
|
|
388
|
+
<>
|
|
389
|
+
<div role="menuitem">Alpha</div>
|
|
390
|
+
<div role="menuitem">Beta</div>
|
|
391
|
+
</>
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
it('does not wrap the heading menu popup in a modal dialog', async () => {
|
|
395
|
+
const user = userEvent.setup();
|
|
396
|
+
render(<SideNavHeading heading="My App" menu={menuItems} />);
|
|
397
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
398
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
399
|
+
expect(document.querySelector('[aria-modal="true"]')).toBeNull();
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('scopes role="menu" to only menuitem children with an accessible name', async () => {
|
|
403
|
+
const user = userEvent.setup();
|
|
404
|
+
render(<SideNavHeading heading="My App" menu={menuItems} />);
|
|
405
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
406
|
+
const menu = document.querySelector('[role="menu"]');
|
|
407
|
+
expect(menu).not.toBeNull();
|
|
408
|
+
expect(menu).toHaveAttribute('aria-label', 'My App');
|
|
409
|
+
const children = Array.from(menu!.children);
|
|
410
|
+
expect(children.length).toBeGreaterThan(0);
|
|
411
|
+
for (const child of children) {
|
|
412
|
+
expect(child).toHaveAttribute('role', 'menuitem');
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('keeps the popup heading button outside the menu and closes on click', async () => {
|
|
417
|
+
const user = userEvent.setup();
|
|
418
|
+
render(<SideNavHeading heading="My App" menu={menuItems} />);
|
|
419
|
+
const trigger = screen.getByRole('button', {name: 'Open menu'});
|
|
420
|
+
await user.click(trigger);
|
|
421
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'true');
|
|
422
|
+
const menu = document.querySelector('[role="menu"]');
|
|
423
|
+
expect(menu).not.toBeNull();
|
|
424
|
+
// The heading replica button in the popup is a sibling of the menu,
|
|
425
|
+
// not an invalid menu child.
|
|
426
|
+
const headingButton = Array.from(
|
|
427
|
+
document.querySelectorAll('button'),
|
|
428
|
+
).find(b => b !== trigger && b.textContent?.includes('My App'));
|
|
429
|
+
expect(headingButton).toBeDefined();
|
|
430
|
+
expect(menu!.contains(headingButton!)).toBe(false);
|
|
431
|
+
// Clicking it still closes the popup.
|
|
432
|
+
fireEvent.click(headingButton!);
|
|
433
|
+
expect(trigger).toHaveAttribute('aria-expanded', 'false');
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it('applies the same semantics in mixed mode (menu + hrefs)', async () => {
|
|
437
|
+
const user = userEvent.setup();
|
|
438
|
+
render(
|
|
439
|
+
<SideNavHeading
|
|
440
|
+
heading="Product"
|
|
441
|
+
headingHref="/product"
|
|
442
|
+
menu={menuItems}
|
|
443
|
+
/>,
|
|
444
|
+
);
|
|
445
|
+
await user.click(screen.getByRole('button', {name: 'Open menu'}));
|
|
446
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
447
|
+
const menu = document.querySelector('[role="menu"]');
|
|
448
|
+
expect(menu).not.toBeNull();
|
|
449
|
+
expect(menu).toHaveAttribute('aria-label', 'Product');
|
|
450
|
+
for (const child of Array.from(menu!.children)) {
|
|
451
|
+
expect(child).toHaveAttribute('role', 'menuitem');
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
});
|
|
374
455
|
});
|
|
375
456
|
|
|
376
457
|
// =============================================================================
|
|
@@ -476,6 +557,41 @@ describe('SideNavHeading collapsed', () => {
|
|
|
476
557
|
);
|
|
477
558
|
expect(screen.getByTestId('nav-header')).toBeInTheDocument();
|
|
478
559
|
});
|
|
560
|
+
|
|
561
|
+
it('collapsed menu popup is not a dialog and scopes role="menu" to menu items', async () => {
|
|
562
|
+
const user = userEvent.setup();
|
|
563
|
+
render(
|
|
564
|
+
<CollapsedWrapper>
|
|
565
|
+
<SideNavHeading
|
|
566
|
+
heading="My App"
|
|
567
|
+
icon={<span data-testid="app-icon">🏠</span>}
|
|
568
|
+
menu={
|
|
569
|
+
<>
|
|
570
|
+
<div role="menuitem">Alpha</div>
|
|
571
|
+
<div role="menuitem">Beta</div>
|
|
572
|
+
</>
|
|
573
|
+
}
|
|
574
|
+
/>
|
|
575
|
+
</CollapsedWrapper>,
|
|
576
|
+
);
|
|
577
|
+
await user.click(screen.getByRole('button', {name: 'My App'}));
|
|
578
|
+
// No modal dialog wrapper around the menu popup.
|
|
579
|
+
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
580
|
+
expect(document.querySelector('[aria-modal="true"]')).toBeNull();
|
|
581
|
+
// role="menu" is scoped to the menu items and has a direct name.
|
|
582
|
+
const menu = document.querySelector('[role="menu"]');
|
|
583
|
+
expect(menu).not.toBeNull();
|
|
584
|
+
expect(menu).toHaveAttribute('aria-label', 'My App');
|
|
585
|
+
const children = Array.from(menu!.children);
|
|
586
|
+
expect(children.length).toBeGreaterThan(0);
|
|
587
|
+
for (const child of children) {
|
|
588
|
+
expect(child).toHaveAttribute('role', 'menuitem');
|
|
589
|
+
}
|
|
590
|
+
// No button (trigger or heading replica) lives inside the menu.
|
|
591
|
+
for (const button of Array.from(document.querySelectorAll('button'))) {
|
|
592
|
+
expect(menu!.contains(button)).toBe(false);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
479
595
|
});
|
|
480
596
|
|
|
481
597
|
// =============================================================================
|
|
@@ -120,7 +120,12 @@ export function SideNavCollapseButton({
|
|
|
120
120
|
return (
|
|
121
121
|
<Button
|
|
122
122
|
ref={ref}
|
|
123
|
-
label={
|
|
123
|
+
label={
|
|
124
|
+
label ??
|
|
125
|
+
(isCollapsed
|
|
126
|
+
? t('@astryx.sideNavCollapseButton.expandSidebar')
|
|
127
|
+
: t('@astryx.sideNavCollapseButton.collapseSidebar'))
|
|
128
|
+
}
|
|
124
129
|
variant="ghost"
|
|
125
130
|
{...props}
|
|
126
131
|
onClick={composeEventHandlers(onClickProp, toggle)}
|