@astryxdesign/core 0.1.8 → 0.1.9-canary.1887ee2
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 +53 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +203 -49
- 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/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- 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 +33 -4
- 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 +36 -4
- 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/ChatLayout.js +4 -4
- 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/Chat/useTriggerMenu.js +2 -2
- 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/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- 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 +9 -2
- 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/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/DateInput/DateInput.d.ts +55 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +28 -2
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +9 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +3 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +18 -3
- 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/DropdownMenuItem.js +1 -1
- 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 +43 -16
- package/dist/FieldStatus/FieldStatus.d.ts +15 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +58 -6
- package/dist/FileInput/FileInput.d.ts +9 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +42 -20
- 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/Lightbox/Lightbox.js +4 -4
- 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 +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +41 -12
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +9 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +8 -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/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- 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/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- 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 +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +7 -3
- 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/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +3 -2
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- 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/stickyColumns/useTableStickyColumns.js +1 -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/TextArea/TextArea.d.ts +9 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +2 -0
- package/dist/TextInput/TextInput.d.ts +9 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- 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 +9 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +17 -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 +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +18 -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 +28 -8
- 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/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +20 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +2 -0
- package/dist/astryx.css +41 -31
- 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/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- 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/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useListFocus.d.ts +6 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +12 -4
- 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/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- 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 +32 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +24 -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 +60 -3
- package/src/Avatar/Avatar.test.tsx +281 -1
- package/src/Avatar/Avatar.tsx +324 -64
- 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/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +125 -0
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- 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 +27 -3
- 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 +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +4 -1
- package/src/Chat/ChatLayout.tsx +7 -5
- 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 +4 -2
- 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/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- 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 +10 -2
- 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/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +193 -0
- package/src/DateInput/DateInput.doc.mjs +31 -0
- package/src/DateInput/DateInput.test.tsx +131 -0
- package/src/DateInput/DateInput.tsx +78 -3
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +8 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +23 -0
- package/src/DateRangeInput/DateRangeInput.tsx +13 -3
- package/src/DateTimeInput/DateTimeInput.doc.mjs +16 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +42 -18
- 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/DropdownMenuItem.tsx +1 -1
- 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 +9 -1
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +63 -5
- package/src/FileInput/FileInput.doc.mjs +17 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +53 -28
- 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/Lightbox/Lightbox.tsx +4 -4
- 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 +13 -2
- package/src/MultiSelector/MultiSelector.test.tsx +195 -3
- package/src/MultiSelector/MultiSelector.tsx +65 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +15 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +21 -4
- 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/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- 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.doc.mjs +7 -0
- package/src/Selector/Selector.test.tsx +92 -0
- package/src/Selector/Selector.tsx +16 -2
- 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/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +3 -5
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- 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/stickyColumns/useTableStickyColumns.tsx +1 -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.doc.mjs +15 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +10 -0
- package/src/TextInput/TextInput.doc.mjs +15 -0
- package/src/TextInput/TextInput.test.tsx +44 -0
- package/src/TextInput/TextInput.tsx +13 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +15 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +29 -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 +30 -1
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +26 -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 +52 -12
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +30 -15
- package/src/Typeahead/Typeahead.doc.mjs +7 -0
- package/src/Typeahead/Typeahead.test.tsx +50 -0
- package/src/Typeahead/Typeahead.tsx +10 -0
- 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/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useListFocus.doc.mjs +3 -3
- package/src/hooks/useListFocus.test.tsx +67 -1
- package/src/hooks/useListFocus.ts +21 -5
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -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
|
@@ -10,7 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
render,
|
|
15
|
+
screen,
|
|
16
|
+
fireEvent,
|
|
17
|
+
waitFor,
|
|
18
|
+
within,
|
|
19
|
+
} from '@testing-library/react';
|
|
14
20
|
import userEvent from '@testing-library/user-event';
|
|
15
21
|
import {MultiSelector} from './MultiSelector';
|
|
16
22
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
@@ -360,6 +366,30 @@ describe('MultiSelector', () => {
|
|
|
360
366
|
expect(activeId).toBeTruthy();
|
|
361
367
|
});
|
|
362
368
|
|
|
369
|
+
it('End/Home jump the highlight to the last/first option (non-search)', async () => {
|
|
370
|
+
const user = userEvent.setup();
|
|
371
|
+
render(
|
|
372
|
+
<MultiSelector
|
|
373
|
+
label="Fruit"
|
|
374
|
+
options={defaultOptions}
|
|
375
|
+
value={[]}
|
|
376
|
+
onChange={() => {}}
|
|
377
|
+
/>,
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
const trigger = screen.getByRole('combobox');
|
|
381
|
+
await user.click(trigger);
|
|
382
|
+
const options = screen.getAllByRole('option', h);
|
|
383
|
+
|
|
384
|
+
await user.keyboard('{End}');
|
|
385
|
+
expect(trigger).toHaveAttribute(
|
|
386
|
+
'aria-activedescendant',
|
|
387
|
+
options[options.length - 1].id,
|
|
388
|
+
);
|
|
389
|
+
await user.keyboard('{Home}');
|
|
390
|
+
expect(trigger).toHaveAttribute('aria-activedescendant', options[0].id);
|
|
391
|
+
});
|
|
392
|
+
|
|
363
393
|
it('toggles item with Enter key', async () => {
|
|
364
394
|
const user = userEvent.setup();
|
|
365
395
|
const onChange = vi.fn();
|
|
@@ -535,6 +565,65 @@ describe('MultiSelector', () => {
|
|
|
535
565
|
expect(options).toHaveLength(1);
|
|
536
566
|
});
|
|
537
567
|
|
|
568
|
+
it('PageDown/PageUp jump the highlight to the last/first filtered option', async () => {
|
|
569
|
+
const user = userEvent.setup();
|
|
570
|
+
render(
|
|
571
|
+
<MultiSelector
|
|
572
|
+
label="Fruit"
|
|
573
|
+
options={defaultOptions}
|
|
574
|
+
value={[]}
|
|
575
|
+
onChange={() => {}}
|
|
576
|
+
hasSearch
|
|
577
|
+
/>,
|
|
578
|
+
);
|
|
579
|
+
|
|
580
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
581
|
+
const searchInput = screen.getByRole('combobox', h);
|
|
582
|
+
// Filter to Banana and Orange so "last" means last *visible* option.
|
|
583
|
+
await user.type(searchInput, 'an');
|
|
584
|
+
const options = screen.getAllByRole('option', h);
|
|
585
|
+
expect(options).toHaveLength(2);
|
|
586
|
+
|
|
587
|
+
await user.keyboard('{PageDown}');
|
|
588
|
+
expect(searchInput).toHaveAttribute(
|
|
589
|
+
'aria-activedescendant',
|
|
590
|
+
options[options.length - 1].id,
|
|
591
|
+
);
|
|
592
|
+
await user.keyboard('{PageUp}');
|
|
593
|
+
expect(searchInput).toHaveAttribute('aria-activedescendant', options[0].id);
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
it('Home/End move the search caret, not the option highlight', async () => {
|
|
597
|
+
const user = userEvent.setup();
|
|
598
|
+
render(
|
|
599
|
+
<MultiSelector
|
|
600
|
+
label="Fruit"
|
|
601
|
+
options={defaultOptions}
|
|
602
|
+
value={[]}
|
|
603
|
+
onChange={() => {}}
|
|
604
|
+
hasSearch
|
|
605
|
+
/>,
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
609
|
+
const searchInput = screen.getByRole<HTMLInputElement>('combobox', h);
|
|
610
|
+
await user.type(searchInput, 'an');
|
|
611
|
+
expect(searchInput.selectionStart).toBe(2);
|
|
612
|
+
const activeBefore = searchInput.getAttribute('aria-activedescendant');
|
|
613
|
+
// Home/End stay on the input for caret movement (APG editable combobox);
|
|
614
|
+
// the option highlight must not move.
|
|
615
|
+
await user.keyboard('{Home}');
|
|
616
|
+
expect(searchInput.selectionStart).toBe(0);
|
|
617
|
+
expect(searchInput.getAttribute('aria-activedescendant')).toBe(
|
|
618
|
+
activeBefore,
|
|
619
|
+
);
|
|
620
|
+
await user.keyboard('{End}');
|
|
621
|
+
expect(searchInput.selectionStart).toBe(2);
|
|
622
|
+
expect(searchInput.getAttribute('aria-activedescendant')).toBe(
|
|
623
|
+
activeBefore,
|
|
624
|
+
);
|
|
625
|
+
});
|
|
626
|
+
|
|
538
627
|
it('shows empty state when search has no results', async () => {
|
|
539
628
|
const user = userEvent.setup();
|
|
540
629
|
render(
|
|
@@ -551,7 +640,85 @@ describe('MultiSelector', () => {
|
|
|
551
640
|
const searchInput = screen.getByRole('combobox', h);
|
|
552
641
|
await user.type(searchInput, 'xyz');
|
|
553
642
|
|
|
554
|
-
expect(
|
|
643
|
+
expect(
|
|
644
|
+
within(screen.getByRole('listbox', h)).getByText('No results found'),
|
|
645
|
+
).toBeInTheDocument();
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
describe('result announcements', () => {
|
|
649
|
+
it('announces the match count politely while searching', async () => {
|
|
650
|
+
const user = userEvent.setup();
|
|
651
|
+
render(
|
|
652
|
+
<MultiSelector
|
|
653
|
+
label="Fruit"
|
|
654
|
+
options={defaultOptions}
|
|
655
|
+
value={EMPTY_VALUE}
|
|
656
|
+
onChange={() => {}}
|
|
657
|
+
hasSearch
|
|
658
|
+
/>,
|
|
659
|
+
);
|
|
660
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
661
|
+
// "an" matches Banana and Orange.
|
|
662
|
+
await user.type(screen.getByRole('combobox', h), 'an');
|
|
663
|
+
await waitFor(() => {
|
|
664
|
+
expect(politeRegion()).toHaveTextContent('2 results');
|
|
665
|
+
});
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
it('announces the singular form when one option matches', async () => {
|
|
669
|
+
const user = userEvent.setup();
|
|
670
|
+
render(
|
|
671
|
+
<MultiSelector
|
|
672
|
+
label="Fruit"
|
|
673
|
+
options={defaultOptions}
|
|
674
|
+
value={EMPTY_VALUE}
|
|
675
|
+
onChange={() => {}}
|
|
676
|
+
hasSearch
|
|
677
|
+
/>,
|
|
678
|
+
);
|
|
679
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
680
|
+
// "app" matches only Apple. Anchored so it cannot pass on "1 results".
|
|
681
|
+
await user.type(screen.getByRole('combobox', h), 'app');
|
|
682
|
+
await waitFor(() => {
|
|
683
|
+
expect(politeRegion()).toHaveTextContent(/^1 result$/);
|
|
684
|
+
});
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
it('announces "No results found" when nothing matches', async () => {
|
|
688
|
+
const user = userEvent.setup();
|
|
689
|
+
render(
|
|
690
|
+
<MultiSelector
|
|
691
|
+
label="Fruit"
|
|
692
|
+
options={defaultOptions}
|
|
693
|
+
value={EMPTY_VALUE}
|
|
694
|
+
onChange={() => {}}
|
|
695
|
+
hasSearch
|
|
696
|
+
/>,
|
|
697
|
+
);
|
|
698
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
699
|
+
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
700
|
+
await waitFor(() => {
|
|
701
|
+
expect(politeRegion()).toHaveTextContent('No results found');
|
|
702
|
+
});
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
it('does not announce results until the user searches', async () => {
|
|
706
|
+
const user = userEvent.setup();
|
|
707
|
+
render(
|
|
708
|
+
<MultiSelector
|
|
709
|
+
label="Fruit"
|
|
710
|
+
options={defaultOptions}
|
|
711
|
+
value={EMPTY_VALUE}
|
|
712
|
+
onChange={() => {}}
|
|
713
|
+
hasSearch
|
|
714
|
+
/>,
|
|
715
|
+
);
|
|
716
|
+
// Popover closed: nothing announced.
|
|
717
|
+
expect(politeRegion()?.textContent ?? '').toBe('');
|
|
718
|
+
// Open with an empty query: still nothing announced.
|
|
719
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
720
|
+
expect(politeRegion()?.textContent ?? '').toBe('');
|
|
721
|
+
});
|
|
555
722
|
});
|
|
556
723
|
|
|
557
724
|
it('renders with description', () => {
|
|
@@ -1072,7 +1239,32 @@ describe('MultiSelector', () => {
|
|
|
1072
1239
|
/>
|
|
1073
1240
|
</form>,
|
|
1074
1241
|
);
|
|
1075
|
-
expect([
|
|
1242
|
+
expect([
|
|
1243
|
+
...new FormData(container.querySelector('form')!).keys(),
|
|
1244
|
+
]).toEqual([]);
|
|
1076
1245
|
});
|
|
1077
1246
|
});
|
|
1078
1247
|
});
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
describe('MultiSelector statusVariant forwarding', () => {
|
|
1251
|
+
it('defaults to attached (status renders with data-variant="attached")', () => {
|
|
1252
|
+
const {container} = render(
|
|
1253
|
+
<MultiSelector label="Fruit" options={['Apple', 'Banana']} value={[]} onChange={() => {}} status={{type: 'error', message: 'Required'}} />,
|
|
1254
|
+
);
|
|
1255
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1256
|
+
'data-variant',
|
|
1257
|
+
'attached',
|
|
1258
|
+
);
|
|
1259
|
+
});
|
|
1260
|
+
|
|
1261
|
+
it('forwards statusVariant="detached" to the underlying Field status', () => {
|
|
1262
|
+
const {container} = render(
|
|
1263
|
+
<MultiSelector label="Fruit" options={['Apple', 'Banana']} value={[]} onChange={() => {}} status={{type: 'error', message: 'Required'}} statusVariant="detached" />,
|
|
1264
|
+
);
|
|
1265
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1266
|
+
'data-variant',
|
|
1267
|
+
'detached',
|
|
1268
|
+
);
|
|
1269
|
+
});
|
|
1270
|
+
});
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
inputStatusBorderStyles,
|
|
38
38
|
inputStatusHoverShadowStyles,
|
|
39
39
|
inputWrapperStyles,
|
|
40
|
+
type FieldStatusVariant,
|
|
40
41
|
} from '../Field';
|
|
41
42
|
import {Divider} from '../Divider';
|
|
42
43
|
import {Spinner} from '../Spinner';
|
|
@@ -479,6 +480,13 @@ export interface MultiSelectorProps<
|
|
|
479
480
|
* Status indicator for the selector.
|
|
480
481
|
*/
|
|
481
482
|
status?: MultiSelectorStatus;
|
|
483
|
+
/**
|
|
484
|
+
* How the status message is placed relative to the input.
|
|
485
|
+
* - 'attached': message overlaps directly below the input (bordered treatment)
|
|
486
|
+
* - 'detached': message floats below as a separate element with spacing
|
|
487
|
+
* @default 'attached'
|
|
488
|
+
*/
|
|
489
|
+
statusVariant?: FieldStatusVariant;
|
|
482
490
|
|
|
483
491
|
/**
|
|
484
492
|
* Width of the field. Numbers are treated as pixels, strings are used as-is
|
|
@@ -562,6 +570,23 @@ export interface MultiSelectorProps<
|
|
|
562
570
|
'data-testid'?: string;
|
|
563
571
|
}
|
|
564
572
|
|
|
573
|
+
// Case-insensitive substring filter over the selectable options. Shared by the
|
|
574
|
+
// `filteredItems` memo (rendering) and the search-change handler, which needs
|
|
575
|
+
// the count for the *next* query synchronously to announce it exactly once per
|
|
576
|
+
// keystroke rather than reacting to state in an effect.
|
|
577
|
+
function filterOptionsByQuery(
|
|
578
|
+
items: MultiSelectorOptionData[],
|
|
579
|
+
query: string,
|
|
580
|
+
): MultiSelectorOptionData[] {
|
|
581
|
+
if (!query) {
|
|
582
|
+
return items;
|
|
583
|
+
}
|
|
584
|
+
const q = query.toLowerCase();
|
|
585
|
+
return items.filter(item =>
|
|
586
|
+
(item.label ?? item.value).toLowerCase().includes(q),
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
|
|
565
590
|
/**
|
|
566
591
|
* A multi-select dropdown component with checkboxes for choosing
|
|
567
592
|
* multiple items from a list of options.
|
|
@@ -593,6 +618,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
593
618
|
placeholder: placeholderFromProps,
|
|
594
619
|
size: sizeProp,
|
|
595
620
|
status,
|
|
621
|
+
statusVariant = 'attached',
|
|
596
622
|
labelTooltip,
|
|
597
623
|
startIcon,
|
|
598
624
|
hasClear = false,
|
|
@@ -692,15 +718,10 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
692
718
|
);
|
|
693
719
|
|
|
694
720
|
// Filter items by search query
|
|
695
|
-
const filteredItems = useMemo(
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
const query = searchQuery.toLowerCase();
|
|
700
|
-
return selectableItems.filter(item =>
|
|
701
|
-
(item.label ?? item.value).toLowerCase().includes(query),
|
|
702
|
-
);
|
|
703
|
-
}, [selectableItems, searchQuery]);
|
|
721
|
+
const filteredItems = useMemo(
|
|
722
|
+
() => filterOptionsByQuery(selectableItems, searchQuery),
|
|
723
|
+
[selectableItems, searchQuery],
|
|
724
|
+
);
|
|
704
725
|
|
|
705
726
|
// Single source of truth for item order. Both the hook (keyboard navigation)
|
|
706
727
|
// and renderOptions (DOM rendering) consume this list — no independent sorting.
|
|
@@ -772,8 +793,11 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
772
793
|
const handleLayerHide = useCallback(() => {
|
|
773
794
|
setSearchQuery('');
|
|
774
795
|
setSelectedAtOpen(null);
|
|
796
|
+
// Clear any lingering result count when the popover closes so stale status
|
|
797
|
+
// text does not linger in the a11y tree.
|
|
798
|
+
announce('');
|
|
775
799
|
triggerRef.current?.focus();
|
|
776
|
-
}, []);
|
|
800
|
+
}, [announce]);
|
|
777
801
|
|
|
778
802
|
const popover = usePopover({
|
|
779
803
|
hasLightDismiss: true,
|
|
@@ -793,6 +817,30 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
793
817
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- mount-only: isDefaultOpen is not reactive
|
|
794
818
|
}, []);
|
|
795
819
|
|
|
820
|
+
// Announce the filtered result count from the query-change handler (matching
|
|
821
|
+
// BaseTypeahead) rather than a reactive effect: computing the count for the
|
|
822
|
+
// next query here fires the announcement exactly once per keystroke and does
|
|
823
|
+
// not re-speak on unrelated re-renders. Reuses the announce instance shared
|
|
824
|
+
// with the selection-count announcements above.
|
|
825
|
+
const handleSearchChange = useCallback(
|
|
826
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
827
|
+
const nextQuery = event.target.value;
|
|
828
|
+
setSearchQuery(nextQuery);
|
|
829
|
+
if (nextQuery.length === 0) {
|
|
830
|
+
// Emptying the query clears the region rather than announcing a count.
|
|
831
|
+
announce('');
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
const count = filterOptionsByQuery(selectableItems, nextQuery).length;
|
|
835
|
+
announce(
|
|
836
|
+
count === 0
|
|
837
|
+
? 'No results found'
|
|
838
|
+
: `${count} result${count === 1 ? '' : 's'}`,
|
|
839
|
+
);
|
|
840
|
+
},
|
|
841
|
+
[announce, selectableItems],
|
|
842
|
+
);
|
|
843
|
+
|
|
796
844
|
// Handle toggle
|
|
797
845
|
// Clear all selected values. Shared by the clear button and the keyboard
|
|
798
846
|
// Delete/Backspace path so clearing is reachable without a mouse.
|
|
@@ -1041,14 +1089,17 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1041
1089
|
aria-label={t('@astryx.multiSelector.searchOptions')}
|
|
1042
1090
|
type="text"
|
|
1043
1091
|
value={searchQuery}
|
|
1044
|
-
onChange={
|
|
1092
|
+
onChange={handleSearchChange}
|
|
1045
1093
|
onKeyDown={e => {
|
|
1046
1094
|
// Arrow keys navigate options; Enter toggles; Escape/Tab close.
|
|
1047
1095
|
// Space and Home/End are left to the input (type a space / move
|
|
1048
|
-
// the caret)
|
|
1096
|
+
// the caret) per the APG editable combobox; PageUp/PageDown are
|
|
1097
|
+
// the sanctioned substitute for jumping to the first/last option.
|
|
1049
1098
|
if (
|
|
1050
1099
|
e.key === 'ArrowDown' ||
|
|
1051
1100
|
e.key === 'ArrowUp' ||
|
|
1101
|
+
e.key === 'PageUp' ||
|
|
1102
|
+
e.key === 'PageDown' ||
|
|
1052
1103
|
e.key === 'Enter' ||
|
|
1053
1104
|
e.key === 'Escape' ||
|
|
1054
1105
|
e.key === 'Tab'
|
|
@@ -1067,6 +1118,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1067
1118
|
listboxId,
|
|
1068
1119
|
searchQuery,
|
|
1069
1120
|
searchPlaceholder,
|
|
1121
|
+
handleSearchChange,
|
|
1070
1122
|
onKeyDown,
|
|
1071
1123
|
popover.isOpen,
|
|
1072
1124
|
highlightedIndex,
|
|
@@ -1383,6 +1435,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1383
1435
|
}
|
|
1384
1436
|
: undefined
|
|
1385
1437
|
}
|
|
1438
|
+
statusVariant={statusVariant}
|
|
1386
1439
|
labelTooltip={labelTooltip}
|
|
1387
1440
|
width={width}>
|
|
1388
1441
|
{multiSelectorContent}
|
|
@@ -192,6 +192,23 @@ export function useMultiCombobox({
|
|
|
192
192
|
}
|
|
193
193
|
break;
|
|
194
194
|
|
|
195
|
+
// PageUp/PageDown mirror Home/End. In search mode Home/End stay on
|
|
196
|
+
// the input for caret movement (APG editable combobox), so these are
|
|
197
|
+
// the sanctioned substitute for jumping to the first/last option.
|
|
198
|
+
case 'PageUp':
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
if (isOpen && enabledIndices.length > 0) {
|
|
201
|
+
setHighlightedIndex(enabledIndices[0]);
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
|
|
205
|
+
case 'PageDown':
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
if (isOpen && enabledIndices.length > 0) {
|
|
208
|
+
setHighlightedIndex(enabledIndices[enabledIndices.length - 1]);
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
|
|
195
212
|
case 'Delete':
|
|
196
213
|
case 'Backspace':
|
|
197
214
|
// Keyboard equivalent of the clear button (comboboxes-2): clear all
|
|
@@ -94,6 +94,13 @@ export const docs = {
|
|
|
94
94
|
type: "{type: 'error' | 'warning' | 'success', message?: string}",
|
|
95
95
|
description: 'Validation status with optional message.',
|
|
96
96
|
},
|
|
97
|
+
{
|
|
98
|
+
name: 'statusVariant',
|
|
99
|
+
type: "'attached' | 'detached'",
|
|
100
|
+
description:
|
|
101
|
+
'How the status message is placed relative to the input. attached overlaps directly below the input (bordered treatment); detached floats below as a separate element with spacing.',
|
|
102
|
+
default: "'attached'",
|
|
103
|
+
},
|
|
97
104
|
{
|
|
98
105
|
name: 'min',
|
|
99
106
|
type: 'number | null',
|
|
@@ -275,6 +282,13 @@ export const docsZh = {
|
|
|
275
282
|
type: "{type: 'error' | 'warning' | 'success', message?: string}",
|
|
276
283
|
description: '带可选消息的验证状态。',
|
|
277
284
|
},
|
|
285
|
+
{
|
|
286
|
+
name: 'statusVariant',
|
|
287
|
+
type: "'attached' | 'detached'",
|
|
288
|
+
description:
|
|
289
|
+
'状态消息相对于输入框的放置方式。attached 直接叠加在输入框下方(带边框处理);detached 作为独立元素浮于下方并留有间距。',
|
|
290
|
+
default: "'attached'",
|
|
291
|
+
},
|
|
278
292
|
{
|
|
279
293
|
name: 'min',
|
|
280
294
|
type: 'number | null',
|
|
@@ -402,6 +416,7 @@ export const docsDense = {
|
|
|
402
416
|
startIcon: 'Icon at input start.',
|
|
403
417
|
labelIcon: 'Icon before label text.',
|
|
404
418
|
status: 'Validation status w/ optional message.',
|
|
419
|
+
statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing.',
|
|
405
420
|
min: 'Minimum value allowed.',
|
|
406
421
|
max: 'Maximum value allowed.',
|
|
407
422
|
step: 'Step increment.',
|
|
@@ -9,11 +9,20 @@
|
|
|
9
9
|
* SYNC: When NumberInput.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 {TestIcon} from '../__tests__/TestIcon';
|
|
16
|
+
import {InputGroup} from '../InputGroup';
|
|
16
17
|
import {NumberInput} from './NumberInput';
|
|
18
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
19
|
+
|
|
20
|
+
// FieldStatus announces status messages through the persistent useAnnounce
|
|
21
|
+
// singletons; remove them between tests so role/aria-live queries in this
|
|
22
|
+
// file never match a leftover region.
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
__resetLiveRegionsForTest();
|
|
25
|
+
});
|
|
17
26
|
|
|
18
27
|
// Mock showPopover/hidePopover since jsdom does not implement them. Used by the
|
|
19
28
|
// disabledMessage tooltip.
|
|
@@ -328,6 +337,33 @@ describe('NumberInput', () => {
|
|
|
328
337
|
expect(screen.queryByText('%')).not.toBeInTheDocument();
|
|
329
338
|
expect(screen.queryByText('GB')).not.toBeInTheDocument();
|
|
330
339
|
});
|
|
340
|
+
|
|
341
|
+
it('includes the units text in the accessible description (WCAG 1.3.1)', () => {
|
|
342
|
+
render(
|
|
343
|
+
<NumberInput
|
|
344
|
+
label="Storage"
|
|
345
|
+
value={50}
|
|
346
|
+
onChange={() => {}}
|
|
347
|
+
units="GB"
|
|
348
|
+
/>,
|
|
349
|
+
);
|
|
350
|
+
expect(screen.getByRole('spinbutton')).toHaveAccessibleDescription(/GB/);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
it('combines units with the description in the accessible description', () => {
|
|
354
|
+
render(
|
|
355
|
+
<NumberInput
|
|
356
|
+
label="Discount"
|
|
357
|
+
value={10}
|
|
358
|
+
onChange={() => {}}
|
|
359
|
+
description="Applied at checkout"
|
|
360
|
+
units="%"
|
|
361
|
+
/>,
|
|
362
|
+
);
|
|
363
|
+
const input = screen.getByRole('spinbutton');
|
|
364
|
+
expect(input).toHaveAccessibleDescription(/Applied at checkout/);
|
|
365
|
+
expect(input).toHaveAccessibleDescription(/%/);
|
|
366
|
+
});
|
|
331
367
|
});
|
|
332
368
|
|
|
333
369
|
describe('event callbacks', () => {
|
|
@@ -455,6 +491,26 @@ describe('NumberInput', () => {
|
|
|
455
491
|
expect(screen.getByText('Value must be positive')).toBeInTheDocument();
|
|
456
492
|
});
|
|
457
493
|
|
|
494
|
+
it('has no dangling aria-describedby ids inside InputGroup (WCAG 1.3.1)', () => {
|
|
495
|
+
// Inside an InputGroup no Field renders, so the status message element
|
|
496
|
+
// does not exist; aria-describedby must not reference its id.
|
|
497
|
+
render(
|
|
498
|
+
<InputGroup label="Price">
|
|
499
|
+
<NumberInput
|
|
500
|
+
label="Amount"
|
|
501
|
+
value={null}
|
|
502
|
+
onChange={() => {}}
|
|
503
|
+
status={{type: 'error', message: 'Value must be positive'}}
|
|
504
|
+
/>
|
|
505
|
+
</InputGroup>,
|
|
506
|
+
);
|
|
507
|
+
const input = screen.getByRole('spinbutton');
|
|
508
|
+
const describedBy = input.getAttribute('aria-describedby') ?? '';
|
|
509
|
+
for (const idToken of describedBy.split(/\s+/).filter(Boolean)) {
|
|
510
|
+
expect(document.getElementById(idToken)).not.toBeNull();
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
458
514
|
it('does not render status message when not provided', () => {
|
|
459
515
|
render(
|
|
460
516
|
<NumberInput
|
|
@@ -871,9 +927,7 @@ describe('NumberInput', () => {
|
|
|
871
927
|
describe('keyboard clearing with hasClear (#3599)', () => {
|
|
872
928
|
it('commits null when the input is emptied and blurred', () => {
|
|
873
929
|
const onChange = vi.fn();
|
|
874
|
-
render(
|
|
875
|
-
<NumberInput label="Qty" hasClear value={42} onChange={onChange} />,
|
|
876
|
-
);
|
|
930
|
+
render(<NumberInput label="Qty" hasClear value={42} onChange={onChange} />);
|
|
877
931
|
const input = screen.getByLabelText('Qty');
|
|
878
932
|
fireEvent.change(input, {target: {value: ''}});
|
|
879
933
|
fireEvent.blur(input);
|
|
@@ -882,9 +936,7 @@ describe('keyboard clearing with hasClear (#3599)', () => {
|
|
|
882
936
|
|
|
883
937
|
it('commits null when the input is emptied and Enter is pressed', () => {
|
|
884
938
|
const onChange = vi.fn();
|
|
885
|
-
render(
|
|
886
|
-
<NumberInput label="Qty" hasClear value={42} onChange={onChange} />,
|
|
887
|
-
);
|
|
939
|
+
render(<NumberInput label="Qty" hasClear value={42} onChange={onChange} />);
|
|
888
940
|
const input = screen.getByLabelText('Qty');
|
|
889
941
|
fireEvent.change(input, {target: {value: ''}});
|
|
890
942
|
fireEvent.keyDown(input, {key: 'Enter'});
|
|
@@ -912,3 +964,26 @@ describe('keyboard clearing with hasClear (#3599)', () => {
|
|
|
912
964
|
expect((input as HTMLInputElement).value).toBe('42');
|
|
913
965
|
});
|
|
914
966
|
});
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
describe('NumberInput statusVariant forwarding', () => {
|
|
970
|
+
it('defaults to attached (status renders with data-variant="attached")', () => {
|
|
971
|
+
const {container} = render(
|
|
972
|
+
<NumberInput label="Amount" value={null} onChange={() => {}} status={{type: 'error', message: 'Must be positive'}} />,
|
|
973
|
+
);
|
|
974
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
975
|
+
'data-variant',
|
|
976
|
+
'attached',
|
|
977
|
+
);
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
it('forwards statusVariant="detached" to the underlying Field status', () => {
|
|
981
|
+
const {container} = render(
|
|
982
|
+
<NumberInput label="Amount" value={null} onChange={() => {}} status={{type: 'error', message: 'Must be positive'}} statusVariant="detached" />,
|
|
983
|
+
);
|
|
984
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
985
|
+
'data-variant',
|
|
986
|
+
'detached',
|
|
987
|
+
);
|
|
988
|
+
});
|
|
989
|
+
});
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
inputStatusBorderStyles,
|
|
45
45
|
inputStatusHoverShadowStyles,
|
|
46
46
|
inputStatusFocusWithinStyles,
|
|
47
|
+
type FieldStatusVariant,
|
|
47
48
|
} from '../Field';
|
|
48
49
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
49
50
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
@@ -207,6 +208,13 @@ interface NumberInputPropsBase extends Omit<
|
|
|
207
208
|
* If message is provided, displays a floating message box below the input.
|
|
208
209
|
*/
|
|
209
210
|
status?: InputStatus;
|
|
211
|
+
/**
|
|
212
|
+
* How the status message is placed relative to the input.
|
|
213
|
+
* - 'attached': message overlaps directly below the input (bordered treatment)
|
|
214
|
+
* - 'detached': message floats below as a separate element with spacing
|
|
215
|
+
* @default 'attached'
|
|
216
|
+
*/
|
|
217
|
+
statusVariant?: FieldStatusVariant;
|
|
210
218
|
/**
|
|
211
219
|
* The size of the input.
|
|
212
220
|
* - 'sm': Compact size (28px height)
|
|
@@ -311,8 +319,7 @@ type NumberInputPropsClearable = NumberInputPropsBase & {
|
|
|
311
319
|
};
|
|
312
320
|
|
|
313
321
|
export type NumberInputProps =
|
|
314
|
-
|
|
|
315
|
-
| NumberInputPropsClearable;
|
|
322
|
+
NumberInputPropsNonClearable | NumberInputPropsClearable;
|
|
316
323
|
|
|
317
324
|
/**
|
|
318
325
|
* Parse and validate a string input as a number.
|
|
@@ -375,6 +382,7 @@ export function NumberInput({
|
|
|
375
382
|
startIcon,
|
|
376
383
|
labelIcon,
|
|
377
384
|
status,
|
|
385
|
+
statusVariant = 'attached',
|
|
378
386
|
size: sizeProp,
|
|
379
387
|
onChange,
|
|
380
388
|
value,
|
|
@@ -406,6 +414,7 @@ export function NumberInput({
|
|
|
406
414
|
const inputLabelID = useId();
|
|
407
415
|
const descriptionID = useId();
|
|
408
416
|
const statusMessageID = useId();
|
|
417
|
+
const unitsID = useId();
|
|
409
418
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
410
419
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
411
420
|
const inputGroup = useInputGroup();
|
|
@@ -446,7 +455,10 @@ export function NumberInput({
|
|
|
446
455
|
inputLabelID,
|
|
447
456
|
[
|
|
448
457
|
description ? descriptionID : null,
|
|
449
|
-
status
|
|
458
|
+
// The status message element is rendered by Field, which is skipped
|
|
459
|
+
// inside an InputGroup — only reference it when it actually exists.
|
|
460
|
+
!inputGroup && status?.message ? statusMessageID : null,
|
|
461
|
+
units ? unitsID : null,
|
|
450
462
|
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
451
463
|
],
|
|
452
464
|
inputGroup,
|
|
@@ -652,7 +664,11 @@ export function NumberInput({
|
|
|
652
664
|
!isInputValid && styles.inputInvalid,
|
|
653
665
|
)}
|
|
654
666
|
/>
|
|
655
|
-
{units &&
|
|
667
|
+
{units && (
|
|
668
|
+
<span id={unitsID} {...stylex.props(styles.units)}>
|
|
669
|
+
{units}
|
|
670
|
+
</span>
|
|
671
|
+
)}
|
|
656
672
|
{/*
|
|
657
673
|
Live region announcing invalid typed input to assistive technology.
|
|
658
674
|
The value silently reverts on blur, so without this a screen-reader
|
|
@@ -710,6 +726,7 @@ export function NumberInput({
|
|
|
710
726
|
}
|
|
711
727
|
: undefined
|
|
712
728
|
}
|
|
729
|
+
statusVariant={statusVariant}
|
|
713
730
|
labelTooltip={labelTooltip}
|
|
714
731
|
width={width}>
|
|
715
732
|
{inputWrapper}
|
package/src/Outline/Outline.tsx
CHANGED