@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2
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 +105 -0
- package/README.md +131 -13
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Banner/Banner.d.ts +7 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +9 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts +12 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +53 -17
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +49 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -8
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +7 -1
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +8 -0
- package/dist/HoverCard/HoverCard.d.ts +2 -2
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +18 -6
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -3
- package/dist/InputGroup/InputGroup.d.ts +2 -2
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +14 -5
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +34 -2
- package/dist/Layer/anchorName.d.ts +20 -0
- package/dist/Layer/anchorName.d.ts.map +1 -0
- package/dist/Layer/anchorName.js +36 -0
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +29 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +55 -11
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +17 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +20 -9
- package/dist/Link/LinkProvider.d.ts +1 -0
- package/dist/Link/LinkProvider.d.ts.map +1 -1
- package/dist/Link/LinkProvider.js +1 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +18 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +13 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +25 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +103 -22
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +46 -28
- package/dist/Popover/usePopover.d.ts +25 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +18 -6
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +22 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +84 -23
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +38 -11
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +86 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +38 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -7
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/TableRow.d.ts +6 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +15 -7
- package/dist/Table/index.d.ts +4 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +3 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
- package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/index.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +161 -5
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +1 -1
- package/dist/Text/text.stylex.d.ts +2 -2
- package/dist/Text/text.stylex.js +2 -2
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +53 -10
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +28 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +132 -3
- package/dist/ToggleButton/ToggleButton.d.ts +7 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +34 -57
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +27 -5
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +57 -9
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +67 -6
- package/dist/Typeahead/Typeahead.d.ts +24 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +29 -5
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +40 -1
- package/dist/astryx.umd.js +147 -0
- package/dist/astryx.umd.js.map +7 -0
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
- package/dist/theme/syntax/presets.d.ts +1 -1
- package/dist/theme/syntax/presets.d.ts.map +1 -1
- package/dist/theme/syntax/presets.js +1 -1
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.js +1 -1
- package/dist/theme/types.d.ts +1 -1
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/package.json +15 -5
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +16 -7
- package/src/Banner/Banner.tsx +9 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.doc.mjs +6 -0
- package/src/Button/Button.test.tsx +105 -11
- package/src/Button/Button.tsx +76 -21
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposer.doc.mjs +3 -0
- package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +3 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +169 -16
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +117 -0
- package/src/Citation/Citation.tsx +9 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +61 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +281 -56
- package/src/DateInput/DateInput.test.tsx +188 -2
- package/src/DateInput/DateInput.tsx +89 -10
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/EmptyState/EmptyState.test.tsx +4 -2
- package/src/EmptyState/EmptyState.tsx +6 -2
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +14 -4
- package/src/Grid/Grid.tsx +20 -0
- package/src/HoverCard/HoverCard.doc.mjs +3 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -2
- package/src/HoverCard/HoverCard.tsx +20 -16
- package/src/HoverCard/useHoverCard.tsx +13 -10
- package/src/Icon/Icon.doc.mjs +8 -0
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.test.tsx +98 -60
- package/src/InputGroup/InputGroup.tsx +21 -4
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +37 -12
- package/src/Layer/anchorName.test.ts +146 -0
- package/src/Layer/anchorName.ts +46 -0
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +12 -2
- package/src/Layer/useLayer.tsx +100 -15
- package/src/Layout/Layout.doc.mjs +1 -1
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -2
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +52 -2
- package/src/Link/Link.tsx +42 -7
- package/src/Link/LinkProvider.tsx +1 -0
- package/src/List/List.doc.mjs +7 -0
- package/src/Markdown/Markdown.doc.mjs +2 -0
- package/src/Markdown/Markdown.test.tsx +28 -26
- package/src/Markdown/Markdown.tsx +21 -6
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MobileNav/MobileNav.doc.mjs +8 -8
- package/src/MobileNav/MobileNav.tsx +13 -0
- package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +145 -21
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/OverflowList/OverflowList.doc.mjs +17 -0
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +250 -14
- package/src/Pagination/Pagination.tsx +54 -29
- package/src/Popover/usePopover.doc.mjs +7 -3
- package/src/Popover/usePopover.tsx +49 -6
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +45 -27
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/Resizable/Resizable.doc.mjs +1 -1
- package/src/Section/Section.doc.mjs +11 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +15 -0
- package/src/Selector/Selector.doc.mjs +25 -0
- package/src/Selector/Selector.test.tsx +322 -15
- package/src/Selector/Selector.tsx +126 -40
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +16 -0
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.doc.mjs +11 -1
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +19 -0
- package/src/Slider/Slider.test.tsx +158 -18
- package/src/Slider/Slider.tsx +54 -6
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +12 -0
- package/src/TabList/TabList.test.tsx +208 -0
- package/src/TabList/TabList.tsx +102 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +72 -41
- package/src/Table/Table.doc.mjs +14 -0
- package/src/Table/Table.test.tsx +39 -30
- package/src/Table/Table.tsx +27 -1
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/TableRow.tsx +37 -7
- package/src/Table/index.ts +6 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/plugins/stickyColumns/index.ts +4 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +175 -4
- package/src/Table/useBaseTablePlugins.ts +1 -0
- package/src/Table/useTableColumnResize.doc.mjs +96 -0
- package/src/Table/useTableStickyColumns.doc.mjs +59 -0
- package/src/Text/Heading.doc.mjs +15 -2
- package/src/Text/Text.doc.mjs +7 -1
- package/src/Text/text.stylex.ts +2 -2
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/TimeInput/TimeInput.doc.mjs +335 -60
- package/src/TimeInput/TimeInput.test.tsx +144 -7
- package/src/TimeInput/TimeInput.tsx +74 -5
- package/src/Timestamp/Timestamp.doc.mjs +9 -0
- package/src/Timestamp/Timestamp.test.tsx +44 -18
- package/src/Timestamp/Timestamp.tsx +30 -10
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +204 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
- package/src/ToggleButton/ToggleButton.test.tsx +39 -18
- package/src/ToggleButton/ToggleButton.tsx +46 -83
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +41 -2
- package/src/Toolbar/Toolbar.doc.mjs +65 -5
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +81 -0
- package/src/Tooltip/useTooltip.tsx +57 -11
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +86 -9
- package/src/Typeahead/Typeahead.doc.mjs +136 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +52 -1
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useImageMode.test.ts +133 -0
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +7 -8
- package/src/theme/generateThemeRules.ts +1 -1
- package/src/theme/syntax/SyntaxTheme.tsx +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
- package/src/theme/syntax/presets.ts +5 -2
- package/src/theme/syntax/tokens.ts +1 -1
- package/src/theme/types.ts +1 -1
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file MultiSelector.tsx
|
|
7
|
-
* @input Uses React, StyleX, usePopover, CheckboxInput, Field, Badge, Icon
|
|
7
|
+
* @input Uses React, StyleX, usePopover, useTooltip, CheckboxInput, Field, Badge, Icon
|
|
8
8
|
* @output Exports MultiSelector component
|
|
9
9
|
* @position Core implementation; consumed by index.ts
|
|
10
10
|
*
|
|
@@ -27,6 +27,7 @@ import React, {
|
|
|
27
27
|
} from 'react';
|
|
28
28
|
import * as stylex from '@stylexjs/stylex';
|
|
29
29
|
import {usePopover} from '../Popover/usePopover';
|
|
30
|
+
import {useTooltip} from '../Tooltip';
|
|
30
31
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
31
32
|
import type {IconName} from '../Icon';
|
|
32
33
|
import {
|
|
@@ -65,6 +66,7 @@ import {
|
|
|
65
66
|
} from '../Selector/utils';
|
|
66
67
|
import {useMultiCombobox} from './hooks';
|
|
67
68
|
import {mergeProps} from '../utils';
|
|
69
|
+
import {useAnnounce} from '../hooks/useAnnounce';
|
|
68
70
|
import type {BaseProps} from '../BaseProps';
|
|
69
71
|
import type {SizeValue} from '../utils/types';
|
|
70
72
|
import {useSize} from '../SizeContext/SizeContext';
|
|
@@ -397,6 +399,30 @@ export interface MultiSelectorProps<
|
|
|
397
399
|
*/
|
|
398
400
|
isDisabled?: boolean;
|
|
399
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Explains why the selector is disabled. When set together with
|
|
404
|
+
* `isDisabled`, the selector shows a tooltip with this text on hover and
|
|
405
|
+
* keyboard focus, and the trigger stays focusable (via `aria-disabled`)
|
|
406
|
+
* so the reason is discoverable by keyboard and assistive technology.
|
|
407
|
+
* Activation stays blocked.
|
|
408
|
+
*
|
|
409
|
+
* Use this instead of wrapping a disabled selector in `Tooltip` — disabled
|
|
410
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* ```
|
|
414
|
+
* <MultiSelector
|
|
415
|
+
* label="Columns"
|
|
416
|
+
* options={columns}
|
|
417
|
+
* value={selected}
|
|
418
|
+
* onChange={setSelected}
|
|
419
|
+
* isDisabled
|
|
420
|
+
* disabledMessage="Select a table first"
|
|
421
|
+
* />
|
|
422
|
+
* ```
|
|
423
|
+
*/
|
|
424
|
+
disabledMessage?: string;
|
|
425
|
+
|
|
400
426
|
/**
|
|
401
427
|
* The options to display in the selector.
|
|
402
428
|
* Can be strings, objects, dividers, or sections.
|
|
@@ -545,6 +571,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
545
571
|
isOptional = false,
|
|
546
572
|
isRequired = false,
|
|
547
573
|
isDisabled = false,
|
|
574
|
+
disabledMessage,
|
|
548
575
|
options,
|
|
549
576
|
value,
|
|
550
577
|
onChange,
|
|
@@ -592,11 +619,26 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
592
619
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
593
620
|
const isBusy = isLoading || optimisticValue !== value;
|
|
594
621
|
|
|
622
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
623
|
+
// tooltip listeners attach to the trigger container (which already exists)
|
|
624
|
+
// and the trigger button stays perceivable via aria-disabled instead of the
|
|
625
|
+
// disabled attribute. Activation is blocked by the isDisabled guards in
|
|
626
|
+
// useMultiCombobox (onTriggerClick / onKeyDown).
|
|
627
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
628
|
+
const disabledMessageTooltip = useTooltip({
|
|
629
|
+
placement: 'above',
|
|
630
|
+
// The container div is not naturally focusable; focusin bubbles up from
|
|
631
|
+
// the trigger button, so always attach focus listeners.
|
|
632
|
+
focusTrigger: 'always',
|
|
633
|
+
isEnabled: showsDisabledMessage,
|
|
634
|
+
});
|
|
635
|
+
|
|
595
636
|
// Build aria-describedby
|
|
596
637
|
const ariaDescribedBy =
|
|
597
638
|
[
|
|
598
639
|
description ? descriptionId : null,
|
|
599
640
|
status?.message ? statusMessageId : null,
|
|
641
|
+
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
600
642
|
]
|
|
601
643
|
.filter(Boolean)
|
|
602
644
|
.join(' ') || undefined;
|
|
@@ -607,6 +649,25 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
607
649
|
[options],
|
|
608
650
|
);
|
|
609
651
|
|
|
652
|
+
// Announce selection-count changes politely (comboboxes-7 announce path).
|
|
653
|
+
// Toggling options / select-all previously produced no audible feedback.
|
|
654
|
+
const announce = useAnnounce();
|
|
655
|
+
const announceSelection = useCallback(
|
|
656
|
+
(nextValue: string[]) => {
|
|
657
|
+
const total = selectableItems.length;
|
|
658
|
+
const selectableSet = new Set(selectableItems.map(item => item.value));
|
|
659
|
+
const selectedCount = nextValue.filter(v => selectableSet.has(v)).length;
|
|
660
|
+
if (selectedCount === 0) {
|
|
661
|
+
announce('Selection cleared');
|
|
662
|
+
} else if (total > 0 && selectedCount === total) {
|
|
663
|
+
announce('All selected');
|
|
664
|
+
} else {
|
|
665
|
+
announce(`${selectedCount} of ${total} selected`);
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
[announce, selectableItems],
|
|
669
|
+
);
|
|
670
|
+
|
|
610
671
|
// Filter items by search query
|
|
611
672
|
const filteredItems = useMemo(() => {
|
|
612
673
|
if (!searchQuery) {
|
|
@@ -696,7 +757,9 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
696
757
|
onHide: handleLayerHide,
|
|
697
758
|
hasCloseButton: false,
|
|
698
759
|
hasAutoFocus: false,
|
|
699
|
-
|
|
760
|
+
// The popup's own role="listbox" is the exposed semantics; the trigger
|
|
761
|
+
// keeps DOM focus, so wrapping it in a modal dialog would misrepresent it.
|
|
762
|
+
role: 'none',
|
|
700
763
|
});
|
|
701
764
|
|
|
702
765
|
// Open dropdown on mount when isDefaultOpen is true
|
|
@@ -708,19 +771,34 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
708
771
|
}, []);
|
|
709
772
|
|
|
710
773
|
// Handle toggle
|
|
711
|
-
//
|
|
774
|
+
// Clear all selected values. Shared by the clear button and the keyboard
|
|
775
|
+
// Delete/Backspace path so clearing is reachable without a mouse.
|
|
776
|
+
const clearValues = useCallback(() => {
|
|
777
|
+
onChange([]);
|
|
778
|
+
announceSelection([]);
|
|
779
|
+
if (changeAction) {
|
|
780
|
+
startTransition(async () => {
|
|
781
|
+
setOptimisticValue([]);
|
|
782
|
+
await changeAction([]);
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
}, [
|
|
786
|
+
onChange,
|
|
787
|
+
changeAction,
|
|
788
|
+
startTransition,
|
|
789
|
+
setOptimisticValue,
|
|
790
|
+
announceSelection,
|
|
791
|
+
]);
|
|
792
|
+
|
|
793
|
+
// Whether there is at least one selected value (clearing is meaningful).
|
|
794
|
+
const hasValue = optimisticValue.length > 0;
|
|
795
|
+
|
|
712
796
|
const handleClear = useCallback(
|
|
713
797
|
(e: React.MouseEvent) => {
|
|
714
798
|
e.stopPropagation(); // Don't open dropdown
|
|
715
|
-
|
|
716
|
-
if (changeAction) {
|
|
717
|
-
startTransition(async () => {
|
|
718
|
-
setOptimisticValue([]);
|
|
719
|
-
await changeAction([]);
|
|
720
|
-
});
|
|
721
|
-
}
|
|
799
|
+
clearValues();
|
|
722
800
|
},
|
|
723
|
-
[
|
|
801
|
+
[clearValues],
|
|
724
802
|
);
|
|
725
803
|
|
|
726
804
|
const handleToggle = useCallback(
|
|
@@ -730,6 +808,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
730
808
|
: [...optimisticValue, itemValue];
|
|
731
809
|
|
|
732
810
|
onChange(newValue);
|
|
811
|
+
announceSelection(newValue);
|
|
733
812
|
if (changeAction) {
|
|
734
813
|
startTransition(async () => {
|
|
735
814
|
setOptimisticValue(newValue);
|
|
@@ -743,6 +822,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
743
822
|
changeAction,
|
|
744
823
|
startTransition,
|
|
745
824
|
setOptimisticValue,
|
|
825
|
+
announceSelection,
|
|
746
826
|
],
|
|
747
827
|
);
|
|
748
828
|
|
|
@@ -788,6 +868,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
788
868
|
}
|
|
789
869
|
|
|
790
870
|
onChange(newValue);
|
|
871
|
+
announceSelection(newValue);
|
|
791
872
|
if (changeAction) {
|
|
792
873
|
startTransition(async () => {
|
|
793
874
|
setOptimisticValue(newValue);
|
|
@@ -802,6 +883,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
802
883
|
changeAction,
|
|
803
884
|
startTransition,
|
|
804
885
|
setOptimisticValue,
|
|
886
|
+
announceSelection,
|
|
805
887
|
]);
|
|
806
888
|
|
|
807
889
|
// Route toggle: select-all sentinel → handleSelectAll, everything else → handleToggle
|
|
@@ -843,9 +925,24 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
843
925
|
}, [popover, hasSearch, optimisticValue]),
|
|
844
926
|
onClose: popover.hide,
|
|
845
927
|
onToggle: handleNavigableToggle,
|
|
928
|
+
onClear: hasClear ? clearValues : undefined,
|
|
929
|
+
hasValue,
|
|
846
930
|
listboxId,
|
|
847
931
|
});
|
|
848
932
|
|
|
933
|
+
// Keep the highlighted option visible during keyboard navigation. The
|
|
934
|
+
// listbox is a fixed-height scroll container, so without this the virtual
|
|
935
|
+
// cursor walks off-screen once navigation passes the visible window. Mirrors
|
|
936
|
+
// CommandPaletteItem's scrollIntoView({block: 'nearest'}) behavior.
|
|
937
|
+
useEffect(() => {
|
|
938
|
+
if (!popover.isOpen || highlightedIndex < 0) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
document
|
|
942
|
+
.getElementById(getItemId(highlightedIndex))
|
|
943
|
+
?.scrollIntoView?.({block: 'nearest'});
|
|
944
|
+
}, [popover.isOpen, highlightedIndex, getItemId]);
|
|
945
|
+
|
|
849
946
|
// Build trigger display content
|
|
850
947
|
const selectedLabels = useMemo(() => {
|
|
851
948
|
return optimisticValue.map(v => {
|
|
@@ -906,17 +1003,30 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
906
1003
|
<input
|
|
907
1004
|
ref={searchRef}
|
|
908
1005
|
id={searchId}
|
|
909
|
-
|
|
1006
|
+
// When hasSearch is set, focus moves into this input on open, so it —
|
|
1007
|
+
// not the trigger — must be the combobox reporting the highlighted
|
|
1008
|
+
// option via aria-activedescendant (comboboxes-4).
|
|
1009
|
+
role="combobox"
|
|
1010
|
+
aria-expanded={popover.isOpen}
|
|
910
1011
|
aria-controls={listboxId}
|
|
1012
|
+
aria-autocomplete="list"
|
|
1013
|
+
aria-activedescendant={
|
|
1014
|
+
popover.isOpen && highlightedIndex >= 0
|
|
1015
|
+
? getItemId(highlightedIndex)
|
|
1016
|
+
: undefined
|
|
1017
|
+
}
|
|
911
1018
|
aria-label="Search options"
|
|
912
1019
|
type="text"
|
|
913
1020
|
value={searchQuery}
|
|
914
1021
|
onChange={e => setSearchQuery(e.target.value)}
|
|
915
1022
|
onKeyDown={e => {
|
|
916
|
-
//
|
|
1023
|
+
// Arrow keys navigate options; Enter toggles; Escape/Tab close.
|
|
1024
|
+
// Space and Home/End are left to the input (type a space / move
|
|
1025
|
+
// the caret), not forwarded to option navigation.
|
|
917
1026
|
if (
|
|
918
1027
|
e.key === 'ArrowDown' ||
|
|
919
1028
|
e.key === 'ArrowUp' ||
|
|
1029
|
+
e.key === 'Enter' ||
|
|
920
1030
|
e.key === 'Escape' ||
|
|
921
1031
|
e.key === 'Tab'
|
|
922
1032
|
) {
|
|
@@ -935,6 +1045,9 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
935
1045
|
searchQuery,
|
|
936
1046
|
searchPlaceholder,
|
|
937
1047
|
onKeyDown,
|
|
1048
|
+
popover.isOpen,
|
|
1049
|
+
highlightedIndex,
|
|
1050
|
+
getItemId,
|
|
938
1051
|
]);
|
|
939
1052
|
|
|
940
1053
|
// Render an individual item (index-based)
|
|
@@ -1062,9 +1175,7 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1062
1175
|
|
|
1063
1176
|
if (isDivider(option)) {
|
|
1064
1177
|
flushPending();
|
|
1065
|
-
elements.push(
|
|
1066
|
-
<Divider key={`divider-${i}`} xstyle={styles.divider} />,
|
|
1067
|
-
);
|
|
1178
|
+
elements.push(<Divider key={`divider-${i}`} xstyle={styles.divider} />);
|
|
1068
1179
|
} else if (isSection(option)) {
|
|
1069
1180
|
flushPending();
|
|
1070
1181
|
const count = option.options.length;
|
|
@@ -1120,6 +1231,10 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1120
1231
|
<div
|
|
1121
1232
|
ref={el => {
|
|
1122
1233
|
popover.triggerRef(el);
|
|
1234
|
+
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
1235
|
+
// Handlers are gated internally by isEnabled, and anchor names
|
|
1236
|
+
// compose, so attaching unconditionally is safe.
|
|
1237
|
+
disabledMessageTooltip.ref(el);
|
|
1123
1238
|
}}
|
|
1124
1239
|
onClick={onTriggerClick}
|
|
1125
1240
|
data-testid={testId}
|
|
@@ -1144,12 +1259,15 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1144
1259
|
ref={triggerRef}
|
|
1145
1260
|
id={triggerId}
|
|
1146
1261
|
type="button"
|
|
1147
|
-
|
|
1262
|
+
// In hasSearch mode the popup's search input is the combobox (it owns
|
|
1263
|
+
// focus + aria-activedescendant, comboboxes-4), so the trigger is a
|
|
1264
|
+
// plain button that opens the listbox — not a second combobox.
|
|
1265
|
+
role={hasSearch ? undefined : 'combobox'}
|
|
1148
1266
|
aria-haspopup="listbox"
|
|
1149
1267
|
aria-expanded={popover.isOpen}
|
|
1150
1268
|
aria-controls={listboxId}
|
|
1151
1269
|
aria-activedescendant={
|
|
1152
|
-
popover.isOpen && highlightedIndex >= 0
|
|
1270
|
+
!hasSearch && popover.isOpen && highlightedIndex >= 0
|
|
1153
1271
|
? getItemId(highlightedIndex)
|
|
1154
1272
|
: undefined
|
|
1155
1273
|
}
|
|
@@ -1157,9 +1275,13 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1157
1275
|
aria-required={isRequired ? 'true' : undefined}
|
|
1158
1276
|
aria-invalid={status?.type === 'error' ? 'true' : undefined}
|
|
1159
1277
|
aria-busy={isBusy || undefined}
|
|
1160
|
-
|
|
1278
|
+
// With a disabledMessage the trigger keeps focusability via
|
|
1279
|
+
// aria-disabled so the reason is focus-discoverable; activation is
|
|
1280
|
+
// still blocked by the isDisabled guards in useMultiCombobox.
|
|
1281
|
+
disabled={isDisabled && !showsDisabledMessage}
|
|
1282
|
+
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
1161
1283
|
onKeyDown={onKeyDown}
|
|
1162
|
-
tabIndex={-1}
|
|
1284
|
+
tabIndex={isDisabled && !showsDisabledMessage ? -1 : 0}
|
|
1163
1285
|
{...stylex.props(styles.trigger)}>
|
|
1164
1286
|
<span {...stylex.props(styles.triggerContent)}>
|
|
1165
1287
|
{renderTriggerContent()}
|
|
@@ -1169,7 +1291,6 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1169
1291
|
{hasClear && value.length > 0 && !isDisabled && (
|
|
1170
1292
|
<button
|
|
1171
1293
|
type="button"
|
|
1172
|
-
tabIndex={-1}
|
|
1173
1294
|
onClick={handleClear}
|
|
1174
1295
|
aria-label={`Clear all ${label}`}
|
|
1175
1296
|
{...stylex.props(styles.clearButton)}>
|
|
@@ -1211,6 +1332,9 @@ export function MultiSelector<T extends MultiSelectorOptionType>({
|
|
|
1211
1332
|
xstyle: styles.popover,
|
|
1212
1333
|
},
|
|
1213
1334
|
)}
|
|
1335
|
+
|
|
1336
|
+
{showsDisabledMessage &&
|
|
1337
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
1214
1338
|
</Field>
|
|
1215
1339
|
);
|
|
1216
1340
|
}
|
|
@@ -23,6 +23,17 @@ interface UseMultiComboboxOptions {
|
|
|
23
23
|
onOpen: () => void;
|
|
24
24
|
onClose: () => void;
|
|
25
25
|
onToggle: (itemValue: string) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Clear all selected values. When provided, pressing Delete or Backspace on
|
|
28
|
+
* the closed trigger clears the selection — a keyboard equivalent of the
|
|
29
|
+
* clear button (comboboxes-2). No-op when the popup is open or search is on.
|
|
30
|
+
*/
|
|
31
|
+
onClear?: () => void;
|
|
32
|
+
/**
|
|
33
|
+
* Whether at least one value is selected (i.e. there is something to clear).
|
|
34
|
+
* The Delete/Backspace clear path is skipped when false.
|
|
35
|
+
*/
|
|
36
|
+
hasValue?: boolean;
|
|
26
37
|
listboxId: string;
|
|
27
38
|
}
|
|
28
39
|
|
|
@@ -49,6 +60,8 @@ export function useMultiCombobox({
|
|
|
49
60
|
onOpen,
|
|
50
61
|
onClose,
|
|
51
62
|
onToggle,
|
|
63
|
+
onClear,
|
|
64
|
+
hasValue = false,
|
|
52
65
|
listboxId,
|
|
53
66
|
}: UseMultiComboboxOptions): UseMultiComboboxResult {
|
|
54
67
|
const [highlightedIndex, setHighlightedIndex] = useState<number>(-1);
|
|
@@ -179,6 +192,18 @@ export function useMultiCombobox({
|
|
|
179
192
|
}
|
|
180
193
|
break;
|
|
181
194
|
|
|
195
|
+
case 'Delete':
|
|
196
|
+
case 'Backspace':
|
|
197
|
+
// Keyboard equivalent of the clear button (comboboxes-2): clear all
|
|
198
|
+
// selected values from the closed trigger so clearing is not
|
|
199
|
+
// mouse-only. Skipped in search mode (keys edit the query) and while
|
|
200
|
+
// the popup is open (arrow navigation owns interaction).
|
|
201
|
+
if (!hasSearch && !isOpen && onClear != null && hasValue) {
|
|
202
|
+
e.preventDefault();
|
|
203
|
+
onClear();
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
206
|
+
|
|
182
207
|
default:
|
|
183
208
|
// Typeahead only when search is not present
|
|
184
209
|
if (!hasSearch && e.key.length === 1 && !e.ctrlKey && !e.metaKey) {
|
|
@@ -218,6 +243,8 @@ export function useMultiCombobox({
|
|
|
218
243
|
getEnabledIndices,
|
|
219
244
|
typeahead,
|
|
220
245
|
hasSearch,
|
|
246
|
+
onClear,
|
|
247
|
+
hasValue,
|
|
221
248
|
],
|
|
222
249
|
);
|
|
223
250
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
3
|
import {describe, it, expect, vi} from 'vitest';
|
|
4
|
-
import {render, screen} from '@testing-library/react';
|
|
4
|
+
import {render, screen, fireEvent} from '@testing-library/react';
|
|
5
5
|
import userEvent from '@testing-library/user-event';
|
|
6
6
|
import {NavHeadingMenu} from './NavHeadingMenu';
|
|
7
7
|
import {NavHeadingMenuItem} from './NavHeadingMenuItem';
|
|
@@ -204,6 +204,82 @@ describe('keyboard navigation', () => {
|
|
|
204
204
|
await user.keyboard('{End}');
|
|
205
205
|
expect(document.activeElement).toBe(items[2]);
|
|
206
206
|
});
|
|
207
|
+
|
|
208
|
+
it('activates a focused onClick-only item with Enter', async () => {
|
|
209
|
+
const user = userEvent.setup();
|
|
210
|
+
const onClick = vi.fn();
|
|
211
|
+
render(
|
|
212
|
+
<NavHeadingMenu>
|
|
213
|
+
<NavHeadingMenuItem label="Action" onClick={onClick} />
|
|
214
|
+
</NavHeadingMenu>,
|
|
215
|
+
);
|
|
216
|
+
const item = screen.getByRole('menuitem');
|
|
217
|
+
item.focus();
|
|
218
|
+
|
|
219
|
+
await user.keyboard('{Enter}');
|
|
220
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it('activates a focused onClick-only item with Space', async () => {
|
|
224
|
+
const user = userEvent.setup();
|
|
225
|
+
const onClick = vi.fn();
|
|
226
|
+
render(
|
|
227
|
+
<NavHeadingMenu>
|
|
228
|
+
<NavHeadingMenuItem label="Action" onClick={onClick} />
|
|
229
|
+
</NavHeadingMenu>,
|
|
230
|
+
);
|
|
231
|
+
const item = screen.getByRole('menuitem');
|
|
232
|
+
item.focus();
|
|
233
|
+
|
|
234
|
+
await user.keyboard('{ }');
|
|
235
|
+
expect(onClick).toHaveBeenCalledOnce();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('does not activate a disabled item with Enter', async () => {
|
|
239
|
+
const user = userEvent.setup();
|
|
240
|
+
const onClick = vi.fn();
|
|
241
|
+
render(
|
|
242
|
+
<NavHeadingMenu>
|
|
243
|
+
<NavHeadingMenuItem label="Action" onClick={onClick} isDisabled />
|
|
244
|
+
</NavHeadingMenu>,
|
|
245
|
+
);
|
|
246
|
+
const item = screen.getByRole('menuitem');
|
|
247
|
+
item.focus();
|
|
248
|
+
|
|
249
|
+
await user.keyboard('{Enter}');
|
|
250
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('typeahead focuses the item matching the typed character (menus-11)', () => {
|
|
254
|
+
render(
|
|
255
|
+
<NavHeadingMenu>
|
|
256
|
+
<NavHeadingMenuItem label="Cut" />
|
|
257
|
+
<NavHeadingMenuItem label="Paste" />
|
|
258
|
+
</NavHeadingMenu>,
|
|
259
|
+
);
|
|
260
|
+
const menu = screen.getByRole('menu');
|
|
261
|
+
fireEvent.keyDown(menu, {key: 'p'});
|
|
262
|
+
expect(screen.getByRole('menuitem', {name: 'Paste'})).toHaveFocus();
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('typeahead skips a disabled menuitem (menus-11)', () => {
|
|
266
|
+
render(
|
|
267
|
+
<NavHeadingMenu>
|
|
268
|
+
<NavHeadingMenuItem label="Cut" />
|
|
269
|
+
<NavHeadingMenuItem label="Paste (disabled)" isDisabled />
|
|
270
|
+
<NavHeadingMenuItem label="Paste special" />
|
|
271
|
+
</NavHeadingMenu>,
|
|
272
|
+
);
|
|
273
|
+
const menu = screen.getByRole('menu');
|
|
274
|
+
// Typing "p" must land on the enabled "Paste special", never the disabled
|
|
275
|
+
// "Paste (disabled)" — the disabled item is excluded from the typeahead
|
|
276
|
+
// selector entirely.
|
|
277
|
+
fireEvent.keyDown(menu, {key: 'p'});
|
|
278
|
+
expect(screen.getByRole('menuitem', {name: 'Paste special'})).toHaveFocus();
|
|
279
|
+
expect(
|
|
280
|
+
screen.getByRole('menuitem', {name: 'Paste (disabled)'}),
|
|
281
|
+
).not.toHaveFocus();
|
|
282
|
+
});
|
|
207
283
|
});
|
|
208
284
|
|
|
209
285
|
describe('context forwarding', () => {
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
* - /packages/core/src/NavMenu/index.ts
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import React, {useMemo, type ReactNode} from 'react';
|
|
15
|
+
import React, {useCallback, useMemo, type ReactNode} from 'react';
|
|
16
16
|
import * as stylex from '@stylexjs/stylex';
|
|
17
17
|
import {spacingVars} from '../theme/tokens.stylex';
|
|
18
18
|
import {mergeProps, mergeRefs} from '../utils';
|
|
19
19
|
import type {BaseProps} from '../BaseProps';
|
|
20
20
|
import {useListFocus} from '../hooks/useListFocus';
|
|
21
|
+
import {useTypeahead} from '../hooks/useTypeahead';
|
|
21
22
|
import {themeProps} from '../utils/themeProps';
|
|
22
23
|
import {
|
|
23
24
|
NavHeadingMenuContext,
|
|
@@ -98,10 +99,56 @@ export function NavHeadingMenu({
|
|
|
98
99
|
const closeCtx = useNavHeadingCloseContext();
|
|
99
100
|
const closeMenu = closeCtx?.closeMenu;
|
|
100
101
|
|
|
101
|
-
const {listRef, handleKeyDown} = useListFocus({
|
|
102
|
+
const {listRef, handleKeyDown, focusItem} = useListFocus({
|
|
103
|
+
itemSelector: '[role="menuitem"]:not([aria-disabled="true"])',
|
|
102
104
|
onEscape: closeMenu,
|
|
103
105
|
});
|
|
104
106
|
|
|
107
|
+
// First-character typeahead over the (enabled) menu items (menus-11).
|
|
108
|
+
const getMenuItems = useCallback(
|
|
109
|
+
(): HTMLElement[] =>
|
|
110
|
+
listRef.current
|
|
111
|
+
? Array.from(
|
|
112
|
+
listRef.current.querySelectorAll<HTMLElement>(
|
|
113
|
+
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
: [],
|
|
117
|
+
[listRef],
|
|
118
|
+
);
|
|
119
|
+
const typeahead = useTypeahead({
|
|
120
|
+
getItemLabels: () => getMenuItems().map(el => el.textContent),
|
|
121
|
+
onMatch: focusItem,
|
|
122
|
+
getCurrentIndex: () =>
|
|
123
|
+
getMenuItems().findIndex(
|
|
124
|
+
el =>
|
|
125
|
+
el === document.activeElement || el.contains(document.activeElement),
|
|
126
|
+
),
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Extend useListFocus with Enter/Space activation. Items rendered without an
|
|
130
|
+
// `href` are `<div role="menuitem">` elements, which have no native keyboard
|
|
131
|
+
// activation — without this, Enter/Space on a focused onClick-only item does
|
|
132
|
+
// nothing. Anchor items (with `href`) already activate on Enter natively.
|
|
133
|
+
const listKeyDown = useCallback(
|
|
134
|
+
(e: React.KeyboardEvent) => {
|
|
135
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
136
|
+
const focused = document.activeElement as HTMLElement | null;
|
|
137
|
+
if (focused?.getAttribute('role') === 'menuitem') {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
focused.click();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (typeahead.onKeyDown(e)) {
|
|
144
|
+
e.preventDefault();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
handleKeyDown(e);
|
|
148
|
+
},
|
|
149
|
+
[handleKeyDown, typeahead],
|
|
150
|
+
);
|
|
151
|
+
|
|
105
152
|
const ctx = useMemo(
|
|
106
153
|
() => ({
|
|
107
154
|
closeMenu: closeMenu ?? (() => {}),
|
|
@@ -117,7 +164,7 @@ export function NavHeadingMenu({
|
|
|
117
164
|
<div
|
|
118
165
|
ref={mergeRefs(ref, listRef)}
|
|
119
166
|
role="menu"
|
|
120
|
-
onKeyDown={
|
|
167
|
+
onKeyDown={listKeyDown}
|
|
121
168
|
data-testid={testId}
|
|
122
169
|
{...mergeProps(
|
|
123
170
|
themeProps('nav-heading-menu', {size}),
|
|
@@ -62,6 +62,12 @@ export const docs = {
|
|
|
62
62
|
type: 'boolean',
|
|
63
63
|
description: 'Whether the input is disabled.',
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
name: 'disabledMessage',
|
|
67
|
+
type: 'string',
|
|
68
|
+
description:
|
|
69
|
+
'Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled NumberInput in Tooltip.',
|
|
70
|
+
},
|
|
65
71
|
{
|
|
66
72
|
name: 'placeholder',
|
|
67
73
|
type: 'string',
|
|
@@ -166,6 +172,7 @@ export const docs = {
|
|
|
166
172
|
{ guidance: true, description: 'Show units (e.g. "%" or "GB") so users know what the number represents.' },
|
|
167
173
|
{ guidance: false, description: 'Use NumberInput for free-form text that happens to contain numbers; use TextInput instead.' },
|
|
168
174
|
{ guidance: false, description: 'Set both isOptional and isRequired on the same field.' },
|
|
175
|
+
{ guidance: false, description: "Wrap a disabled NumberInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead." },
|
|
169
176
|
],
|
|
170
177
|
anatomy: [
|
|
171
178
|
{name: 'Label', required: true, description: 'The label for the number input.'},
|
|
@@ -236,6 +243,12 @@ export const docsZh = {
|
|
|
236
243
|
type: 'boolean',
|
|
237
244
|
description: '输入框是否禁用。',
|
|
238
245
|
},
|
|
246
|
+
{
|
|
247
|
+
name: 'disabledMessage',
|
|
248
|
+
type: 'string',
|
|
249
|
+
description:
|
|
250
|
+
'说明输入框被禁用的原因。与 isDisabled 一起使用时,在悬停/键盘聚焦时显示工具提示,并通过 aria-disabled 保持输入框可聚焦(字段变为只读)。请使用此属性,而不是用 Tooltip 包裹已禁用的 NumberInput。',
|
|
251
|
+
},
|
|
239
252
|
{
|
|
240
253
|
name: 'placeholder',
|
|
241
254
|
type: 'string',
|
|
@@ -339,6 +352,7 @@ export const docsZh = {
|
|
|
339
352
|
{ guidance: true, description: 'Show units (e.g. "%" or "GB") so users know what the number represents.' },
|
|
340
353
|
{ guidance: false, description: 'Use NumberInput for free-form text that happens to contain numbers; use TextInput instead.' },
|
|
341
354
|
{ guidance: false, description: 'Set both isOptional and isRequired on the same field.' },
|
|
355
|
+
{ guidance: false, description: "Wrap a disabled NumberInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead." },
|
|
342
356
|
],
|
|
343
357
|
anatomy: [
|
|
344
358
|
{name: 'Label', required: true, description: 'The label for the number input.'},
|
|
@@ -361,6 +375,7 @@ export const docsDense = {
|
|
|
361
375
|
{ guidance: true, description: 'Show units (e.g. "%" or "GB") so users know what the number represents.' },
|
|
362
376
|
{ guidance: false, description: 'Use NumberInput for free-form text that happens to contain numbers; use TextInput instead.' },
|
|
363
377
|
{ guidance: false, description: 'Set both isOptional and isRequired on the same field.' },
|
|
378
|
+
{ guidance: false, description: "Wrap a disabled NumberInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead." },
|
|
364
379
|
],
|
|
365
380
|
anatomy: [
|
|
366
381
|
{name: 'Label', required: true, description: 'The label for the number input.'},
|
|
@@ -380,6 +395,8 @@ export const docsDense = {
|
|
|
380
395
|
isOptional: 'Field optional (mutually exclusive w/ isRequired).',
|
|
381
396
|
isRequired: 'Field required (mutually exclusive w/ isOptional).',
|
|
382
397
|
isDisabled: 'Input disabled.',
|
|
398
|
+
disabledMessage:
|
|
399
|
+
'Explains why input is disabled. With isDisabled, shows tooltip on hover/focus + keeps input focusable via aria-disabled (field becomes read-only). Use instead of wrapping a disabled NumberInput in Tooltip.',
|
|
383
400
|
placeholder: 'Placeholder text.',
|
|
384
401
|
labelTooltip: 'Tooltip text in info icon at label end.',
|
|
385
402
|
startIcon: 'Icon at input start.',
|