@astryxdesign/core 0.1.9 → 0.2.0-canary.136a00f
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 +39 -3
- 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/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 +70 -30
- 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 +158 -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.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.test.tsx +72 -0
- package/src/FieldStatus/FieldStatus.tsx +48 -2
- 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/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 +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -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
package/src/Divider/Divider.tsx
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - /packages/cli/templates/blocks/components/Divider/ (showcase blocks)
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import type
|
|
18
|
+
import {useId, type ReactNode} from 'react';
|
|
19
19
|
import type {BaseProps} from '../BaseProps';
|
|
20
20
|
import * as stylex from '@stylexjs/stylex';
|
|
21
21
|
|
|
@@ -165,9 +165,19 @@ export function Divider({
|
|
|
165
165
|
className,
|
|
166
166
|
style,
|
|
167
167
|
ref,
|
|
168
|
+
'aria-label': ariaLabel,
|
|
169
|
+
'aria-labelledby': ariaLabelledBy,
|
|
168
170
|
...props
|
|
169
171
|
}: DividerProps) {
|
|
170
172
|
const isHorizontal = orientation === 'horizontal';
|
|
173
|
+
const labelId = useId();
|
|
174
|
+
|
|
175
|
+
// A separator does not derive its accessible name from its content, so the
|
|
176
|
+
// rendered label must be referenced explicitly via aria-labelledby to be
|
|
177
|
+
// exposed as the separator's name (WCAG 1.3.1). An explicit aria-label or
|
|
178
|
+
// aria-labelledby from the consumer takes precedence.
|
|
179
|
+
const resolvedLabelledBy =
|
|
180
|
+
ariaLabelledBy ?? (label && ariaLabel == null ? labelId : undefined);
|
|
171
181
|
|
|
172
182
|
return (
|
|
173
183
|
<div
|
|
@@ -175,6 +185,8 @@ export function Divider({
|
|
|
175
185
|
{...props}
|
|
176
186
|
role="separator"
|
|
177
187
|
aria-orientation={orientation}
|
|
188
|
+
aria-label={ariaLabel}
|
|
189
|
+
aria-labelledby={resolvedLabelledBy}
|
|
178
190
|
{...mergeProps(
|
|
179
191
|
themeProps('divider', {variant, orientation}),
|
|
180
192
|
stylex.props(
|
|
@@ -196,6 +208,7 @@ export function Divider({
|
|
|
196
208
|
/>
|
|
197
209
|
{label && (
|
|
198
210
|
<div
|
|
211
|
+
id={labelId}
|
|
199
212
|
{...stylex.props(
|
|
200
213
|
labelStyles.label,
|
|
201
214
|
!isHorizontal && labelStyles.verticalLabel,
|
|
@@ -781,4 +781,64 @@ describe('DropdownMenu keyboard access for menuitemradio/menuitemcheckbox (#3829
|
|
|
781
781
|
screen.getByRole('menuitemradio', {name: 'Oldest', hidden: true}),
|
|
782
782
|
).toHaveFocus();
|
|
783
783
|
});
|
|
784
|
+
|
|
785
|
+
it('moves focus to the item the mouse hovers, keeping a single highlight', async () => {
|
|
786
|
+
const user = userEvent.setup();
|
|
787
|
+
render(
|
|
788
|
+
<DropdownMenu button={{label: 'Actions'}}>
|
|
789
|
+
<DropdownMenuItem label="Edit" onClick={() => {}} />
|
|
790
|
+
<DropdownMenuItem label="Duplicate" onClick={() => {}} />
|
|
791
|
+
<DropdownMenuItem label="Delete" onClick={() => {}} />
|
|
792
|
+
</DropdownMenu>,
|
|
793
|
+
);
|
|
794
|
+
|
|
795
|
+
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
796
|
+
// Keyboard focus starts on the first item.
|
|
797
|
+
const edit = screen.getByRole('menuitem', {name: 'Edit', hidden: true});
|
|
798
|
+
const del = screen.getByRole('menuitem', {name: 'Delete', hidden: true});
|
|
799
|
+
edit.focus();
|
|
800
|
+
expect(edit).toHaveFocus();
|
|
801
|
+
|
|
802
|
+
// A mouse hover over another item moves focus to it, so the single
|
|
803
|
+
// focus-driven highlight follows the pointer instead of leaving two.
|
|
804
|
+
fireEvent.pointerMove(del, {pointerType: 'mouse'});
|
|
805
|
+
expect(del).toHaveFocus();
|
|
806
|
+
expect(edit).not.toHaveFocus();
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
it('does not move focus on hover for a disabled item', async () => {
|
|
810
|
+
const user = userEvent.setup();
|
|
811
|
+
render(
|
|
812
|
+
<DropdownMenu button={{label: 'Actions'}}>
|
|
813
|
+
<DropdownMenuItem label="Edit" onClick={() => {}} />
|
|
814
|
+
<DropdownMenuItem label="Delete" isDisabled onClick={() => {}} />
|
|
815
|
+
</DropdownMenu>,
|
|
816
|
+
);
|
|
817
|
+
|
|
818
|
+
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
819
|
+
const edit = screen.getByRole('menuitem', {name: 'Edit', hidden: true});
|
|
820
|
+
const del = screen.getByRole('menuitem', {name: 'Delete', hidden: true});
|
|
821
|
+
edit.focus();
|
|
822
|
+
|
|
823
|
+
fireEvent.pointerMove(del, {pointerType: 'mouse'});
|
|
824
|
+
expect(edit).toHaveFocus();
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
it('does not move focus for a non-mouse (touch) pointer', async () => {
|
|
828
|
+
const user = userEvent.setup();
|
|
829
|
+
render(
|
|
830
|
+
<DropdownMenu button={{label: 'Actions'}}>
|
|
831
|
+
<DropdownMenuItem label="Edit" onClick={() => {}} />
|
|
832
|
+
<DropdownMenuItem label="Delete" onClick={() => {}} />
|
|
833
|
+
</DropdownMenu>,
|
|
834
|
+
);
|
|
835
|
+
|
|
836
|
+
await user.click(screen.getByRole('button', {name: /Actions/}));
|
|
837
|
+
const edit = screen.getByRole('menuitem', {name: 'Edit', hidden: true});
|
|
838
|
+
const del = screen.getByRole('menuitem', {name: 'Delete', hidden: true});
|
|
839
|
+
edit.focus();
|
|
840
|
+
|
|
841
|
+
fireEvent.pointerMove(del, {pointerType: 'touch'});
|
|
842
|
+
expect(edit).toHaveFocus();
|
|
843
|
+
});
|
|
784
844
|
});
|
|
@@ -38,7 +38,11 @@ import {Icon} from '../Icon';
|
|
|
38
38
|
import type {IconType} from '../Icon';
|
|
39
39
|
|
|
40
40
|
import {renderDropdownItems} from './renderDropdownItems';
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
MENU_ITEM_ROLES,
|
|
43
|
+
MENU_ITEM_SELECTOR,
|
|
44
|
+
MENU_BOUNDARY_SELECTOR,
|
|
45
|
+
} from './menuItemRoles';
|
|
42
46
|
import {
|
|
43
47
|
DropdownMenuContext,
|
|
44
48
|
type DropdownMenuContextValue,
|
|
@@ -100,6 +104,12 @@ export interface DropdownMenuItemData {
|
|
|
100
104
|
onClick?: () => void;
|
|
101
105
|
isDisabled?: boolean;
|
|
102
106
|
icon?: ReactNode | IconType;
|
|
107
|
+
/**
|
|
108
|
+
* Nested submenu entries. When present, this row becomes a submenu (a
|
|
109
|
+
* flyout revealing `items`) instead of a leaf action — no separate item
|
|
110
|
+
* "type" is needed. Data-mode parity for the compound DropdownMenuSubMenu API.
|
|
111
|
+
*/
|
|
112
|
+
items?: DropdownMenuOption[];
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
export interface DropdownMenuDivider {
|
|
@@ -200,6 +210,14 @@ export function DropdownMenu({
|
|
|
200
210
|
const items = ('items' in props ? props.items : undefined) ?? [];
|
|
201
211
|
const children = props.children;
|
|
202
212
|
|
|
213
|
+
// Extract BaseProps pass-throughs (aria-*, id, event handlers) from the
|
|
214
|
+
// discriminated-union rest bag so they can be forwarded to the menu element.
|
|
215
|
+
const {
|
|
216
|
+
items: _items,
|
|
217
|
+
children: _children,
|
|
218
|
+
...rest
|
|
219
|
+
} = props as Record<string, unknown>;
|
|
220
|
+
|
|
203
221
|
const menuId = useId();
|
|
204
222
|
const menuSize = button.size ?? 'md';
|
|
205
223
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
@@ -265,23 +283,18 @@ export function DropdownMenu({
|
|
|
265
283
|
handleKeyDown: listNavKeyDown,
|
|
266
284
|
focusFirst,
|
|
267
285
|
focusItem,
|
|
286
|
+
ownsEvent,
|
|
287
|
+
getItems: getMenuItems,
|
|
268
288
|
} = useListFocus<HTMLDivElement>({
|
|
269
289
|
itemSelector: MENU_ITEM_SELECTOR,
|
|
290
|
+
boundarySelector: MENU_BOUNDARY_SELECTOR,
|
|
270
291
|
wrap: false,
|
|
271
292
|
onEscape: closeMenu,
|
|
272
293
|
});
|
|
273
294
|
|
|
274
295
|
// First-character typeahead over the (enabled) menu items — jump to the next
|
|
275
|
-
// item whose label starts with the typed text (menus-11).
|
|
276
|
-
|
|
277
|
-
(): HTMLElement[] =>
|
|
278
|
-
listRef.current
|
|
279
|
-
? Array.from(
|
|
280
|
-
listRef.current.querySelectorAll<HTMLElement>(MENU_ITEM_SELECTOR),
|
|
281
|
-
)
|
|
282
|
-
: [],
|
|
283
|
-
[listRef],
|
|
284
|
-
);
|
|
296
|
+
// item whose label starts with the typed text (menus-11). Reuses the hook's
|
|
297
|
+
// scoped item collection so an inline submenu flyout's items aren't swept in.
|
|
285
298
|
const typeahead = useTypeahead({
|
|
286
299
|
getItemLabels: () => getMenuItems().map(el => el.textContent),
|
|
287
300
|
onMatch: focusItem,
|
|
@@ -307,6 +320,11 @@ export function DropdownMenu({
|
|
|
307
320
|
// Extend useListFocus with Enter/Space activation + typeahead
|
|
308
321
|
const listKeyDown = useCallback(
|
|
309
322
|
(e: React.KeyboardEvent) => {
|
|
323
|
+
// A submenu flyout renders inline inside this menu; its key events bubble
|
|
324
|
+
// up here. Let that level own them — only handle events from this level.
|
|
325
|
+
if (!ownsEvent(e)) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
310
328
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
311
329
|
e.preventDefault();
|
|
312
330
|
const focused = document.activeElement as HTMLElement | null;
|
|
@@ -334,7 +352,7 @@ export function DropdownMenu({
|
|
|
334
352
|
}
|
|
335
353
|
listNavKeyDown(e);
|
|
336
354
|
},
|
|
337
|
-
[listNavKeyDown, closeMenu, typeahead],
|
|
355
|
+
[listNavKeyDown, closeMenu, typeahead, ownsEvent],
|
|
338
356
|
);
|
|
339
357
|
|
|
340
358
|
const openAndFocus = useCallback(() => {
|
|
@@ -435,6 +453,7 @@ export function DropdownMenu({
|
|
|
435
453
|
|
|
436
454
|
{popover.render(
|
|
437
455
|
<div
|
|
456
|
+
{...rest}
|
|
438
457
|
ref={listRef}
|
|
439
458
|
id={menuId}
|
|
440
459
|
role="menu"
|
|
@@ -23,11 +23,12 @@
|
|
|
23
23
|
* checkmark uses the `check` icon from the active theme's icon registry.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {useCallback, type ReactNode} from 'react';
|
|
26
|
+
import {useCallback, type PointerEvent, type ReactNode} from 'react';
|
|
27
27
|
import * as stylex from '@stylexjs/stylex';
|
|
28
28
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
29
29
|
import {Item} from '../Item';
|
|
30
30
|
import {useDropdownMenuContext} from './DropdownMenuContext';
|
|
31
|
+
import {focusMenuItemOnHover} from './menuItemHover';
|
|
31
32
|
import {
|
|
32
33
|
colorVars,
|
|
33
34
|
spacingVars,
|
|
@@ -47,7 +48,6 @@ const styles = stylex.create({
|
|
|
47
48
|
backgroundColor: {
|
|
48
49
|
default: 'transparent',
|
|
49
50
|
':focus': colorVars['--color-overlay-hover'],
|
|
50
|
-
':hover': colorVars['--color-overlay-hover'],
|
|
51
51
|
},
|
|
52
52
|
cursor: 'pointer',
|
|
53
53
|
outline: 'none',
|
|
@@ -190,12 +190,18 @@ export function DropdownMenuCheckboxItem({
|
|
|
190
190
|
}
|
|
191
191
|
}, [isDisabled, onChange, value, hasCloseOnSelect, ctx]);
|
|
192
192
|
|
|
193
|
+
const handlePointerMove = useCallback(
|
|
194
|
+
(e: PointerEvent<HTMLElement>) => focusMenuItemOnHover(e, isDisabled),
|
|
195
|
+
[isDisabled],
|
|
196
|
+
);
|
|
197
|
+
|
|
193
198
|
return (
|
|
194
199
|
<Item
|
|
195
200
|
{...rest}
|
|
196
201
|
role="menuitemcheckbox"
|
|
197
202
|
aria-checked={value}
|
|
198
203
|
tabIndex={isDisabled ? undefined : -1}
|
|
204
|
+
onPointerMove={handlePointerMove}
|
|
199
205
|
marker={
|
|
200
206
|
<span
|
|
201
207
|
aria-hidden="true"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* - /packages/cli/templates/blocks/components/DropdownMenu/ (showcase blocks)
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {useCallback, type ReactNode} from 'react';
|
|
26
|
+
import {useCallback, type PointerEvent, type ReactNode} from 'react';
|
|
27
27
|
import * as stylex from '@stylexjs/stylex';
|
|
28
28
|
import {renderIconSlot, type IconType} from '../Icon';
|
|
29
29
|
import {Item} from '../Item';
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
import {mergeProps} from '../utils';
|
|
37
37
|
import type {BaseProps} from '../BaseProps';
|
|
38
38
|
import {useDropdownMenuContext} from './DropdownMenuContext';
|
|
39
|
+
import {focusMenuItemOnHover} from './menuItemHover';
|
|
39
40
|
import {themeProps} from '../utils/themeProps';
|
|
40
41
|
|
|
41
42
|
const menuItemStyles = stylex.create({
|
|
@@ -51,11 +52,10 @@ const menuItemStyles = stylex.create({
|
|
|
51
52
|
backgroundColor: {
|
|
52
53
|
default: 'transparent',
|
|
53
54
|
':focus': colorVars['--color-overlay-hover'],
|
|
54
|
-
':hover': colorVars['--color-overlay-hover'],
|
|
55
55
|
},
|
|
56
56
|
border: 'none',
|
|
57
57
|
cursor: 'pointer',
|
|
58
|
-
textAlign: '
|
|
58
|
+
textAlign: 'start',
|
|
59
59
|
outline: 'none',
|
|
60
60
|
},
|
|
61
61
|
disabled: {
|
|
@@ -129,10 +129,16 @@ export function DropdownMenuItem({
|
|
|
129
129
|
ctx?.closeMenu();
|
|
130
130
|
}, [isDisabled, onClick, ctx]);
|
|
131
131
|
|
|
132
|
+
const handlePointerMove = useCallback(
|
|
133
|
+
(e: PointerEvent<HTMLElement>) => focusMenuItemOnHover(e, isDisabled),
|
|
134
|
+
[isDisabled],
|
|
135
|
+
);
|
|
136
|
+
|
|
132
137
|
return (
|
|
133
138
|
<Item
|
|
134
139
|
role="menuitem"
|
|
135
140
|
tabIndex={isDisabled ? undefined : -1}
|
|
141
|
+
onPointerMove={handlePointerMove}
|
|
136
142
|
startContent={
|
|
137
143
|
icon
|
|
138
144
|
? renderIconSlot(icon, {size: 'sm', color: 'secondary'})
|
|
@@ -22,16 +22,10 @@ export const docs = {
|
|
|
22
22
|
description: 'Callback fired when the selected value changes.',
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
name: '
|
|
25
|
+
name: 'label',
|
|
26
26
|
type: 'string',
|
|
27
27
|
description:
|
|
28
|
-
'Accessible
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'aria-labelledby',
|
|
32
|
-
type: 'string',
|
|
33
|
-
description:
|
|
34
|
-
'The id of an element that labels the group, as an alternative to aria-label.',
|
|
28
|
+
'Accessible name for the group, applied as aria-label so screen readers announce the radios as a named set, e.g. "Sort by". Required. Pass aria-labelledby (via base props) instead when the name already exists as a visible element.',
|
|
35
29
|
},
|
|
36
30
|
{
|
|
37
31
|
name: 'hasCloseOnSelect',
|
|
@@ -57,8 +51,7 @@ export const docsZh = {
|
|
|
57
51
|
propDescriptions: {
|
|
58
52
|
value: '组中当前选中的值。尚无选中项时传 undefined。',
|
|
59
53
|
onChange: '所选值变化时触发的回调。',
|
|
60
|
-
'aria-label
|
|
61
|
-
'aria-labelledby': '标记该组的元素 id,作为 aria-label 的替代。',
|
|
54
|
+
label: '组的无障碍名称,作为 aria-label 应用,以便屏幕阅读器将单选项作为命名集合朗读,例如“Sort by”。必需。当名称已作为可见元素存在时,可改用 aria-labelledby(通过基础属性)。',
|
|
62
55
|
hasCloseOnSelect: '选择某值是否关闭菜单。默认关闭。',
|
|
63
56
|
children: '组成该组的 DropdownMenuRadioItem。',
|
|
64
57
|
},
|
|
@@ -72,8 +65,7 @@ export const docsDense = {
|
|
|
72
65
|
propDescriptions: {
|
|
73
66
|
value: 'selected value (undefined = none)',
|
|
74
67
|
onChange: 'fired when selected value changes',
|
|
75
|
-
|
|
76
|
-
'aria-labelledby': 'id of labelling element (alt to aria-label)',
|
|
68
|
+
label: 'accessible group name (applied as aria-label); required',
|
|
77
69
|
hasCloseOnSelect: 'close menu on select (default true)',
|
|
78
70
|
children: 'the DropdownMenuRadioItems',
|
|
79
71
|
},
|
|
@@ -49,16 +49,13 @@ export interface DropdownMenuRadioGroupProps extends Omit<
|
|
|
49
49
|
*/
|
|
50
50
|
onChange: (value: string) => void;
|
|
51
51
|
/**
|
|
52
|
-
* Accessible
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* Accessible name for the group, announced by screen readers so the radios
|
|
53
|
+
* read as a named set (e.g. "Sort by"). Applied as the group's `aria-label`.
|
|
54
|
+
* Required -- an unnamed radio group is an accessibility defect. Pass
|
|
55
|
+
* `aria-labelledby` (via base props) instead if the name already exists as a
|
|
56
|
+
* visible element on the page.
|
|
55
57
|
*/
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The id of an element that labels the group, as an alternative to
|
|
59
|
-
* `aria-label`.
|
|
60
|
-
*/
|
|
61
|
-
'aria-labelledby'?: string;
|
|
58
|
+
label: string;
|
|
62
59
|
/**
|
|
63
60
|
* Whether selecting a value closes the menu. Radio items default to closing
|
|
64
61
|
* on selection (a single-choice commit), unlike checkbox items which stay
|
|
@@ -82,7 +79,7 @@ export interface DropdownMenuRadioGroupProps extends Omit<
|
|
|
82
79
|
* DropdownMenuRadioItem,
|
|
83
80
|
* } from '@astryxdesign/core/DropdownMenu';
|
|
84
81
|
* <DropdownMenu button={{label: 'Sort'}}>
|
|
85
|
-
* <DropdownMenuRadioGroup value={sort} onChange={setSort}
|
|
82
|
+
* <DropdownMenuRadioGroup value={sort} onChange={setSort} label="Sort by">
|
|
86
83
|
* <DropdownMenuRadioItem value="newest" label="Newest" />
|
|
87
84
|
* <DropdownMenuRadioItem value="oldest" label="Oldest" />
|
|
88
85
|
* </DropdownMenuRadioGroup>
|
|
@@ -92,6 +89,7 @@ export interface DropdownMenuRadioGroupProps extends Omit<
|
|
|
92
89
|
export function DropdownMenuRadioGroup({
|
|
93
90
|
value,
|
|
94
91
|
onChange,
|
|
92
|
+
label,
|
|
95
93
|
hasCloseOnSelect = true,
|
|
96
94
|
children,
|
|
97
95
|
className,
|
|
@@ -107,6 +105,7 @@ export function DropdownMenuRadioGroup({
|
|
|
107
105
|
<div
|
|
108
106
|
{...rest}
|
|
109
107
|
role="group"
|
|
108
|
+
aria-label={label}
|
|
110
109
|
{...mergeProps(stylex.props(styles.group), {className, style})}>
|
|
111
110
|
<DropdownMenuRadioGroupContext value={contextValue}>
|
|
112
111
|
{children}
|
|
@@ -21,11 +21,12 @@
|
|
|
21
21
|
* has no registry glyph).
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import {useCallback, type ReactNode} from 'react';
|
|
24
|
+
import {useCallback, type PointerEvent, type ReactNode} from 'react';
|
|
25
25
|
import * as stylex from '@stylexjs/stylex';
|
|
26
26
|
import {renderIconSlot, type IconType} from '../Icon';
|
|
27
27
|
import {Item} from '../Item';
|
|
28
28
|
import {useDropdownMenuContext} from './DropdownMenuContext';
|
|
29
|
+
import {focusMenuItemOnHover} from './menuItemHover';
|
|
29
30
|
import {
|
|
30
31
|
colorVars,
|
|
31
32
|
spacingVars,
|
|
@@ -45,7 +46,6 @@ const styles = stylex.create({
|
|
|
45
46
|
backgroundColor: {
|
|
46
47
|
default: 'transparent',
|
|
47
48
|
':focus': colorVars['--color-overlay-hover'],
|
|
48
|
-
':hover': colorVars['--color-overlay-hover'],
|
|
49
49
|
},
|
|
50
50
|
cursor: 'pointer',
|
|
51
51
|
outline: 'none',
|
|
@@ -145,7 +145,7 @@ export interface DropdownMenuRadioItemProps extends Omit<
|
|
|
145
145
|
*
|
|
146
146
|
* @example
|
|
147
147
|
* ```
|
|
148
|
-
* <DropdownMenuRadioGroup value={sort} onChange={setSort}
|
|
148
|
+
* <DropdownMenuRadioGroup value={sort} onChange={setSort} label="Sort by">
|
|
149
149
|
* <DropdownMenuRadioItem value="newest" label="Newest" />
|
|
150
150
|
* <DropdownMenuRadioItem value="oldest" label="Oldest" icon="clock" />
|
|
151
151
|
* </DropdownMenuRadioGroup>
|
|
@@ -184,12 +184,18 @@ export function DropdownMenuRadioItem({
|
|
|
184
184
|
}
|
|
185
185
|
}, [isDisabled, groupCtx, value, menuCtx]);
|
|
186
186
|
|
|
187
|
+
const handlePointerMove = useCallback(
|
|
188
|
+
(e: PointerEvent<HTMLElement>) => focusMenuItemOnHover(e, isDisabled),
|
|
189
|
+
[isDisabled],
|
|
190
|
+
);
|
|
191
|
+
|
|
187
192
|
return (
|
|
188
193
|
<Item
|
|
189
194
|
{...rest}
|
|
190
195
|
role="menuitemradio"
|
|
191
196
|
aria-checked={isChecked}
|
|
192
197
|
tabIndex={isDisabled ? undefined : -1}
|
|
198
|
+
onPointerMove={handlePointerMove}
|
|
193
199
|
marker={
|
|
194
200
|
<span
|
|
195
201
|
aria-hidden="true"
|
|
@@ -110,7 +110,7 @@ describe('DropdownMenuRadioGroup / RadioItem', () => {
|
|
|
110
110
|
<DropdownMenuRadioGroup
|
|
111
111
|
value="newest"
|
|
112
112
|
onChange={() => {}}
|
|
113
|
-
|
|
113
|
+
label="Sort by">
|
|
114
114
|
<DropdownMenuRadioItem value="newest" label="Newest" />
|
|
115
115
|
<DropdownMenuRadioItem value="oldest" label="Oldest" />
|
|
116
116
|
</DropdownMenuRadioGroup>
|
|
@@ -136,7 +136,7 @@ describe('DropdownMenuRadioGroup / RadioItem', () => {
|
|
|
136
136
|
<DropdownMenuRadioGroup
|
|
137
137
|
value="newest"
|
|
138
138
|
onChange={onChange}
|
|
139
|
-
|
|
139
|
+
label="Sort by">
|
|
140
140
|
<DropdownMenuRadioItem value="newest" label="Newest" />
|
|
141
141
|
<DropdownMenuRadioItem value="oldest" label="Oldest" />
|
|
142
142
|
</DropdownMenuRadioGroup>
|
|
@@ -149,6 +149,24 @@ describe('DropdownMenuRadioGroup / RadioItem', () => {
|
|
|
149
149
|
expect(onChange).toHaveBeenCalledWith('oldest');
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
+
it('names the group from the required label prop', async () => {
|
|
153
|
+
const user = userEvent.setup();
|
|
154
|
+
render(
|
|
155
|
+
<DropdownMenu button={{label: 'Sort'}}>
|
|
156
|
+
<DropdownMenuRadioGroup
|
|
157
|
+
value="newest"
|
|
158
|
+
onChange={() => {}}
|
|
159
|
+
label="Sort by">
|
|
160
|
+
<DropdownMenuRadioItem value="newest" label="Newest" />
|
|
161
|
+
</DropdownMenuRadioGroup>
|
|
162
|
+
</DropdownMenu>,
|
|
163
|
+
);
|
|
164
|
+
await user.click(screen.getByRole('button', {name: /Sort/}));
|
|
165
|
+
expect(
|
|
166
|
+
screen.getByRole('group', {name: 'Sort by', hidden: true}),
|
|
167
|
+
).toBeInTheDocument();
|
|
168
|
+
});
|
|
169
|
+
|
|
152
170
|
it('throws when a radio item is used outside a group', () => {
|
|
153
171
|
const spy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
154
172
|
expect(() =>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('../docs-types').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'DropdownMenuSubMenu',
|
|
7
|
+
subComponentOf: 'DropdownMenu',
|
|
8
|
+
displayName: 'Dropdown Menu Submenu',
|
|
9
|
+
isHiddenFromOverview: true,
|
|
10
|
+
description:
|
|
11
|
+
'A single menu row that reveals a nested flyout of its own items. The row adopts DropdownMenuItem semantics (label / icon / description / isDisabled); its children become the flyout content. Opens inline-end with viewport auto-flip; Right/Enter/Space opens and focuses the first item, Left/Escape closes and returns focus to the trigger (Right/Left swap in RTL). For data-driven menus, give a menu item a nested `items` array instead of using this component directly.',
|
|
12
|
+
playground: {
|
|
13
|
+
defaults: {label: 'Move to'},
|
|
14
|
+
},
|
|
15
|
+
props: [
|
|
16
|
+
{
|
|
17
|
+
name: 'label',
|
|
18
|
+
type: 'ReactNode',
|
|
19
|
+
description: 'Primary label text for the trigger row.',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'icon',
|
|
23
|
+
type: 'IconType',
|
|
24
|
+
description:
|
|
25
|
+
'Icon to display before the label. See `astryx docs icons` for valid semantic names.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'description',
|
|
29
|
+
type: 'ReactNode',
|
|
30
|
+
description: 'Secondary description text displayed below the label.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'children',
|
|
34
|
+
type: 'ReactNode',
|
|
35
|
+
description:
|
|
36
|
+
'The flyout menu items: the same components used at the top level (DropdownMenuItem, nested DropdownMenuSubMenu, selectable items).',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'isDisabled',
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
default: 'false',
|
|
42
|
+
description:
|
|
43
|
+
'A disabled submenu renders its trigger row but never opens the flyout.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'hasSpinner',
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
default: 'false',
|
|
49
|
+
description:
|
|
50
|
+
'Show a spinner in place of the caret, e.g. while a lazy submenu\'s children are loading.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'menuWidth',
|
|
54
|
+
type: 'number | string',
|
|
55
|
+
description: 'Fixed flyout width. Defaults to sizing to its content (min 160px).',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'onOpenChange',
|
|
59
|
+
type: '(isOpen: boolean) => void',
|
|
60
|
+
description: 'Called when the flyout opens or closes.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'xstyle',
|
|
64
|
+
type: 'StyleXStyles',
|
|
65
|
+
description:
|
|
66
|
+
'StyleX styles for the trigger row. Must be a stylex.create() value: not an inline style object like style={{}}.',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const docsDense = {
|
|
72
|
+
name: 'DropdownMenuSubMenu',
|
|
73
|
+
isHiddenFromOverview: true,
|
|
74
|
+
displayName: 'Dropdown Menu Submenu',
|
|
75
|
+
description:
|
|
76
|
+
'menu row that reveals a nested flyout of its own children/items (single component, not Sub/SubTrigger/SubContent)',
|
|
77
|
+
propDescriptions: {
|
|
78
|
+
label: 'primary label text for the trigger row',
|
|
79
|
+
icon: 'icon before label',
|
|
80
|
+
description: 'secondary text below label',
|
|
81
|
+
children: 'flyout menu items (same components as top level)',
|
|
82
|
+
isDisabled: 'renders trigger but never opens',
|
|
83
|
+
hasSpinner: 'spinner instead of caret for async children',
|
|
84
|
+
menuWidth: 'fixed flyout width (default: content, min 160px)',
|
|
85
|
+
onOpenChange: 'called when flyout opens/closes',
|
|
86
|
+
xstyle: 'StyleX styles for the trigger row',
|
|
87
|
+
},
|
|
88
|
+
};
|