@astryxdesign/core 0.1.9 → 0.2.0-canary.0f56f82
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 +107 -0
- package/dist/Avatar/Avatar.d.ts +42 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +190 -59
- package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- 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 +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
- package/dist/Banner/Banner.js +2 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
- package/dist/Breadcrumbs/index.d.ts +1 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +2 -1
- package/dist/Button/Button.d.ts +1 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +6 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +50 -9
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +2 -2
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- package/dist/Card/Card.js +1 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +22 -12
- package/dist/Chat/ChatComposerInput.js +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +3 -1
- package/dist/Chat/ChatLayout.js +4 -4
- package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
- package/dist/Chat/ChatMessageBubble.js +8 -8
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +10 -3
- package/dist/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -6
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +19 -4
- 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/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +16 -10
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +42 -3
- package/dist/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +23 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +10 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +33 -19
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -18
- package/dist/Divider/Divider.d.ts +2 -2
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +13 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -1
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -5
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +10 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +51 -5
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +93 -65
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +10 -4
- package/dist/Icon/Icon.d.ts +15 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- package/dist/Item/Item.d.ts +16 -3
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +31 -6
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +10 -2
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +6 -3
- package/dist/List/ListItem.d.ts +11 -1
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +2 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -0
- package/dist/MetadataList/MetadataList.d.ts +1 -1
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +4 -2
- package/dist/MultiSelector/MultiSelector.d.ts +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +80 -42
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- package/dist/Outline/Outline.js +2 -2
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- 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/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +6 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +49 -19
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
- package/dist/Selector/Selector.d.ts +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +66 -17
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +2 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +87 -34
- package/dist/Spinner/Spinner.d.ts +3 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +11 -2
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +171 -91
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts +2 -11
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +5 -9
- package/dist/TabList/TabListContext.d.ts +0 -5
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +0 -5
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +30 -4
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
- package/dist/Table/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- package/dist/Thumbnail/Thumbnail.js +2 -2
- package/dist/TimeInput/TimeInput.d.ts +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +17 -17
- package/dist/Timestamp/Timestamp.d.ts +31 -3
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +47 -76
- package/dist/Timestamp/formatInstant.d.ts +41 -0
- package/dist/Timestamp/formatInstant.d.ts.map +1 -0
- package/dist/Timestamp/formatInstant.js +177 -0
- package/dist/Timestamp/index.d.ts +1 -0
- package/dist/Timestamp/index.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.d.ts +56 -0
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
- package/dist/Timestamp/tooltipEntries.js +163 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +61 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +3 -1
- package/dist/Token/Token.d.ts +34 -4
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +85 -45
- package/dist/Token/TokenLink.d.ts +62 -0
- package/dist/Token/TokenLink.d.ts.map +1 -0
- package/dist/Token/TokenLink.js +76 -0
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +9 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +4 -2
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -1
- package/dist/TopNav/TopNavItem.d.ts +3 -1
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +30 -3
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +9 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +1 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +8 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +32 -14
- package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +22 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +11 -2
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +74 -33
- package/dist/astryx.umd.js +51 -51
- package/dist/astryx.umd.js.map +4 -4
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- 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/useAnnounce.d.ts +3 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -1
- package/dist/hooks/useAnnounce.js +39 -1
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +52 -11
- 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/useHotkeys.d.ts +9 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +9 -0
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +169 -0
- package/dist/hooks/useKeyboardHint.d.ts +1 -1
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
- package/dist/hooks/useKeyboardHint.js +4 -2
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- 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/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/plainDate.d.ts +17 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +23 -4
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/locales/en.json +112 -0
- package/locales/pseudo.json +84 -0
- package/package.json +6 -1
- package/src/Avatar/Avatar.doc.mjs +50 -3
- package/src/Avatar/Avatar.test.tsx +218 -0
- package/src/Avatar/Avatar.tsx +285 -79
- package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
- package/src/Avatar/AvatarStatusDot.tsx +6 -4
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
- package/src/Banner/Banner.tsx +6 -6
- package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
- package/src/Breadcrumbs/index.ts +4 -0
- package/src/Button/Button.doc.mjs +0 -4
- package/src/Button/Button.test.tsx +16 -0
- package/src/Button/Button.tsx +6 -4
- package/src/Calendar/Calendar.test.tsx +170 -20
- package/src/Calendar/Calendar.tsx +73 -16
- package/src/Calendar/dayCellUtils.test.ts +18 -18
- package/src/Calendar/dayCellUtils.ts +2 -2
- package/src/Calendar/styles.ts +33 -39
- package/src/Card/Card.tsx +1 -1
- package/src/Carousel/Carousel.tsx +25 -6
- package/src/Chat/ChatComposer.doc.mjs +2 -2
- package/src/Chat/ChatComposerInput.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.tsx +2 -2
- package/src/Chat/ChatDictationButton.tsx +7 -1
- package/src/Chat/ChatLayout.tsx +4 -4
- package/src/Chat/ChatMessageBubble.tsx +15 -10
- package/src/Chat/ChatSystemMessage.test.tsx +5 -0
- package/src/Chat/ChatToolCalls.tsx +9 -2
- package/src/Chat/useTriggerMenu.tsx +1 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
- package/src/CheckboxInput/CheckboxInput.tsx +21 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- package/src/CheckboxList/CheckboxList.test.tsx +94 -3
- package/src/CheckboxList/CheckboxListItem.tsx +17 -10
- 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/CodeBlock/CodeBlock.test.tsx +17 -0
- package/src/CodeBlock/CodeBlock.tsx +38 -11
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +41 -2
- package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +59 -2
- package/src/ContextMenu/ContextMenu.tsx +22 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +25 -0
- package/src/DateInput/DateInput.test.tsx +230 -0
- package/src/DateInput/DateInput.tsx +51 -29
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
- package/src/DateTimeInput/DateTimeInput.tsx +44 -39
- package/src/Divider/Divider.test.tsx +32 -8
- package/src/Divider/Divider.tsx +14 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.doc.mjs +4 -0
- package/src/Field/Field.tsx +14 -9
- package/src/Field/FieldLabel.test.tsx +25 -0
- package/src/Field/FieldLabel.tsx +12 -3
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
- package/src/FieldStatus/FieldStatus.test.tsx +133 -0
- package/src/FieldStatus/FieldStatus.tsx +61 -4
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +104 -13
- package/src/FileInput/FileInput.tsx +106 -79
- package/src/HoverCard/useHoverCard.tsx +15 -3
- package/src/Icon/Icon.doc.mjs +13 -0
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +51 -3
- package/src/Item/Item.doc.mjs +5 -0
- package/src/Item/Item.test.tsx +88 -0
- package/src/Item/Item.tsx +57 -11
- package/src/Layer/layerAnimations.stylex.ts +23 -0
- package/src/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +17 -29
- package/src/List/List.tsx +6 -1
- package/src/List/ListItem.doc.mjs +12 -0
- package/src/List/ListItem.tsx +13 -0
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -0
- package/src/MetadataList/MetadataList.test.tsx +24 -0
- package/src/MetadataList/MetadataList.tsx +6 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
- package/src/MultiSelector/MultiSelector.test.tsx +402 -0
- package/src/MultiSelector/MultiSelector.tsx +120 -59
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +71 -0
- package/src/NumberInput/NumberInput.tsx +35 -26
- package/src/Outline/Outline.test.tsx +12 -12
- package/src/Outline/Outline.tsx +2 -2
- package/src/Pagination/Pagination.tsx +11 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +23 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/ProgressBar/ProgressBar.test.tsx +34 -0
- package/src/ProgressBar/ProgressBar.tsx +16 -1
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.test.tsx +26 -4
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +12 -5
- package/src/Resizable/ResizeHandle.test.tsx +94 -0
- package/src/Resizable/ResizeHandle.tsx +70 -20
- package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
- package/src/Selector/Selector.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +370 -0
- package/src/Selector/Selector.tsx +88 -20
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +9 -7
- package/src/SideNav/SideNavItem.tsx +5 -3
- package/src/Skeleton/Skeleton.test.tsx +16 -0
- package/src/Skeleton/Skeleton.tsx +13 -1
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +240 -12
- package/src/Slider/Slider.tsx +96 -23
- package/src/Spinner/Spinner.test.tsx +10 -8
- package/src/Spinner/Spinner.tsx +15 -5
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +111 -0
- package/src/Switch/Switch.tsx +149 -32
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabList.doc.mjs +0 -6
- package/src/TabList/TabList.test.tsx +3 -15
- package/src/TabList/TabList.tsx +6 -17
- package/src/TabList/TabListContext.ts +0 -6
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +34 -2
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
- package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
- package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
- package/src/Table/types.ts +33 -0
- package/src/Table/useTableRowStatus.doc.mjs +1 -1
- package/src/TextArea/TextArea.doc.mjs +21 -0
- package/src/TextArea/TextArea.test.tsx +23 -0
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.tsx +1 -1
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +23 -0
- package/src/TimeInput/TimeInput.tsx +24 -25
- package/src/Timestamp/Timestamp.doc.mjs +32 -6
- package/src/Timestamp/Timestamp.test.tsx +371 -0
- package/src/Timestamp/Timestamp.tsx +96 -93
- package/src/Timestamp/formatInstant.ts +218 -0
- package/src/Timestamp/index.ts +4 -0
- package/src/Timestamp/tooltipEntries.test.ts +552 -0
- package/src/Timestamp/tooltipEntries.ts +210 -0
- package/src/Toast/ToastViewport.test.tsx +218 -8
- package/src/Toast/ToastViewport.tsx +71 -12
- package/src/ToggleButton/ToggleButton.test.tsx +24 -0
- package/src/ToggleButton/ToggleButton.tsx +19 -1
- package/src/Token/Token.test.tsx +166 -15
- package/src/Token/Token.tsx +104 -47
- package/src/Token/TokenLink.tsx +107 -0
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
- package/src/Tokenizer/Tokenizer.test.tsx +23 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -2
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- package/src/TopNav/TopNav.test.tsx +93 -2
- package/src/TopNav/TopNavItem.doc.mjs +3 -3
- package/src/TopNav/TopNavItem.tsx +35 -6
- package/src/TopNav/TopNavMegaMenu.tsx +26 -2
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
- package/src/TreeList/TreeList.doc.mjs +6 -0
- package/src/TreeList/TreeList.test.tsx +50 -10
- package/src/TreeList/TreeList.tsx +5 -0
- package/src/TreeList/TreeListBranches.tsx +8 -6
- package/src/TreeList/TreeListItem.tsx +33 -11
- package/src/Typeahead/BaseTypeahead.tsx +42 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +112 -0
- package/src/Typeahead/Typeahead.tsx +17 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/forcedColors.ts +60 -0
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/doc-mjs.d.ts +19 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useAnnounce.test.tsx +75 -2
- package/src/hooks/useAnnounce.ts +47 -1
- package/src/hooks/useFocusTrap.test.tsx +104 -0
- package/src/hooks/useFocusTrap.ts +61 -12
- 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/useHotkeys.ts +9 -0
- package/src/hooks/useInputStatusIcon.test.tsx +221 -0
- package/src/hooks/useInputStatusIcon.tsx +235 -0
- package/src/hooks/useKeyboardHint.test.tsx +22 -0
- package/src/hooks/useKeyboardHint.tsx +6 -2
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/i18n/InternationalizationContext.ts +4 -0
- 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/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +42 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +24 -6
- package/src/utils/plainDate.ts +18 -4
- package/src/utils/rtlStyles.ts +27 -0
|
@@ -5,6 +5,7 @@ import {render, screen} from '@testing-library/react';
|
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
import {MetadataList} from './MetadataList';
|
|
7
7
|
import {MetadataListItem} from './MetadataListItem';
|
|
8
|
+
import {InternationalizationProvider} from '../i18n';
|
|
8
9
|
|
|
9
10
|
describe('MetadataList', () => {
|
|
10
11
|
it('renders a description list with items', () => {
|
|
@@ -87,6 +88,29 @@ describe('MetadataList', () => {
|
|
|
87
88
|
expect(screen.queryByText('B')).not.toBeInTheDocument();
|
|
88
89
|
});
|
|
89
90
|
|
|
91
|
+
it('localizes the show more / show less labels through the i18n catalog', async () => {
|
|
92
|
+
const user = userEvent.setup();
|
|
93
|
+
|
|
94
|
+
render(
|
|
95
|
+
<InternationalizationProvider
|
|
96
|
+
locale="fr"
|
|
97
|
+
overrides={{
|
|
98
|
+
fr: {
|
|
99
|
+
'@astryx.metadataList.showMore': 'Afficher plus',
|
|
100
|
+
'@astryx.metadataList.showLess': 'Afficher moins',
|
|
101
|
+
},
|
|
102
|
+
}}>
|
|
103
|
+
<MetadataList maxNumOfItems={1}>
|
|
104
|
+
<MetadataListItem label="A">1</MetadataListItem>
|
|
105
|
+
<MetadataListItem label="B">2</MetadataListItem>
|
|
106
|
+
</MetadataList>
|
|
107
|
+
</InternationalizationProvider>,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
await user.click(screen.getByText('Afficher plus'));
|
|
111
|
+
expect(screen.getByText('Afficher moins')).toBeInTheDocument();
|
|
112
|
+
});
|
|
113
|
+
|
|
90
114
|
it('does not show toggle in horizontal mode even with maxNumOfItems', () => {
|
|
91
115
|
render(
|
|
92
116
|
<MetadataList orientation="horizontal" maxNumOfItems={1}>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file MetadataList.tsx
|
|
7
|
-
* @input Uses React, ReactNode, StyleXStyles, theme tokens, MetadataListContext
|
|
7
|
+
* @input Uses React, ReactNode, StyleXStyles, theme tokens, MetadataListContext, i18n (useTranslator)
|
|
8
8
|
* @output Exports MetadataList component, MetadataListProps, MetadataListColumns types
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by MetadataList.test.tsx
|
|
10
10
|
*
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
import type {BaseProps} from '../BaseProps';
|
|
32
32
|
import {mergeProps} from '../utils';
|
|
33
33
|
import {themeProps} from '../utils/themeProps';
|
|
34
|
+
import {useTranslator} from '../i18n';
|
|
34
35
|
|
|
35
36
|
// =============================================================================
|
|
36
37
|
// Types
|
|
@@ -197,6 +198,7 @@ export function MetadataList({
|
|
|
197
198
|
const labelConfig = label ?? (isMultiColumn ? LABEL_TOP : LABEL_START);
|
|
198
199
|
const [isShowAll, setIsShowAll] = useState(false);
|
|
199
200
|
const contentId = useId();
|
|
201
|
+
const t = useTranslator();
|
|
200
202
|
|
|
201
203
|
const contextValue = useMemo(
|
|
202
204
|
() => ({
|
|
@@ -283,7 +285,9 @@ export function MetadataList({
|
|
|
283
285
|
aria-expanded={isShowAll}
|
|
284
286
|
onClick={() => setIsShowAll(prev => !prev)}
|
|
285
287
|
{...stylex.props(styles.toggleButton)}>
|
|
286
|
-
{isShowAll
|
|
288
|
+
{isShowAll
|
|
289
|
+
? t('@astryx.metadataList.showLess')
|
|
290
|
+
: t('@astryx.metadataList.showMore')}
|
|
287
291
|
</button>
|
|
288
292
|
)}
|
|
289
293
|
</div>
|
|
@@ -21,6 +21,11 @@ export const docs = {
|
|
|
21
21
|
theming: {
|
|
22
22
|
targets: [
|
|
23
23
|
{className: 'astryx-multi-selector', visualProps: ['size', 'status']},
|
|
24
|
+
{className: 'astryx-multi-selector-clear-icon'},
|
|
25
|
+
{
|
|
26
|
+
className: 'astryx-multi-selector-indicator-icon',
|
|
27
|
+
states: ['state'],
|
|
28
|
+
},
|
|
24
29
|
],
|
|
25
30
|
},
|
|
26
31
|
components: [
|
|
@@ -155,12 +160,25 @@ export const docs = {
|
|
|
155
160
|
type: "{type: 'error' | 'warning' | 'success', message?: string}",
|
|
156
161
|
description: 'Validation status with an optional message.',
|
|
157
162
|
},
|
|
163
|
+
{
|
|
164
|
+
name: 'statusVariant',
|
|
165
|
+
type: "'attached' | 'detached'",
|
|
166
|
+
description:
|
|
167
|
+
'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.',
|
|
168
|
+
default: "'attached'",
|
|
169
|
+
},
|
|
158
170
|
{
|
|
159
171
|
name: 'renderOption',
|
|
160
172
|
type: '(option: MultiSelectorOptionData) => ReactNode',
|
|
161
173
|
description:
|
|
162
174
|
'Custom render function for each selectable option in the dropdown. Not called for dividers, sections, or the select-all row.',
|
|
163
175
|
},
|
|
176
|
+
{
|
|
177
|
+
name: 'width',
|
|
178
|
+
type: 'SizeValue',
|
|
179
|
+
description:
|
|
180
|
+
'Width of the field (number = pixels, string used as-is, e.g. "100%"). Sizes the whole field (label, control, and status) so they stay aligned.',
|
|
181
|
+
},
|
|
164
182
|
{
|
|
165
183
|
name: 'xstyle',
|
|
166
184
|
type: 'StyleXStyles',
|
|
@@ -250,6 +268,7 @@ export const docsZh = {
|
|
|
250
268
|
isRequired: '将字段标记为必填。',
|
|
251
269
|
isLoading: '在触发器中显示加载旋转器。',
|
|
252
270
|
status: '带可选消息的验证状态。',
|
|
271
|
+
statusVariant: '状态消息的放置方式:attached 直接叠加在输入框下方;detached 作为独立元素浮于下方并留有间距。',
|
|
253
272
|
renderOption:
|
|
254
273
|
'每个可选选项的自定义渲染函数。不会用于分隔线、分组或全选行。',
|
|
255
274
|
xstyle: '布局自定义的 StyleX 样式,必须是 stylex.create() 值。',
|
|
@@ -375,6 +394,7 @@ export const docsDense = {
|
|
|
375
394
|
isRequired: 'marks required',
|
|
376
395
|
isLoading: 'spinner in trigger',
|
|
377
396
|
status: 'validation status w/ optional message',
|
|
397
|
+
statusVariant: 'How status message is placed: attached overlaps below input; detached floats below w/ spacing.',
|
|
378
398
|
renderOption:
|
|
379
399
|
'custom render fn per selectable option; not dividers/sections/select-all',
|
|
380
400
|
xstyle: 'StyleX layout styles; stylex.create() only',
|
|
@@ -19,7 +19,10 @@ import {
|
|
|
19
19
|
} from '@testing-library/react';
|
|
20
20
|
import userEvent from '@testing-library/user-event';
|
|
21
21
|
import {MultiSelector} from './MultiSelector';
|
|
22
|
+
import {Icon} from '../Icon';
|
|
22
23
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
24
|
+
import {defineTheme} from '../theme/defineTheme';
|
|
25
|
+
import {generateThemeCSSFlat} from '../theme/generateThemeRules';
|
|
23
26
|
|
|
24
27
|
// Module-level constants to satisfy @eslint-react/no-unstable-default-props.
|
|
25
28
|
const ANNOUNCE_OPTIONS = ['Apple', 'Banana', 'Orange'] as const;
|
|
@@ -507,6 +510,59 @@ describe('MultiSelector', () => {
|
|
|
507
510
|
expect(options[0]).toHaveTextContent('Select all');
|
|
508
511
|
});
|
|
509
512
|
|
|
513
|
+
it('select-all accessible name reflects none/partial/all selection', async () => {
|
|
514
|
+
const user = userEvent.setup();
|
|
515
|
+
const options = [
|
|
516
|
+
{value: 'apple', label: 'Apple'},
|
|
517
|
+
{value: 'banana', label: 'Banana'},
|
|
518
|
+
];
|
|
519
|
+
const {rerender} = render(
|
|
520
|
+
<MultiSelector
|
|
521
|
+
label="Fruit"
|
|
522
|
+
options={options}
|
|
523
|
+
value={[]}
|
|
524
|
+
onChange={() => {}}
|
|
525
|
+
hasSelectAll
|
|
526
|
+
/>,
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
await user.click(screen.getByRole('combobox'));
|
|
530
|
+
|
|
531
|
+
// None selected: plain name, not selected
|
|
532
|
+
let selectAll = screen.getAllByRole('option', h)[0];
|
|
533
|
+
expect(selectAll).not.toHaveAccessibleName(/partially selected/);
|
|
534
|
+
expect(selectAll).toHaveAttribute('aria-selected', 'false');
|
|
535
|
+
|
|
536
|
+
// Partial: aria-selected="mixed" is invalid on role="option", so the
|
|
537
|
+
// indeterminate state must be conveyed through the accessible name.
|
|
538
|
+
rerender(
|
|
539
|
+
<MultiSelector
|
|
540
|
+
label="Fruit"
|
|
541
|
+
options={options}
|
|
542
|
+
value={['apple']}
|
|
543
|
+
onChange={() => {}}
|
|
544
|
+
hasSelectAll
|
|
545
|
+
/>,
|
|
546
|
+
);
|
|
547
|
+
selectAll = screen.getAllByRole('option', h)[0];
|
|
548
|
+
expect(selectAll).toHaveAccessibleName('Select all, partially selected');
|
|
549
|
+
expect(selectAll).toHaveAttribute('aria-selected', 'false');
|
|
550
|
+
|
|
551
|
+
// All selected: plain name again, selected
|
|
552
|
+
rerender(
|
|
553
|
+
<MultiSelector
|
|
554
|
+
label="Fruit"
|
|
555
|
+
options={options}
|
|
556
|
+
value={['apple', 'banana']}
|
|
557
|
+
onChange={() => {}}
|
|
558
|
+
hasSelectAll
|
|
559
|
+
/>,
|
|
560
|
+
);
|
|
561
|
+
selectAll = screen.getAllByRole('option', h)[0];
|
|
562
|
+
expect(selectAll).not.toHaveAccessibleName(/partially selected/);
|
|
563
|
+
expect(selectAll).toHaveAttribute('aria-selected', 'true');
|
|
564
|
+
});
|
|
565
|
+
|
|
510
566
|
it('select-all toggles via keyboard Enter', async () => {
|
|
511
567
|
const user = userEvent.setup();
|
|
512
568
|
const onChange = vi.fn();
|
|
@@ -565,6 +621,72 @@ describe('MultiSelector', () => {
|
|
|
565
621
|
expect(options).toHaveLength(1);
|
|
566
622
|
});
|
|
567
623
|
|
|
624
|
+
describe('grouped search', () => {
|
|
625
|
+
const GROUPED = [
|
|
626
|
+
{
|
|
627
|
+
type: 'section' as const,
|
|
628
|
+
title: 'Citrus',
|
|
629
|
+
options: [
|
|
630
|
+
{value: 'orange', label: 'Orange'},
|
|
631
|
+
{value: 'lemon', label: 'Lemon'},
|
|
632
|
+
],
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
type: 'section' as const,
|
|
636
|
+
title: 'Berries',
|
|
637
|
+
options: [
|
|
638
|
+
{value: 'strawberry', label: 'Strawberry'},
|
|
639
|
+
{value: 'blueberry', label: 'Blueberry'},
|
|
640
|
+
],
|
|
641
|
+
},
|
|
642
|
+
];
|
|
643
|
+
|
|
644
|
+
it('keeps the group header above matching items while searching', async () => {
|
|
645
|
+
const user = userEvent.setup();
|
|
646
|
+
render(
|
|
647
|
+
<MultiSelector
|
|
648
|
+
label="Fruit"
|
|
649
|
+
options={GROUPED}
|
|
650
|
+
value={[]}
|
|
651
|
+
onChange={() => {}}
|
|
652
|
+
hasSearch
|
|
653
|
+
/>,
|
|
654
|
+
);
|
|
655
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
656
|
+
await user.type(screen.getByRole('combobox', h), 'orange');
|
|
657
|
+
|
|
658
|
+
expect(
|
|
659
|
+
screen.getByRole('group', {name: 'Citrus', ...h}),
|
|
660
|
+
).toBeInTheDocument();
|
|
661
|
+
const options = screen.getAllByRole('option', h);
|
|
662
|
+
expect(options).toHaveLength(1);
|
|
663
|
+
expect(options[0]).toHaveTextContent('Orange');
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('hides a group whose items have no match', async () => {
|
|
667
|
+
const user = userEvent.setup();
|
|
668
|
+
render(
|
|
669
|
+
<MultiSelector
|
|
670
|
+
label="Fruit"
|
|
671
|
+
options={GROUPED}
|
|
672
|
+
value={[]}
|
|
673
|
+
onChange={() => {}}
|
|
674
|
+
hasSearch
|
|
675
|
+
/>,
|
|
676
|
+
);
|
|
677
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
678
|
+
await user.type(screen.getByRole('combobox', h), 'berry');
|
|
679
|
+
|
|
680
|
+
expect(
|
|
681
|
+
screen.getByRole('group', {name: 'Berries', ...h}),
|
|
682
|
+
).toBeInTheDocument();
|
|
683
|
+
expect(
|
|
684
|
+
screen.queryByRole('group', {name: 'Citrus', ...h}),
|
|
685
|
+
).not.toBeInTheDocument();
|
|
686
|
+
expect(screen.getAllByRole('option', h)).toHaveLength(2);
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
|
|
568
690
|
it('PageDown/PageUp jump the highlight to the last/first filtered option', async () => {
|
|
569
691
|
const user = userEvent.setup();
|
|
570
692
|
render(
|
|
@@ -645,6 +767,29 @@ describe('MultiSelector', () => {
|
|
|
645
767
|
).toBeInTheDocument();
|
|
646
768
|
});
|
|
647
769
|
|
|
770
|
+
it('empty-state message is not exposed as a listbox child', async () => {
|
|
771
|
+
const user = userEvent.setup();
|
|
772
|
+
render(
|
|
773
|
+
<MultiSelector
|
|
774
|
+
label="Fruit"
|
|
775
|
+
options={defaultOptions}
|
|
776
|
+
value={[]}
|
|
777
|
+
onChange={() => {}}
|
|
778
|
+
hasSearch
|
|
779
|
+
/>,
|
|
780
|
+
);
|
|
781
|
+
|
|
782
|
+
await user.click(screen.getByRole('button', {name: 'Fruit'}));
|
|
783
|
+
await user.type(screen.getByRole('combobox', h), 'xyz');
|
|
784
|
+
|
|
785
|
+
// role="listbox" only permits option/group children — the visual
|
|
786
|
+
// empty-state message must be presentational (it is announced through
|
|
787
|
+
// the result-count live region instead).
|
|
788
|
+
const listbox = screen.getByRole('listbox', h);
|
|
789
|
+
const empty = within(listbox).getByText('No results found');
|
|
790
|
+
expect(empty).toHaveAttribute('role', 'presentation');
|
|
791
|
+
});
|
|
792
|
+
|
|
648
793
|
describe('result announcements', () => {
|
|
649
794
|
it('announces the match count politely while searching', async () => {
|
|
650
795
|
const user = userEvent.setup();
|
|
@@ -1245,3 +1390,260 @@ describe('MultiSelector', () => {
|
|
|
1245
1390
|
});
|
|
1246
1391
|
});
|
|
1247
1392
|
});
|
|
1393
|
+
|
|
1394
|
+
describe('MultiSelector statusVariant forwarding', () => {
|
|
1395
|
+
it('defaults to attached (status renders with data-variant="attached")', () => {
|
|
1396
|
+
const {container} = render(
|
|
1397
|
+
<MultiSelector
|
|
1398
|
+
label="Fruit"
|
|
1399
|
+
options={['Apple', 'Banana']}
|
|
1400
|
+
value={[]}
|
|
1401
|
+
onChange={() => {}}
|
|
1402
|
+
status={{type: 'error', message: 'Required'}}
|
|
1403
|
+
/>,
|
|
1404
|
+
);
|
|
1405
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1406
|
+
'data-variant',
|
|
1407
|
+
'attached',
|
|
1408
|
+
);
|
|
1409
|
+
});
|
|
1410
|
+
|
|
1411
|
+
it('forwards statusVariant="detached" to the underlying Field status', () => {
|
|
1412
|
+
const {container} = render(
|
|
1413
|
+
<MultiSelector
|
|
1414
|
+
label="Fruit"
|
|
1415
|
+
options={['Apple', 'Banana']}
|
|
1416
|
+
value={[]}
|
|
1417
|
+
onChange={() => {}}
|
|
1418
|
+
status={{type: 'error', message: 'Required'}}
|
|
1419
|
+
statusVariant="detached"
|
|
1420
|
+
/>,
|
|
1421
|
+
);
|
|
1422
|
+
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1423
|
+
'data-variant',
|
|
1424
|
+
'detached',
|
|
1425
|
+
);
|
|
1426
|
+
});
|
|
1427
|
+
});
|
|
1428
|
+
|
|
1429
|
+
describe('MultiSelector clear icon theme target', () => {
|
|
1430
|
+
const ICON_OPTIONS = ['Apple', 'Banana', 'Orange'];
|
|
1431
|
+
|
|
1432
|
+
// Resolve the clear glyph span (the astryx-icon element inside the clear
|
|
1433
|
+
// button), independent of the theme target class.
|
|
1434
|
+
const getClearIcon = (): HTMLElement => {
|
|
1435
|
+
const button = screen.getByRole('button', {name: 'Clear all Fruit'});
|
|
1436
|
+
const icon = button.querySelector('.astryx-icon');
|
|
1437
|
+
if (icon == null) {
|
|
1438
|
+
throw new Error('clear icon not found');
|
|
1439
|
+
}
|
|
1440
|
+
return icon as HTMLElement;
|
|
1441
|
+
};
|
|
1442
|
+
|
|
1443
|
+
it('renders the astryx-multi-selector-clear-icon target on the clear glyph', () => {
|
|
1444
|
+
render(
|
|
1445
|
+
<MultiSelector
|
|
1446
|
+
label="Fruit"
|
|
1447
|
+
options={ICON_OPTIONS}
|
|
1448
|
+
value={['Banana']}
|
|
1449
|
+
onChange={() => {}}
|
|
1450
|
+
hasClear
|
|
1451
|
+
/>,
|
|
1452
|
+
);
|
|
1453
|
+
// The stable theme target lands on the icon element itself (not the
|
|
1454
|
+
// button), so a theme can restyle just this glyph (color, size, hover)
|
|
1455
|
+
// via `defineTheme` — a button-level target could not reach the icon's
|
|
1456
|
+
// own color/size.
|
|
1457
|
+
const icon = getClearIcon();
|
|
1458
|
+
expect(icon).toHaveClass('astryx-multi-selector-clear-icon');
|
|
1459
|
+
expect(icon).toHaveClass('astryx-icon');
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1462
|
+
it('keeps the clear button functional alongside the target', () => {
|
|
1463
|
+
const onChange = vi.fn();
|
|
1464
|
+
render(
|
|
1465
|
+
<MultiSelector
|
|
1466
|
+
label="Fruit"
|
|
1467
|
+
options={ICON_OPTIONS}
|
|
1468
|
+
value={['Banana']}
|
|
1469
|
+
onChange={onChange}
|
|
1470
|
+
hasClear
|
|
1471
|
+
/>,
|
|
1472
|
+
);
|
|
1473
|
+
const clear = screen.getByRole('button', {name: 'Clear all Fruit'});
|
|
1474
|
+
expect(clear.tagName).toBe('BUTTON');
|
|
1475
|
+
fireEvent.click(clear);
|
|
1476
|
+
expect(onChange).toHaveBeenCalledWith([]);
|
|
1477
|
+
});
|
|
1478
|
+
|
|
1479
|
+
it('renders the default icon (secondary color, sm size) byte-identically', () => {
|
|
1480
|
+
// Pixel-identical default guard: the clear glyph must carry the exact same
|
|
1481
|
+
// StyleX color/size classes as a standalone secondary/sm icon. The added
|
|
1482
|
+
// target class is purely additive — it changes nothing until a theme
|
|
1483
|
+
// targets it.
|
|
1484
|
+
render(
|
|
1485
|
+
<MultiSelector
|
|
1486
|
+
label="Fruit"
|
|
1487
|
+
options={ICON_OPTIONS}
|
|
1488
|
+
value={['Banana']}
|
|
1489
|
+
onChange={() => {}}
|
|
1490
|
+
hasClear
|
|
1491
|
+
/>,
|
|
1492
|
+
);
|
|
1493
|
+
const icon = getClearIcon();
|
|
1494
|
+
|
|
1495
|
+
const {container: refContainer} = render(
|
|
1496
|
+
<Icon icon="close" size="sm" color="secondary" />,
|
|
1497
|
+
);
|
|
1498
|
+
const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
|
|
1499
|
+
|
|
1500
|
+
const styleClasses = (el: HTMLElement) =>
|
|
1501
|
+
el.className
|
|
1502
|
+
.split(' ')
|
|
1503
|
+
.filter(c => c !== 'astryx-multi-selector-clear-icon')
|
|
1504
|
+
.sort();
|
|
1505
|
+
|
|
1506
|
+
expect(styleClasses(icon)).toEqual(styleClasses(refIcon));
|
|
1507
|
+
});
|
|
1508
|
+
|
|
1509
|
+
it('exposes multi-selector-clear-icon so a theme reaches the icon color, size, and hover', () => {
|
|
1510
|
+
// jsdom cannot resolve the @layer cascade, so the DOM-class assertion above
|
|
1511
|
+
// (target lands on the icon element) plus this generation assertion (the
|
|
1512
|
+
// theme emits same-element icon rules in @layer astryx-theme) together
|
|
1513
|
+
// prove the seam: a same-element theme rule wins over the icon's own
|
|
1514
|
+
// base-layer color/size.
|
|
1515
|
+
const theme = defineTheme({
|
|
1516
|
+
name: 'multi-selector-clear-icon-test',
|
|
1517
|
+
components: {
|
|
1518
|
+
'multi-selector-clear-icon': {
|
|
1519
|
+
base: {
|
|
1520
|
+
width: '12px',
|
|
1521
|
+
height: '12px',
|
|
1522
|
+
fontSize: '12px',
|
|
1523
|
+
color: 'var(--color-icon-secondary)',
|
|
1524
|
+
':hover': {color: 'var(--color-icon-primary)'},
|
|
1525
|
+
},
|
|
1526
|
+
},
|
|
1527
|
+
},
|
|
1528
|
+
});
|
|
1529
|
+
const css = generateThemeCSSFlat(theme);
|
|
1530
|
+
expect(css).toContain('.astryx-multi-selector-clear-icon {');
|
|
1531
|
+
expect(css).toContain('width: 12px');
|
|
1532
|
+
expect(css).toContain('height: 12px');
|
|
1533
|
+
expect(css).toContain('.astryx-multi-selector-clear-icon:hover {');
|
|
1534
|
+
expect(css).toContain('color: var(--color-icon-primary)');
|
|
1535
|
+
});
|
|
1536
|
+
});
|
|
1537
|
+
|
|
1538
|
+
describe('MultiSelector indicator (chevron) icon theme target', () => {
|
|
1539
|
+
const ICON_OPTIONS = ['Apple', 'Banana', 'Orange'];
|
|
1540
|
+
|
|
1541
|
+
const getIndicatorIcon = (container: HTMLElement): HTMLElement => {
|
|
1542
|
+
// The chevron is the only glyph carrying the indicator target class.
|
|
1543
|
+
const icon = container.querySelector(
|
|
1544
|
+
'.astryx-multi-selector-indicator-icon',
|
|
1545
|
+
);
|
|
1546
|
+
if (icon == null) {
|
|
1547
|
+
throw new Error('indicator icon not found');
|
|
1548
|
+
}
|
|
1549
|
+
return icon as HTMLElement;
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
it('renders the astryx-multi-selector-indicator-icon target on the chevron glyph', () => {
|
|
1553
|
+
const {container} = render(
|
|
1554
|
+
<MultiSelector
|
|
1555
|
+
label="Fruit"
|
|
1556
|
+
options={ICON_OPTIONS}
|
|
1557
|
+
value={[]}
|
|
1558
|
+
onChange={() => {}}
|
|
1559
|
+
/>,
|
|
1560
|
+
);
|
|
1561
|
+
// The stable theme target lands on the icon element itself (not the trigger
|
|
1562
|
+
// button), so a theme can restyle just this glyph (color, size, hover) —
|
|
1563
|
+
// and each open/closed state — via `defineTheme`. A button-level target
|
|
1564
|
+
// could not reach the icon's own color/size.
|
|
1565
|
+
const icon = getIndicatorIcon(container);
|
|
1566
|
+
expect(icon).toHaveClass('astryx-multi-selector-indicator-icon');
|
|
1567
|
+
expect(icon).toHaveClass('astryx-icon');
|
|
1568
|
+
// Open/closed state is reflected so a theme can target each state alone.
|
|
1569
|
+
expect(icon).toHaveAttribute('data-state', 'collapsed');
|
|
1570
|
+
});
|
|
1571
|
+
|
|
1572
|
+
it('reflects the expanded state on the chevron when the popover is open', async () => {
|
|
1573
|
+
const user = userEvent.setup();
|
|
1574
|
+
const {container} = render(
|
|
1575
|
+
<MultiSelector
|
|
1576
|
+
label="Fruit"
|
|
1577
|
+
options={ICON_OPTIONS}
|
|
1578
|
+
value={[]}
|
|
1579
|
+
onChange={() => {}}
|
|
1580
|
+
/>,
|
|
1581
|
+
);
|
|
1582
|
+
await user.click(screen.getByRole('combobox'));
|
|
1583
|
+
await waitFor(() => {
|
|
1584
|
+
expect(getIndicatorIcon(container)).toHaveAttribute(
|
|
1585
|
+
'data-state',
|
|
1586
|
+
'expanded',
|
|
1587
|
+
);
|
|
1588
|
+
});
|
|
1589
|
+
});
|
|
1590
|
+
|
|
1591
|
+
it('renders the default icon (inherit color, sm size) byte-identically', () => {
|
|
1592
|
+
// Pixel-identical default guard: the chevron glyph must carry the exact
|
|
1593
|
+
// same StyleX color/size classes as a standalone inherit/sm icon. The added
|
|
1594
|
+
// target class + data-state are purely additive — they change nothing until
|
|
1595
|
+
// a theme targets them.
|
|
1596
|
+
const {container} = render(
|
|
1597
|
+
<MultiSelector
|
|
1598
|
+
label="Fruit"
|
|
1599
|
+
options={ICON_OPTIONS}
|
|
1600
|
+
value={[]}
|
|
1601
|
+
onChange={() => {}}
|
|
1602
|
+
/>,
|
|
1603
|
+
);
|
|
1604
|
+
const icon = getIndicatorIcon(container);
|
|
1605
|
+
|
|
1606
|
+
const {container: refContainer} = render(
|
|
1607
|
+
<Icon icon="chevronDown" size="sm" color="inherit" />,
|
|
1608
|
+
);
|
|
1609
|
+
const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
|
|
1610
|
+
|
|
1611
|
+
// Exclude the additive theme-target classes (the stable target + its
|
|
1612
|
+
// reflected state class) so only the StyleX color/size classes remain.
|
|
1613
|
+
const themeTargetClasses = new Set([
|
|
1614
|
+
'astryx-multi-selector-indicator-icon',
|
|
1615
|
+
'collapsed',
|
|
1616
|
+
'expanded',
|
|
1617
|
+
]);
|
|
1618
|
+
const styleClasses = (el: HTMLElement) =>
|
|
1619
|
+
el.className
|
|
1620
|
+
.split(' ')
|
|
1621
|
+
.filter(c => !themeTargetClasses.has(c))
|
|
1622
|
+
.sort();
|
|
1623
|
+
|
|
1624
|
+
expect(styleClasses(icon)).toEqual(styleClasses(refIcon));
|
|
1625
|
+
});
|
|
1626
|
+
|
|
1627
|
+
it('exposes multi-selector-indicator-icon so a theme reaches the icon size and per-state color', () => {
|
|
1628
|
+
// jsdom cannot resolve the @layer cascade, so the DOM-class assertions
|
|
1629
|
+
// above (target lands on the icon element) plus this generation assertion
|
|
1630
|
+
// (the theme emits same-element icon rules in @layer astryx-theme) together
|
|
1631
|
+
// prove the seam: a same-element theme rule wins over the icon's own
|
|
1632
|
+
// base-layer color/size.
|
|
1633
|
+
const theme = defineTheme({
|
|
1634
|
+
name: 'multi-selector-indicator-icon-test',
|
|
1635
|
+
components: {
|
|
1636
|
+
'multi-selector-indicator-icon': {
|
|
1637
|
+
base: {width: '14px', height: '14px', fontSize: '14px'},
|
|
1638
|
+
'state:expanded': {color: 'var(--color-icon-primary)'},
|
|
1639
|
+
},
|
|
1640
|
+
},
|
|
1641
|
+
});
|
|
1642
|
+
const css = generateThemeCSSFlat(theme);
|
|
1643
|
+
expect(css).toContain('.astryx-multi-selector-indicator-icon {');
|
|
1644
|
+
expect(css).toContain('width: 14px');
|
|
1645
|
+
expect(css).toContain('height: 14px');
|
|
1646
|
+
expect(css).toContain('.astryx-multi-selector-indicator-icon.expanded');
|
|
1647
|
+
expect(css).toContain('color: var(--color-icon-primary)');
|
|
1648
|
+
});
|
|
1649
|
+
});
|