@astryxdesign/core 0.1.6 → 0.1.7-canary.0a6de96
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 +68 -0
- package/README.md +2 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +4 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +3 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +4 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +8 -6
- package/dist/Breadcrumbs/Breadcrumbs.d.ts +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs/Breadcrumbs.js +4 -1
- package/dist/Button/Button.d.ts +10 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +49 -6
- package/dist/ButtonGroup/ButtonGroup.d.ts +20 -5
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +27 -11
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +29 -7
- package/dist/Carousel/Carousel.d.ts +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +8 -5
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +4 -1
- package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +9 -2
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +6 -2
- package/dist/Chat/ChatLayout.d.ts +1 -11
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +6 -4
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -2
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +8 -2
- package/dist/Chat/ChatMessageBubble.d.ts +1 -1
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +3 -1
- package/dist/Chat/ChatMessageList.d.ts +1 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +3 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +13 -8
- package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
- package/dist/Chat/ChatPastedTextToken.js +3 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +3 -1
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +12 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +43 -6
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +4 -2
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +4 -2
- package/dist/CheckboxList/CheckboxList.d.ts +1 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +3 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +3 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +71 -53
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.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 +8 -3
- package/dist/CommandPalette/CommandPaletteInput.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +4 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteList.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteList.js +4 -1
- package/dist/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +8 -4
- package/dist/ContextMenu/index.d.ts +3 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +7 -1
- package/dist/DateInput/DateInput.d.ts +1 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +10 -5
- package/dist/DateRangeInput/DateRangeInput.d.ts +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +11 -6
- package/dist/DateTimeInput/DateTimeInput.d.ts +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +15 -7
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +15 -12
- package/dist/Dialog/DialogHeader.d.ts +1 -1
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +7 -3
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +19 -9
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +89 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +170 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +70 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +10 -1
- package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemRoles.js +15 -0
- package/dist/EmptyState/EmptyState.d.ts +4 -1
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +11 -1
- package/dist/Icon/Icon.d.ts +17 -12
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +28 -20
- package/dist/Kbd/Kbd.js +1 -1
- package/dist/Layer/useLayer.d.ts +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +23 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +6 -4
- package/dist/Link/Link.d.ts +5 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +32 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +10 -8
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +4 -2
- package/dist/MobileNav/MobileNavToggle.d.ts +1 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -1
- package/dist/MoreMenu/MoreMenu.d.ts +1 -1
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +13 -6
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +5 -1
- package/dist/Outline/Outline.d.ts +1 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +4 -1
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +38 -11
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +4 -1
- package/dist/PowerSearch/PowerSearch.d.ts +1 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +22 -12
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +26 -20
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +7 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +34 -21
- package/dist/PowerSearch/formatFilterValue.d.ts +2 -1
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +19 -9
- package/dist/PowerSearch/index.d.ts +2 -1
- package/dist/PowerSearch/index.d.ts.map +1 -1
- package/dist/PowerSearch/index.js +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts +23 -0
- package/dist/PowerSearch/resolveOperatorLabel.d.ts.map +1 -0
- package/dist/PowerSearch/resolveOperatorLabel.js +28 -0
- package/dist/PowerSearch/types.d.ts +28 -2
- package/dist/PowerSearch/types.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchConfig.js +27 -27
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/PowerSearch/usePowerSearchSource.js +15 -8
- package/dist/Resizable/ResizeHandle.d.ts +1 -1
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +4 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +52 -14
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +4 -2
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +3 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -3
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +7 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +4 -2
- package/dist/TabList/TabList.d.ts +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +4 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +5 -3
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +56 -19
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +12 -5
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -3
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +8 -6
- package/dist/Table/plugins/rowIndex/useTableRowIndex.d.ts +1 -1
- package/dist/Table/plugins/rowIndex/useTableRowIndex.js +1 -1
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +5 -2
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +6 -4
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +2 -2
- package/dist/Table/types.d.ts +17 -10
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +5 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +8 -2
- package/dist/TimeInput/TimeInput.d.ts +1 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +7 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +18 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +3 -1
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +3 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +8 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +3 -1
- package/dist/TopNav/TopNav.d.ts +2 -1
- package/dist/TopNav/TopNav.d.ts.map +1 -1
- package/dist/TopNav/TopNav.js +4 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +5 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +5 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +7 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +8 -4
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +1 -0
- package/dist/astryx.css +35 -3
- package/dist/astryx.umd.js +62 -60
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts +145 -0
- package/dist/authoring/doc.d.ts.map +1 -0
- package/dist/authoring/doc.js +100 -0
- package/dist/authoring/index.d.ts +29 -0
- package/dist/authoring/index.d.ts.map +1 -0
- package/dist/authoring/index.js +28 -0
- package/dist/authoring/integration.d.ts +35 -0
- package/dist/authoring/integration.d.ts.map +1 -0
- package/dist/authoring/integration.js +30 -0
- package/dist/authoring/template.d.ts +66 -0
- package/dist/authoring/template.d.ts.map +1 -0
- package/dist/authoring/template.js +55 -0
- package/dist/config.d.ts +80 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/docs-types.d.ts +13 -4
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.d.ts +12 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -0
- package/dist/i18n/InternationalizationContext.js +29 -0
- package/dist/i18n/InternationalizationProvider.d.ts +61 -0
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -0
- package/dist/i18n/InternationalizationProvider.js +44 -0
- package/dist/i18n/index.d.ts +24 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +21 -0
- package/dist/i18n/resolve.d.ts +22 -0
- package/dist/i18n/resolve.d.ts.map +1 -0
- package/dist/i18n/resolve.js +141 -0
- package/dist/i18n/translator.d.ts +25 -0
- package/dist/i18n/translator.d.ts.map +1 -0
- package/dist/i18n/translator.js +1 -0
- package/dist/i18n/types.d.ts +47 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +1 -0
- package/dist/i18n/useTranslator.d.ts +15 -0
- package/dist/i18n/useTranslator.d.ts.map +1 -0
- package/dist/i18n/useTranslator.js +39 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +0 -3
- package/dist/utils/color.d.ts +13 -1
- package/dist/utils/color.d.ts.map +1 -1
- package/dist/utils/color.js +23 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/locales/en.json +746 -0
- package/locales/pseudo.json +560 -0
- package/package.json +23 -2
- package/src/AlertDialog/AlertDialog.doc.mjs +5 -0
- package/src/AlertDialog/AlertDialog.tsx +4 -1
- package/src/AppShell/AppShell.doc.mjs +8 -2
- package/src/AppShell/AppShell.tsx +3 -1
- package/src/AvatarGroup/AvatarGroup.tsx +4 -1
- package/src/Banner/Banner.tsx +10 -5
- package/src/Breadcrumbs/Breadcrumbs.tsx +4 -1
- package/src/Button/Button.doc.mjs +8 -0
- package/src/Button/Button.test.tsx +27 -0
- package/src/Button/Button.tsx +51 -5
- package/src/ButtonGroup/ButtonGroup.test.tsx +386 -2
- package/src/ButtonGroup/ButtonGroup.tsx +27 -11
- package/src/Calendar/Calendar.test.tsx +103 -2
- package/src/Calendar/Calendar.tsx +29 -6
- package/src/Card/Card.doc.mjs +3 -3
- package/src/Carousel/Carousel.tsx +10 -7
- package/src/Chat/ChatComposer.tsx +5 -1
- package/src/Chat/ChatComposerDrawer.tsx +9 -2
- package/src/Chat/ChatComposerInput.tsx +10 -4
- package/src/Chat/ChatLayout.test.tsx +127 -2
- package/src/Chat/ChatLayout.tsx +5 -12
- package/src/Chat/ChatLayoutScrollButton.tsx +4 -2
- package/src/Chat/ChatMessage.tsx +5 -1
- package/src/Chat/ChatMessageBubble.tsx +2 -0
- package/src/Chat/ChatMessageList.doc.mjs +1 -1
- package/src/Chat/ChatMessageList.tsx +2 -0
- package/src/Chat/ChatMessageMetadata.tsx +15 -9
- package/src/Chat/ChatPastedTextToken.tsx +3 -1
- package/src/Chat/ChatSendButton.tsx +3 -1
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/index.ts +1 -0
- package/src/Chat/useChatStreamScroll.test.tsx +168 -0
- package/src/Chat/useChatStreamScroll.ts +67 -11
- package/src/Chat/useSpeechRecognition.ts +11 -2
- package/src/Chat/useTriggerMenu.tsx +4 -2
- package/src/CheckboxInput/CheckboxInput.test.tsx +16 -0
- package/src/CheckboxInput/CheckboxInput.tsx +4 -2
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -1
- package/src/CheckboxList/CheckboxList.tsx +2 -0
- package/src/CheckboxList/CheckboxListItem.tsx +7 -1
- package/src/Citation/Citation.tsx +4 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +1 -1
- package/src/CodeBlock/CodeBlock.tsx +91 -40
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +6 -0
- package/src/Collapsible/Collapsible.tsx +19 -4
- package/src/CommandPalette/CommandPalette.tsx +10 -3
- package/src/CommandPalette/CommandPaletteInput.test.tsx +1 -1
- package/src/CommandPalette/CommandPaletteInput.tsx +5 -1
- package/src/CommandPalette/CommandPaletteList.tsx +4 -1
- package/src/ContextMenu/ContextMenu.test.tsx +75 -1
- package/src/ContextMenu/ContextMenu.tsx +14 -6
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateInput/DateInput.doc.mjs +2 -2
- package/src/DateInput/DateInput.test.tsx +17 -5
- package/src/DateInput/DateInput.tsx +13 -5
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.tsx +14 -6
- package/src/DateTimeInput/DateTimeInput.doc.mjs +2 -2
- package/src/DateTimeInput/DateTimeInput.tsx +17 -7
- package/src/Dialog/Dialog.tsx +11 -15
- package/src/Dialog/DialogHeader.tsx +7 -3
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +23 -14
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +237 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +6 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +119 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
- package/src/DropdownMenu/index.ts +23 -3
- package/src/DropdownMenu/menuItemRoles.ts +22 -0
- package/src/EmptyState/EmptyState.doc.mjs +3 -3
- package/src/EmptyState/EmptyState.tsx +4 -1
- package/src/Field/Field.doc.mjs +2 -2
- package/src/FileInput/FileInput.test.tsx +40 -1
- package/src/FileInput/FileInput.tsx +12 -1
- package/src/Grid/Grid.doc.mjs +5 -5
- package/src/Icon/Icon.test.tsx +46 -0
- package/src/Icon/Icon.tsx +37 -24
- package/src/InputGroup/InputGroup.doc.mjs +1 -1
- package/src/Kbd/Kbd.test.tsx +26 -0
- package/src/Kbd/Kbd.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +8 -5
- package/src/Layer/useLayer.test.tsx +136 -1
- package/src/Layer/useLayer.tsx +34 -2
- package/src/Lightbox/Lightbox.doc.mjs +7 -2
- package/src/Lightbox/Lightbox.tsx +6 -4
- package/src/Link/Link.test.tsx +74 -2
- package/src/Link/Link.tsx +48 -1
- package/src/Markdown/Markdown.tsx +12 -4
- package/src/MobileNav/MobileNav.tsx +4 -2
- package/src/MobileNav/MobileNavToggle.tsx +5 -3
- package/src/MoreMenu/MoreMenu.tsx +4 -1
- package/src/MultiSelector/MultiSelector.tsx +14 -5
- package/src/NumberInput/NumberInput.tsx +3 -1
- package/src/Outline/Outline.tsx +4 -1
- package/src/OverflowList/OverflowList.doc.mjs +2 -2
- package/src/Pagination/Pagination.tsx +35 -12
- package/src/Popover/usePopover.tsx +6 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +9 -4
- package/src/PowerSearch/PowerSearch.tsx +22 -10
- package/src/PowerSearch/PowerSearchEditPopover.tsx +27 -20
- package/src/PowerSearch/PowerSearchToken.tsx +17 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +34 -21
- package/src/PowerSearch/formatFilterValue.test.ts +282 -0
- package/src/PowerSearch/formatFilterValue.ts +21 -8
- package/src/PowerSearch/index.ts +5 -0
- package/src/PowerSearch/resolveOperatorLabel.ts +34 -0
- package/src/PowerSearch/types.ts +33 -9
- package/src/PowerSearch/usePowerSearchConfig.ts +59 -27
- package/src/PowerSearch/usePowerSearchSource.ts +17 -8
- package/src/RadioList/RadioList.doc.mjs +1 -1
- package/src/Resizable/ResizeHandle.tsx +4 -1
- package/src/Section/Section.doc.mjs +4 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +6 -3
- package/src/Selector/Selector.test.tsx +114 -6
- package/src/Selector/Selector.tsx +68 -17
- package/src/SideNav/SideNav.tsx +4 -2
- package/src/SideNav/SideNavCollapseButton.tsx +3 -1
- package/src/SideNav/SideNavHeading.tsx +5 -3
- package/src/SideNav/SideNavItem.tsx +3 -1
- package/src/Slider/Slider.doc.mjs +2 -2
- package/src/Stack/Stack.doc.mjs +10 -10
- package/src/Switch/Switch.doc.mjs +2 -2
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +4 -2
- package/src/TabList/TabList.tsx +4 -1
- package/src/Table/BaseTable.tsx +36 -19
- package/src/Table/Table.test.tsx +132 -1
- package/src/Table/Table.tsx +6 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.tsx +31 -30
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +7 -5
- package/src/Table/plugins/pagination/useTablePagination.tsx +4 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +9 -8
- package/src/Table/plugins/rowIndex/useTableRowIndex.tsx +1 -1
- package/src/Table/plugins/selection/useTableSelection.tsx +6 -7
- package/src/Table/plugins/sortable/useTableSortable.tsx +8 -5
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +4 -4
- package/src/Table/types.ts +18 -12
- package/src/Table/useTableFiltering.doc.mjs +2 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTableSortable.doc.mjs +11 -11
- package/src/Text/Text.doc.mjs +2 -2
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.doc.mjs +2 -2
- package/src/TimeInput/TimeInput.tsx +6 -2
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +120 -7
- package/src/Timestamp/Timestamp.tsx +21 -1
- package/src/Toast/Toast.tsx +3 -1
- package/src/Toast/ToastViewport.tsx +3 -1
- package/src/Token/Token.tsx +4 -2
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.tsx +4 -4
- package/src/Toolbar/Toolbar.doc.mjs +1 -1
- package/src/TopNav/TopNav.doc.mjs +1 -0
- package/src/TopNav/TopNav.test.tsx +30 -0
- package/src/TopNav/TopNav.tsx +6 -4
- package/src/TopNav/TopNavHeading.tsx +5 -3
- package/src/TreeList/TreeList.tsx +5 -1
- package/src/TreeList/TreeListItem.tsx +6 -1
- package/src/Typeahead/BaseTypeahead.tsx +11 -4
- package/src/Typeahead/Typeahead.doc.mjs +1 -1
- package/src/Typeahead/Typeahead.tsx +3 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
- package/src/authoring/doc.ts +166 -0
- package/src/authoring/index.test.ts +52 -0
- package/src/authoring/index.ts +50 -0
- package/src/authoring/integration.ts +42 -0
- package/src/authoring/template.ts +74 -0
- package/src/config.test.ts +16 -0
- package/src/config.ts +92 -0
- package/src/docPropLiterals.test.ts +938 -0
- package/src/docs-types.ts +15 -10
- package/src/i18n/InternationalizationContext.ts +39 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +72 -0
- package/src/i18n/InternationalizationProvider.tsx +82 -0
- package/src/i18n/__tests__/e2e-pagination.test.tsx +172 -0
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +130 -0
- package/src/i18n/__tests__/resolve.test.ts +284 -0
- package/src/i18n/index.ts +32 -0
- package/src/i18n/resolve.ts +165 -0
- package/src/i18n/translator.ts +31 -0
- package/src/i18n/types.ts +53 -0
- package/src/i18n/useTranslator.doc.mjs +46 -0
- package/src/i18n/useTranslator.ts +50 -0
- package/src/index.ts +3 -0
- package/src/theme/hct.ts +0 -4
- package/src/utils/color.test.ts +101 -1
- package/src/utils/color.ts +23 -1
- package/src/utils/index.ts +8 -1
- package/dist/NavItem/index.d.ts +0 -9
- package/dist/NavItem/index.d.ts.map +0 -1
- package/dist/NavItem/index.js +0 -10
- package/src/NavItem/index.ts +0 -11
|
@@ -14,14 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
import {useMemo} from 'react';
|
|
16
16
|
import type {SearchSource} from '../Typeahead/types';
|
|
17
|
+
import {useTranslator} from '../i18n';
|
|
18
|
+
import {resolveOperatorLabel} from './resolveOperatorLabel';
|
|
17
19
|
import type {InternalConfig} from './useInternalConfig';
|
|
18
20
|
import type {PowerSearchItem, PowerSearchOperator, FilterValue} from './types';
|
|
19
21
|
|
|
20
22
|
export function usePowerSearchSource(
|
|
21
23
|
config: InternalConfig,
|
|
22
24
|
): SearchSource<PowerSearchItem> {
|
|
25
|
+
const t = useTranslator();
|
|
23
26
|
return useMemo(() => {
|
|
24
27
|
const allItems = buildFieldItems(config);
|
|
28
|
+
// Resolver stays inline — `t()` internally memoizes both catalog
|
|
29
|
+
// lookups and parsed IntlMessageFormat instances, so calling it
|
|
30
|
+
// per keystroke is already O(1).
|
|
31
|
+
const opLabel = (op: PowerSearchOperator): string =>
|
|
32
|
+
resolveOperatorLabel(op, t);
|
|
25
33
|
|
|
26
34
|
return {
|
|
27
35
|
search(query: string): PowerSearchItem[] {
|
|
@@ -68,14 +76,15 @@ export function usePowerSearchSource(
|
|
|
68
76
|
|
|
69
77
|
// Check each field+operator combo against the query
|
|
70
78
|
for (const op of field.operators) {
|
|
71
|
-
const combinedLabel =
|
|
79
|
+
const combinedLabel =
|
|
80
|
+
`${field.label} ${opLabel(op)}`.toLowerCase();
|
|
72
81
|
if (combinedLabel.includes(lower)) {
|
|
73
82
|
const id = `${field.key}:${op.key}`;
|
|
74
83
|
if (!seen.has(id)) {
|
|
75
84
|
seen.add(id);
|
|
76
85
|
results.push({
|
|
77
86
|
id,
|
|
78
|
-
label: `${field.label} ${op
|
|
87
|
+
label: `${field.label} ${opLabel(op)}`,
|
|
79
88
|
auxiliaryData: {
|
|
80
89
|
fieldKey: field.key,
|
|
81
90
|
operatorKey: op.key,
|
|
@@ -100,7 +109,7 @@ export function usePowerSearchSource(
|
|
|
100
109
|
// Try "<field> <operator> <value>" first (longer match wins)
|
|
101
110
|
let hasExactOperatorMatch = false;
|
|
102
111
|
for (const op of field.operators) {
|
|
103
|
-
const prefix = `${fieldLabel} ${op.
|
|
112
|
+
const prefix = `${fieldLabel} ${opLabel(op).toLowerCase()} `;
|
|
104
113
|
if (lower.startsWith(prefix) && lower.length > prefix.length) {
|
|
105
114
|
const rawValue = query.slice(prefix.length);
|
|
106
115
|
const matches = resolveValueMatches(op, rawValue);
|
|
@@ -113,7 +122,7 @@ export function usePowerSearchSource(
|
|
|
113
122
|
seen.add(id);
|
|
114
123
|
results.push({
|
|
115
124
|
id,
|
|
116
|
-
label: `${field.label} ${op
|
|
125
|
+
label: `${field.label} ${opLabel(op)} ${match.quoted ? `"${match.displayValue}"` : match.displayValue}`,
|
|
117
126
|
auxiliaryData: {
|
|
118
127
|
fieldKey: field.key,
|
|
119
128
|
operatorKey: op.key,
|
|
@@ -136,7 +145,7 @@ export function usePowerSearchSource(
|
|
|
136
145
|
// Check the remainder isn't the start of an operator name
|
|
137
146
|
const remainder = lower.slice(fieldPrefix.length);
|
|
138
147
|
const isOperatorPrefix = field.operators.some(op =>
|
|
139
|
-
op.
|
|
148
|
+
opLabel(op).toLowerCase().startsWith(remainder),
|
|
140
149
|
);
|
|
141
150
|
if (!isOperatorPrefix) {
|
|
142
151
|
const rawValue = query.slice(fieldPrefix.length);
|
|
@@ -148,7 +157,7 @@ export function usePowerSearchSource(
|
|
|
148
157
|
seen.add(id);
|
|
149
158
|
results.push({
|
|
150
159
|
id,
|
|
151
|
-
label: `${field.label} ${op
|
|
160
|
+
label: `${field.label} ${opLabel(op)} ${match.quoted ? `"${match.displayValue}"` : match.displayValue}`,
|
|
152
161
|
auxiliaryData: {
|
|
153
162
|
fieldKey: field.key,
|
|
154
163
|
operatorKey: op.key,
|
|
@@ -171,7 +180,7 @@ export function usePowerSearchSource(
|
|
|
171
180
|
f =>
|
|
172
181
|
f.label.toLowerCase() === lower ||
|
|
173
182
|
f.operators.some(
|
|
174
|
-
op => `${f.label} ${op
|
|
183
|
+
op => `${f.label} ${opLabel(op)}`.toLowerCase() === lower,
|
|
175
184
|
),
|
|
176
185
|
);
|
|
177
186
|
if (contentFieldKey && !hasExactMatch) {
|
|
@@ -197,7 +206,7 @@ export function usePowerSearchSource(
|
|
|
197
206
|
return allItems;
|
|
198
207
|
},
|
|
199
208
|
};
|
|
200
|
-
}, [config]);
|
|
209
|
+
}, [config, t]);
|
|
201
210
|
}
|
|
202
211
|
|
|
203
212
|
interface ValueMatch {
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
import {mergeProps, mergeRefs} from '../utils';
|
|
34
34
|
import type {ResizableProps} from './useResizable';
|
|
35
35
|
import {themeProps} from '../utils/themeProps';
|
|
36
|
+
import {useTranslator} from '../i18n';
|
|
36
37
|
|
|
37
38
|
const KEYBOARD_STEP = 10;
|
|
38
39
|
const KEYBOARD_LARGE_STEP = 50;
|
|
@@ -307,7 +308,7 @@ export function ResizeHandle({
|
|
|
307
308
|
hasDivider = false,
|
|
308
309
|
isAlwaysVisible = true,
|
|
309
310
|
pillPlacement = 'auto',
|
|
310
|
-
label
|
|
311
|
+
label: labelFromProps,
|
|
311
312
|
resizable,
|
|
312
313
|
children,
|
|
313
314
|
xstyle,
|
|
@@ -315,6 +316,8 @@ export function ResizeHandle({
|
|
|
315
316
|
ref,
|
|
316
317
|
...props
|
|
317
318
|
}: ResizeHandleProps) {
|
|
319
|
+
const t = useTranslator();
|
|
320
|
+
const label = labelFromProps ?? t('@astryx.resizable.handle.label');
|
|
318
321
|
const handleRef = useRef<HTMLDivElement>(null);
|
|
319
322
|
// Removes the in-flight drag's window listeners (and resets body styles).
|
|
320
323
|
// Held in a ref so unmount can tear down a drag that never got a pointerup.
|
|
@@ -49,13 +49,13 @@ export const docs = {
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: 'padding',
|
|
52
|
-
type: '
|
|
52
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
53
53
|
description: 'Internal padding using the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10). Use padding={0} for edge-to-edge content.',
|
|
54
54
|
default: '4',
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
name: 'paddingBlock',
|
|
58
|
-
type: '
|
|
58
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
59
59
|
description: 'Block (vertical) padding override. Overrides only the block-axis padding while preserving inline padding from `padding` or the container theme default. Accepts the spacing scale (0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10).',
|
|
60
60
|
},
|
|
61
61
|
{
|
|
@@ -131,13 +131,13 @@ export const docsZh = {
|
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
133
|
name: 'padding',
|
|
134
|
-
type: '
|
|
134
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
135
135
|
description: '使用间距比例的内部内边距(0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10)。使用 padding={0} 实现全宽内容。',
|
|
136
136
|
default: '4',
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
name: 'paddingBlock',
|
|
140
|
-
type: '
|
|
140
|
+
type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10',
|
|
141
141
|
description: '块(垂直)方向内边距覆盖。仅覆盖块轴内边距,同时保留来自 padding 或容器主题默认值的行内内边距。使用间距比例(0, 0.5, 1, 1.5, 2, 3, 4, 5, 6, 8, 10)。',
|
|
142
142
|
},
|
|
143
143
|
{
|
|
@@ -25,7 +25,7 @@ export const docs = {
|
|
|
25
25
|
{name: 'onChange', type: '(isSelected: boolean) => void', description: 'Called when toggled.', required: true},
|
|
26
26
|
{name: 'isDisabled', type: 'boolean', description: 'Disables the card.', default: 'false'},
|
|
27
27
|
{name: 'children', type: 'ReactNode', description: 'Card content.'},
|
|
28
|
-
{name: 'padding', type:
|
|
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
30
|
{name: 'width', type: 'SizeValue', description: 'Card width.'},
|
|
31
31
|
{name: 'height', type: 'SizeValue', description: 'Card height.'},
|
|
@@ -36,7 +36,8 @@ export const docs = {
|
|
|
36
36
|
{
|
|
37
37
|
name: 'options',
|
|
38
38
|
type: 'SelectorOption[]',
|
|
39
|
-
description:
|
|
39
|
+
description:
|
|
40
|
+
'Array of items: strings, objects with value/label/icon/disabled, dividers ({type: "divider"}), or sections ({type: "section", title, items}).',
|
|
40
41
|
required: true,
|
|
41
42
|
},
|
|
42
43
|
{
|
|
@@ -59,7 +60,8 @@ export const docs = {
|
|
|
59
60
|
{
|
|
60
61
|
name: 'hasSearch',
|
|
61
62
|
type: 'boolean',
|
|
62
|
-
description:
|
|
63
|
+
description:
|
|
64
|
+
'Whether to show a search input for filtering options. As the user types, the match count (or "No results found") is announced to screen readers via a polite live region.',
|
|
63
65
|
default: 'false',
|
|
64
66
|
},
|
|
65
67
|
{
|
|
@@ -135,7 +137,8 @@ export const docs = {
|
|
|
135
137
|
{
|
|
136
138
|
name: 'xstyle',
|
|
137
139
|
type: 'StyleXStyles',
|
|
138
|
-
description:
|
|
140
|
+
description:
|
|
141
|
+
'StyleX styles for layout customization (margins, positioning, sizing). Must be a stylex.create() value: not an inline style object like style={{}}.',
|
|
139
142
|
},
|
|
140
143
|
],
|
|
141
144
|
components: [{name: 'SelectorOption'}],
|
|
@@ -9,12 +9,23 @@
|
|
|
9
9
|
* SYNC: When Selector.tsx API changes, update these tests.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
-
import {
|
|
12
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
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 {Selector} from './Selector';
|
|
16
22
|
import {SelectorOption} from './SelectorOption';
|
|
17
23
|
import {InputGroup, InputGroupText} from '../InputGroup';
|
|
24
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
25
|
+
|
|
26
|
+
function politeRegion(): HTMLElement | null {
|
|
27
|
+
return document.querySelector('[data-astryx-live-region="polite"]');
|
|
28
|
+
}
|
|
18
29
|
|
|
19
30
|
// Mock showPopover and hidePopover methods since they're not implemented in jsdom
|
|
20
31
|
beforeEach(() => {
|
|
@@ -42,6 +53,10 @@ beforeEach(() => {
|
|
|
42
53
|
};
|
|
43
54
|
});
|
|
44
55
|
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
__resetLiveRegionsForTest();
|
|
58
|
+
});
|
|
59
|
+
|
|
45
60
|
// Helper: jsdom popover content is in the DOM but may not be
|
|
46
61
|
// "visible" in the accessibility tree. Use hidden: true to find it.
|
|
47
62
|
const h = {hidden: true} as const;
|
|
@@ -536,7 +551,11 @@ describe('Selector', () => {
|
|
|
536
551
|
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
537
552
|
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
538
553
|
expect(screen.queryAllByRole('option', h)).toHaveLength(0);
|
|
539
|
-
|
|
554
|
+
// Scope to the listbox: the polite live region also announces "No results
|
|
555
|
+
// found", so an unscoped query matches both the visible empty state and
|
|
556
|
+
// the a11y announcement.
|
|
557
|
+
const listbox = screen.getByRole('listbox', h);
|
|
558
|
+
expect(within(listbox).getByText('No results found')).toBeInTheDocument();
|
|
540
559
|
});
|
|
541
560
|
|
|
542
561
|
it('calls onChange when selecting a filtered option', async () => {
|
|
@@ -599,6 +618,82 @@ describe('Selector', () => {
|
|
|
599
618
|
screen.getByPlaceholderText('Find a fruit...'),
|
|
600
619
|
).toBeInTheDocument();
|
|
601
620
|
});
|
|
621
|
+
|
|
622
|
+
describe('result announcements', () => {
|
|
623
|
+
it('announces the match count politely while searching', async () => {
|
|
624
|
+
const user = userEvent.setup();
|
|
625
|
+
render(
|
|
626
|
+
<Selector
|
|
627
|
+
label="Fruit"
|
|
628
|
+
options={OPTIONS}
|
|
629
|
+
value="Apple"
|
|
630
|
+
onChange={() => {}}
|
|
631
|
+
hasSearch
|
|
632
|
+
/>,
|
|
633
|
+
);
|
|
634
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
635
|
+
// "a" matches Apple and Banana.
|
|
636
|
+
await user.type(screen.getByRole('combobox', h), 'a');
|
|
637
|
+
await waitFor(() => {
|
|
638
|
+
expect(politeRegion()).toHaveTextContent('2 results');
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it('announces the singular form when one option matches', async () => {
|
|
643
|
+
const user = userEvent.setup();
|
|
644
|
+
render(
|
|
645
|
+
<Selector
|
|
646
|
+
label="Fruit"
|
|
647
|
+
options={OPTIONS}
|
|
648
|
+
value="Apple"
|
|
649
|
+
onChange={() => {}}
|
|
650
|
+
hasSearch
|
|
651
|
+
/>,
|
|
652
|
+
);
|
|
653
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
654
|
+
// "ban" matches only Banana. Anchored so it cannot pass on "1 results".
|
|
655
|
+
await user.type(screen.getByRole('combobox', h), 'ban');
|
|
656
|
+
await waitFor(() => {
|
|
657
|
+
expect(politeRegion()).toHaveTextContent(/^1 result$/);
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
it('announces "No results found" when nothing matches', async () => {
|
|
662
|
+
const user = userEvent.setup();
|
|
663
|
+
render(
|
|
664
|
+
<Selector
|
|
665
|
+
label="Fruit"
|
|
666
|
+
options={OPTIONS}
|
|
667
|
+
value="Apple"
|
|
668
|
+
onChange={() => {}}
|
|
669
|
+
hasSearch
|
|
670
|
+
/>,
|
|
671
|
+
);
|
|
672
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
673
|
+
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
674
|
+
await waitFor(() => {
|
|
675
|
+
expect(politeRegion()).toHaveTextContent('No results found');
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
it('does not announce results until the user searches', async () => {
|
|
680
|
+
const user = userEvent.setup();
|
|
681
|
+
render(
|
|
682
|
+
<Selector
|
|
683
|
+
label="Fruit"
|
|
684
|
+
options={OPTIONS}
|
|
685
|
+
value="Apple"
|
|
686
|
+
onChange={() => {}}
|
|
687
|
+
hasSearch
|
|
688
|
+
/>,
|
|
689
|
+
);
|
|
690
|
+
// Popover closed: nothing announced.
|
|
691
|
+
expect(politeRegion()?.textContent ?? '').toBe('');
|
|
692
|
+
// Open with an empty query: still nothing announced.
|
|
693
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
694
|
+
expect(politeRegion()?.textContent ?? '').toBe('');
|
|
695
|
+
});
|
|
696
|
+
});
|
|
602
697
|
});
|
|
603
698
|
|
|
604
699
|
describe('keyboard accessibility', () => {
|
|
@@ -869,7 +964,12 @@ describe('Selector', () => {
|
|
|
869
964
|
it('submits the selected value under htmlName', () => {
|
|
870
965
|
const {container} = render(
|
|
871
966
|
<form>
|
|
872
|
-
<Selector
|
|
967
|
+
<Selector
|
|
968
|
+
label="Fruit"
|
|
969
|
+
htmlName="fruit"
|
|
970
|
+
options={OPTIONS}
|
|
971
|
+
value="Banana"
|
|
972
|
+
/>
|
|
873
973
|
</form>,
|
|
874
974
|
);
|
|
875
975
|
const data = new FormData(container.querySelector('form')!);
|
|
@@ -889,10 +989,18 @@ describe('Selector', () => {
|
|
|
889
989
|
it('is excluded from form data when disabled', () => {
|
|
890
990
|
const {container} = render(
|
|
891
991
|
<form>
|
|
892
|
-
<Selector
|
|
992
|
+
<Selector
|
|
993
|
+
label="Fruit"
|
|
994
|
+
htmlName="fruit"
|
|
995
|
+
options={OPTIONS}
|
|
996
|
+
value="Banana"
|
|
997
|
+
isDisabled
|
|
998
|
+
/>
|
|
893
999
|
</form>,
|
|
894
1000
|
);
|
|
895
|
-
expect([
|
|
1001
|
+
expect([
|
|
1002
|
+
...new FormData(container.querySelector('form')!).keys(),
|
|
1003
|
+
]).toEqual([]);
|
|
896
1004
|
});
|
|
897
1005
|
});
|
|
898
1006
|
});
|
|
@@ -42,6 +42,7 @@ import {Divider} from '../Divider';
|
|
|
42
42
|
import {layerAnimations} from '../Layer/layerAnimations.stylex';
|
|
43
43
|
import type {LayerPlacement} from '../Layer/useLayer';
|
|
44
44
|
import {Spinner} from '../Spinner';
|
|
45
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
45
46
|
import {
|
|
46
47
|
colorVars,
|
|
47
48
|
sizeVars,
|
|
@@ -72,6 +73,7 @@ import {themeProps} from '../utils/themeProps';
|
|
|
72
73
|
import {groupStyles} from '../InputGroup/groupStyles';
|
|
73
74
|
import {useInputGroup} from '../InputGroup/InputGroupContext';
|
|
74
75
|
import {VisuallyHidden} from '../VisuallyHidden';
|
|
76
|
+
import {useTranslator} from '../i18n';
|
|
75
77
|
|
|
76
78
|
const styles = stylex.create({
|
|
77
79
|
// Trigger container — the enhanced click target wrapping the combobox button and clear button as siblings
|
|
@@ -524,8 +526,7 @@ type SelectorPropsClearable<T extends SelectorOptionType = SelectorOptionType> =
|
|
|
524
526
|
};
|
|
525
527
|
|
|
526
528
|
export type SelectorProps<T extends SelectorOptionType = SelectorOptionType> =
|
|
527
|
-
|
|
|
528
|
-
| SelectorPropsClearable<T>;
|
|
529
|
+
SelectorPropsNonClearable<T> | SelectorPropsClearable<T>;
|
|
529
530
|
|
|
530
531
|
/**
|
|
531
532
|
* Default option renderer
|
|
@@ -536,6 +537,23 @@ function DefaultOption({option}: {option: SelectorOptionData}) {
|
|
|
536
537
|
);
|
|
537
538
|
}
|
|
538
539
|
|
|
540
|
+
// Case-insensitive substring filter over the selectable options. Shared by the
|
|
541
|
+
// `filteredItems` memo (rendering) and the search-change handler, which needs
|
|
542
|
+
// the count for the *next* query synchronously to announce it exactly once per
|
|
543
|
+
// keystroke rather than reacting to state in an effect.
|
|
544
|
+
function filterOptionsByQuery(
|
|
545
|
+
items: SelectorOptionData[],
|
|
546
|
+
query: string,
|
|
547
|
+
): SelectorOptionData[] {
|
|
548
|
+
if (!query) {
|
|
549
|
+
return items;
|
|
550
|
+
}
|
|
551
|
+
const q = query.toLowerCase();
|
|
552
|
+
return items.filter(item =>
|
|
553
|
+
(item.label ?? item.value).toLowerCase().includes(q),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
|
|
539
557
|
/**
|
|
540
558
|
* A selector/dropdown component for choosing from a list of options.
|
|
541
559
|
*
|
|
@@ -553,6 +571,7 @@ function DefaultOption({option}: {option: SelectorOptionData}) {
|
|
|
553
571
|
export function Selector<T extends SelectorOptionType>(
|
|
554
572
|
props: SelectorProps<T>,
|
|
555
573
|
) {
|
|
574
|
+
const t = useTranslator();
|
|
556
575
|
const {
|
|
557
576
|
label,
|
|
558
577
|
isLabelHidden = false,
|
|
@@ -566,7 +585,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
566
585
|
onChange,
|
|
567
586
|
changeAction,
|
|
568
587
|
isLoading = false,
|
|
569
|
-
placeholder
|
|
588
|
+
placeholder: placeholderFromProps,
|
|
570
589
|
size: sizeProp,
|
|
571
590
|
status,
|
|
572
591
|
labelTooltip,
|
|
@@ -574,7 +593,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
574
593
|
htmlName,
|
|
575
594
|
renderOption,
|
|
576
595
|
hasSearch = false,
|
|
577
|
-
searchPlaceholder
|
|
596
|
+
searchPlaceholder: searchPlaceholderFromProps,
|
|
578
597
|
placement,
|
|
579
598
|
isDefaultOpen = false,
|
|
580
599
|
'data-testid': testId,
|
|
@@ -585,6 +604,9 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
585
604
|
hasClear: hasClearProp,
|
|
586
605
|
...rest
|
|
587
606
|
} = props as SelectorPropsClearable<T>;
|
|
607
|
+
const placeholder = placeholderFromProps ?? t('@astryx.selector.placeholder');
|
|
608
|
+
const searchPlaceholder =
|
|
609
|
+
searchPlaceholderFromProps ?? t('@astryx.selector.searchPlaceholder');
|
|
588
610
|
const hasClear = hasClearProp === true;
|
|
589
611
|
const size = useSize(sizeProp, 'md');
|
|
590
612
|
|
|
@@ -637,15 +659,10 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
637
659
|
);
|
|
638
660
|
|
|
639
661
|
// Filter items by search query
|
|
640
|
-
const filteredItems = useMemo(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const query = searchQuery.toLowerCase();
|
|
645
|
-
return selectableItems.filter(item =>
|
|
646
|
-
(item.label ?? item.value).toLowerCase().includes(query),
|
|
647
|
-
);
|
|
648
|
-
}, [selectableItems, searchQuery]);
|
|
662
|
+
const filteredItems = useMemo(
|
|
663
|
+
() => filterOptionsByQuery(selectableItems, searchQuery),
|
|
664
|
+
[selectableItems, searchQuery],
|
|
665
|
+
);
|
|
649
666
|
|
|
650
667
|
// Find selected item and its index for positioning
|
|
651
668
|
const selectedItemIndex = useMemo(() => {
|
|
@@ -661,11 +678,20 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
661
678
|
// Ref for listbox to measure selected item position
|
|
662
679
|
const listboxRef = useRef<HTMLDivElement>(null);
|
|
663
680
|
|
|
681
|
+
// Announce match counts / "No results found" politely as the user types, so
|
|
682
|
+
// screen-reader users hear how many options remain. Filtering was previously
|
|
683
|
+
// silent (comboboxes-7). Mirrors BaseTypeahead, which announces from its
|
|
684
|
+
// query-change callback (not a reactive effect) via the same useAnnounce hook.
|
|
685
|
+
const announce = useAnnounce();
|
|
686
|
+
|
|
664
687
|
// Layer for dropdown positioning
|
|
665
688
|
const handleLayerHide = useCallback(() => {
|
|
666
689
|
setSearchQuery('');
|
|
690
|
+
// Clear any lingering result count when the popover closes so stale status
|
|
691
|
+
// text does not linger in the a11y tree.
|
|
692
|
+
announce('');
|
|
667
693
|
triggerRef.current?.focus();
|
|
668
|
-
}, []);
|
|
694
|
+
}, [announce]);
|
|
669
695
|
|
|
670
696
|
const popover = usePopover({
|
|
671
697
|
onHide: handleLayerHide,
|
|
@@ -685,6 +711,29 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
685
711
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- mount-only: isDefaultOpen is not reactive
|
|
686
712
|
}, []);
|
|
687
713
|
|
|
714
|
+
// Announce the filtered result count from the query-change handler (matching
|
|
715
|
+
// BaseTypeahead) rather than a reactive effect: computing the count for the
|
|
716
|
+
// next query here fires the announcement exactly once per keystroke and does
|
|
717
|
+
// not re-speak on unrelated re-renders.
|
|
718
|
+
const handleSearchChange = useCallback(
|
|
719
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
720
|
+
const nextQuery = event.target.value;
|
|
721
|
+
setSearchQuery(nextQuery);
|
|
722
|
+
if (nextQuery.length === 0) {
|
|
723
|
+
// Emptying the query clears the region rather than announcing a count.
|
|
724
|
+
announce('');
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const count = filterOptionsByQuery(selectableItems, nextQuery).length;
|
|
728
|
+
announce(
|
|
729
|
+
count === 0
|
|
730
|
+
? 'No results found'
|
|
731
|
+
: `${count} result${count === 1 ? '' : 's'}`,
|
|
732
|
+
);
|
|
733
|
+
},
|
|
734
|
+
[announce, selectableItems],
|
|
735
|
+
);
|
|
736
|
+
|
|
688
737
|
// Calculate offset to position selected item over trigger. Explicit
|
|
689
738
|
// placement opts out of the selector-specific overlay behavior and uses the
|
|
690
739
|
// standard layer positioning API instead.
|
|
@@ -803,10 +852,10 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
803
852
|
? getItemId(highlightedIndex)
|
|
804
853
|
: undefined
|
|
805
854
|
}
|
|
806
|
-
aria-label=
|
|
855
|
+
aria-label={t('@astryx.selector.searchOptions')}
|
|
807
856
|
type="text"
|
|
808
857
|
value={searchQuery}
|
|
809
|
-
onChange={
|
|
858
|
+
onChange={handleSearchChange}
|
|
810
859
|
onKeyDown={e => {
|
|
811
860
|
// Arrow keys navigate options; Enter selects; Escape/Tab close.
|
|
812
861
|
// Home/End are left to the input for caret movement.
|
|
@@ -831,10 +880,12 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
831
880
|
listboxId,
|
|
832
881
|
searchQuery,
|
|
833
882
|
searchPlaceholder,
|
|
883
|
+
handleSearchChange,
|
|
834
884
|
onKeyDown,
|
|
835
885
|
popover.isOpen,
|
|
836
886
|
highlightedIndex,
|
|
837
887
|
getItemId,
|
|
888
|
+
t,
|
|
838
889
|
]);
|
|
839
890
|
|
|
840
891
|
// Render an individual item
|
|
@@ -1014,7 +1065,7 @@ export function Selector<T extends SelectorOptionType>(
|
|
|
1014
1065
|
<button
|
|
1015
1066
|
type="button"
|
|
1016
1067
|
onClick={handleClear}
|
|
1017
|
-
aria-label={
|
|
1068
|
+
aria-label={t('@astryx.selector.clearLabel', {label})}
|
|
1018
1069
|
{...stylex.props(styles.clearButton)}>
|
|
1019
1070
|
<Icon icon="close" size="sm" color="secondary" />
|
|
1020
1071
|
</button>
|
package/src/SideNav/SideNav.tsx
CHANGED
|
@@ -45,6 +45,7 @@ import {useResizable} from '../Resizable/useResizable';
|
|
|
45
45
|
import type {ResizableConfig} from '../Resizable/useResizable';
|
|
46
46
|
import {ResizeHandle} from '../Resizable/ResizeHandle';
|
|
47
47
|
import {themeProps} from '../utils/themeProps';
|
|
48
|
+
import {useTranslator} from '../i18n';
|
|
48
49
|
|
|
49
50
|
// =============================================================================
|
|
50
51
|
// Constants
|
|
@@ -330,6 +331,7 @@ export function SideNav({
|
|
|
330
331
|
handleRef,
|
|
331
332
|
...props
|
|
332
333
|
}: SideNavProps) {
|
|
334
|
+
const t = useTranslator();
|
|
333
335
|
// Parse collapsible prop
|
|
334
336
|
const collapsibleConfig = typeof collapsible === 'object' ? collapsible : {};
|
|
335
337
|
const isCollapsible = !!collapsible;
|
|
@@ -504,7 +506,7 @@ export function SideNav({
|
|
|
504
506
|
<nav
|
|
505
507
|
ref={mergeRefs(ref, navRef)}
|
|
506
508
|
role="navigation"
|
|
507
|
-
aria-label=
|
|
509
|
+
aria-label={t('@astryx.sideNav.label')}
|
|
508
510
|
data-testid={testId}
|
|
509
511
|
{...mergeProps(
|
|
510
512
|
themeProps('side-nav'),
|
|
@@ -569,7 +571,7 @@ export function SideNav({
|
|
|
569
571
|
pillPlacement="end"
|
|
570
572
|
isAlwaysVisible={false}
|
|
571
573
|
resizable={resizableHook.props}
|
|
572
|
-
label=
|
|
574
|
+
label={t('@astryx.sideNav.resizeSidebar')}
|
|
573
575
|
/>
|
|
574
576
|
</div>
|
|
575
577
|
) : (
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
type SideNavImperativeCollapseHandle,
|
|
31
31
|
} from './SideNavCollapseContext';
|
|
32
32
|
import {useAppShellMobile} from '../AppShell/AppShellMobileContext';
|
|
33
|
+
import {useTranslator} from '../i18n';
|
|
33
34
|
|
|
34
35
|
// =============================================================================
|
|
35
36
|
// Styles
|
|
@@ -105,6 +106,7 @@ export function SideNavCollapseButton({
|
|
|
105
106
|
onClick: onClickProp,
|
|
106
107
|
...props
|
|
107
108
|
}: SideNavCollapseButtonProps) {
|
|
109
|
+
const t = useTranslator();
|
|
108
110
|
const {isCollapsed, toggle, isCollapsible} =
|
|
109
111
|
useSideNavCollapseState(handleRef);
|
|
110
112
|
const {isMobile} = useAppShellMobile();
|
|
@@ -118,7 +120,7 @@ export function SideNavCollapseButton({
|
|
|
118
120
|
return (
|
|
119
121
|
<Button
|
|
120
122
|
ref={ref}
|
|
121
|
-
label={label ?? (isCollapsed ? '
|
|
123
|
+
label={label ?? (isCollapsed ? t('@astryx.sideNavCollapseButton.expandSidebar') : t('@astryx.sideNavCollapseButton.collapseSidebar'))}
|
|
122
124
|
variant="ghost"
|
|
123
125
|
{...props}
|
|
124
126
|
onClick={composeEventHandlers(onClickProp, toggle)}
|
|
@@ -44,6 +44,7 @@ import type {BaseProps} from '../BaseProps';
|
|
|
44
44
|
import {useMenuHover} from '../hooks/useMenuHover';
|
|
45
45
|
import {NavHeadingCloseContext} from '../NavMenu/NavMenuContext';
|
|
46
46
|
import {themeProps} from '../utils/themeProps';
|
|
47
|
+
import {useTranslator} from '../i18n';
|
|
47
48
|
|
|
48
49
|
// =============================================================================
|
|
49
50
|
// Styles
|
|
@@ -342,13 +343,14 @@ export function SideNavHeading({
|
|
|
342
343
|
ref,
|
|
343
344
|
...props
|
|
344
345
|
}: SideNavHeadingProps) {
|
|
346
|
+
const t = useTranslator();
|
|
345
347
|
const LinkComponent = useLinkComponent(as);
|
|
346
348
|
const {isCollapsed} = useSideNavCollapse();
|
|
347
349
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
348
350
|
const collapsedItemRef = useRef<HTMLElement>(null);
|
|
349
351
|
|
|
350
352
|
const popover = usePopover({
|
|
351
|
-
dialogLabel: '
|
|
353
|
+
dialogLabel: t('@astryx.sideNav.heading.dialogLabel'),
|
|
352
354
|
hasCloseButton: false,
|
|
353
355
|
});
|
|
354
356
|
|
|
@@ -603,7 +605,7 @@ export function SideNavHeading({
|
|
|
603
605
|
{renderTextContent(
|
|
604
606
|
<button
|
|
605
607
|
type="button"
|
|
606
|
-
aria-label=
|
|
608
|
+
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
607
609
|
onClick={e => {
|
|
608
610
|
e.stopPropagation();
|
|
609
611
|
triggerProps.onClick();
|
|
@@ -665,7 +667,7 @@ export function SideNavHeading({
|
|
|
665
667
|
showChevron ? (
|
|
666
668
|
<button
|
|
667
669
|
type="button"
|
|
668
|
-
aria-label=
|
|
670
|
+
aria-label={t('@astryx.sideNav.heading.openMenu')}
|
|
669
671
|
onClick={e => {
|
|
670
672
|
e.stopPropagation();
|
|
671
673
|
triggerProps.onClick();
|