@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
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useLayoutEffect,
|
|
9
|
+
useMemo,
|
|
10
|
+
useRef,
|
|
11
|
+
useState,
|
|
12
|
+
} from 'react';
|
|
6
13
|
import * as stylex from '@stylexjs/stylex';
|
|
7
14
|
import {spacingVars, durationVars, easeVars} from '../theme/tokens.stylex';
|
|
8
15
|
import {mergeProps} from '../utils';
|
|
16
|
+
import {INTERACTIVE_SELECTORS} from '../hooks/useClickableContainer';
|
|
9
17
|
import {Toast} from './Toast';
|
|
10
18
|
import {ToastContext, type ToastContextValue} from './ToastContext';
|
|
11
|
-
import type {
|
|
12
|
-
ToastEntry,
|
|
13
|
-
ToastPosition,
|
|
14
|
-
ToastDismissReason,
|
|
15
|
-
} from './types';
|
|
19
|
+
import type {ToastEntry, ToastPosition, ToastDismissReason} from './types';
|
|
16
20
|
|
|
17
21
|
const styles = stylex.create({
|
|
18
22
|
viewport: {
|
|
@@ -108,6 +112,47 @@ export function ToastViewport({
|
|
|
108
112
|
const toastsRef = useRef(toasts);
|
|
109
113
|
toastsRef.current = toasts;
|
|
110
114
|
|
|
115
|
+
// Show the popover on mount so it enters the top layer.
|
|
116
|
+
const viewportRef = useRef<HTMLDivElement>(null);
|
|
117
|
+
// The element that was focused before the user jumped into the viewport
|
|
118
|
+
// (via F6). Used to restore focus once all toasts are dismissed so focus
|
|
119
|
+
// never falls to <body>.
|
|
120
|
+
const prevFocusRef = useRef<HTMLElement | null>(null);
|
|
121
|
+
// When a toast is dismissed while focus lives inside it, we need to move
|
|
122
|
+
// focus to a sensible neighbor after that toast unmounts. This holds the
|
|
123
|
+
// id of the toast whose removal should trigger a focus handoff.
|
|
124
|
+
const focusHandoffIdRef = useRef<string | null>(null);
|
|
125
|
+
// The next toast id that should receive focus once the dismissed toast has
|
|
126
|
+
// unmounted, or 'restore' to fall back to the previously-focused element.
|
|
127
|
+
const pendingFocusRef = useRef<string | 'restore' | null>(null);
|
|
128
|
+
|
|
129
|
+
// Collect a focusable control within a toast node, if any.
|
|
130
|
+
// Reuses the canonical INTERACTIVE_SELECTORS list (native controls plus
|
|
131
|
+
// role-based interactive elements) instead of a hand-rolled subset, then
|
|
132
|
+
// narrows to the first candidate that can actually receive focus —
|
|
133
|
+
// excluding elements opted out with `tabindex="-1"` and disabled controls.
|
|
134
|
+
const getFocusable = useCallback(
|
|
135
|
+
(container: HTMLElement | null): HTMLElement | null => {
|
|
136
|
+
if (!container) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
const candidates =
|
|
140
|
+
container.querySelectorAll<HTMLElement>(INTERACTIVE_SELECTORS);
|
|
141
|
+
for (const candidate of candidates) {
|
|
142
|
+
if (
|
|
143
|
+
candidate.getAttribute('tabindex') === '-1' ||
|
|
144
|
+
candidate.hasAttribute('disabled') ||
|
|
145
|
+
candidate.getAttribute('aria-disabled') === 'true'
|
|
146
|
+
) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
return candidate;
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
},
|
|
153
|
+
[],
|
|
154
|
+
);
|
|
155
|
+
|
|
111
156
|
const addToast = useCallback((entry: ToastEntry) => {
|
|
112
157
|
setToasts(prev => {
|
|
113
158
|
const {uniqueID, collisionBehavior = 'overwrite'} = entry.options;
|
|
@@ -124,21 +169,44 @@ export function ToastViewport({
|
|
|
124
169
|
});
|
|
125
170
|
}, []);
|
|
126
171
|
|
|
127
|
-
const removeToast = useCallback(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
172
|
+
const removeToast = useCallback((id: string, reason: ToastDismissReason) => {
|
|
173
|
+
const entry = toastsRef.current.find(t => t.id === id);
|
|
174
|
+
if (entry) {
|
|
175
|
+
entry.options.onHide?.(reason);
|
|
176
|
+
}
|
|
177
|
+
// If focus currently lives inside the toast being dismissed, remember
|
|
178
|
+
// that its removal must hand focus off to a neighbor (or the element
|
|
179
|
+
// focused before the user entered the viewport) rather than <body>.
|
|
180
|
+
const el = viewportRef.current;
|
|
181
|
+
const active = document.activeElement;
|
|
182
|
+
const dismissedNode =
|
|
183
|
+
el?.querySelector<HTMLElement>(`[data-toast-id="${id}"]`) ?? null;
|
|
184
|
+
if (
|
|
185
|
+
dismissedNode &&
|
|
186
|
+
active instanceof Node &&
|
|
187
|
+
dismissedNode.contains(active)
|
|
188
|
+
) {
|
|
189
|
+
focusHandoffIdRef.current = id;
|
|
190
|
+
// Pick the neighbor to receive focus while the DOM is still intact:
|
|
191
|
+
// prefer the next toast, then the previous, else restore.
|
|
192
|
+
const remaining = toastsRef.current.filter(t => t.id !== id);
|
|
193
|
+
if (remaining.length > 0) {
|
|
194
|
+
const dismissedIndex = toastsRef.current.findIndex(t => t.id === id);
|
|
195
|
+
const next =
|
|
196
|
+
toastsRef.current[dismissedIndex + 1] ??
|
|
197
|
+
toastsRef.current[dismissedIndex - 1];
|
|
198
|
+
pendingFocusRef.current = next ? next.id : 'restore';
|
|
199
|
+
} else {
|
|
200
|
+
pendingFocusRef.current = 'restore';
|
|
132
201
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
);
|
|
202
|
+
}
|
|
203
|
+
setExitingIds(prev => {
|
|
204
|
+
if (prev.has(id)) {
|
|
205
|
+
return prev;
|
|
206
|
+
}
|
|
207
|
+
return new Set(prev).add(id);
|
|
208
|
+
});
|
|
209
|
+
}, []);
|
|
142
210
|
|
|
143
211
|
const handleExited = useCallback((id: string) => {
|
|
144
212
|
setExitingIds(prev => {
|
|
@@ -152,6 +220,43 @@ export function ToastViewport({
|
|
|
152
220
|
setToasts(prev => prev.filter(t => t.id !== id));
|
|
153
221
|
}, []);
|
|
154
222
|
|
|
223
|
+
// After a dismissed toast unmounts, hand focus off so it never falls to
|
|
224
|
+
// <body>. Runs in a layout effect once the toast list no longer contains
|
|
225
|
+
// the dismissed toast.
|
|
226
|
+
useLayoutEffect(() => {
|
|
227
|
+
const handoffId = focusHandoffIdRef.current;
|
|
228
|
+
const target = pendingFocusRef.current;
|
|
229
|
+
if (handoffId == null || target == null) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Wait until the dismissed toast is actually gone from the list.
|
|
233
|
+
if (toasts.some(t => t.id === handoffId)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
focusHandoffIdRef.current = null;
|
|
237
|
+
pendingFocusRef.current = null;
|
|
238
|
+
const el = viewportRef.current;
|
|
239
|
+
if (target !== 'restore' && el) {
|
|
240
|
+
const nextNode = el.querySelector<HTMLElement>(
|
|
241
|
+
`[data-toast-id="${target}"]`,
|
|
242
|
+
);
|
|
243
|
+
const focusable = getFocusable(nextNode) ?? nextNode;
|
|
244
|
+
if (focusable) {
|
|
245
|
+
focusable.focus();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// No remaining toast to receive focus — restore the previously-focused
|
|
250
|
+
// element if it's still connected, else fall back to the container.
|
|
251
|
+
const prev = prevFocusRef.current;
|
|
252
|
+
prevFocusRef.current = null;
|
|
253
|
+
if (prev && prev.isConnected) {
|
|
254
|
+
prev.focus();
|
|
255
|
+
} else if (el) {
|
|
256
|
+
el.focus();
|
|
257
|
+
}
|
|
258
|
+
}, [toasts, getFocusable]);
|
|
259
|
+
|
|
155
260
|
const findByUniqueID = useCallback((uid: string) => {
|
|
156
261
|
return toastsRef.current.find(t => t.options.uniqueID === uid);
|
|
157
262
|
}, []);
|
|
@@ -177,7 +282,6 @@ export function ToastViewport({
|
|
|
177
282
|
}
|
|
178
283
|
|
|
179
284
|
// Show the popover on mount so it enters the top layer
|
|
180
|
-
const viewportRef = useRef<HTMLDivElement>(null);
|
|
181
285
|
useEffect(() => {
|
|
182
286
|
if (!isTopLayer) {
|
|
183
287
|
return;
|
|
@@ -192,6 +296,45 @@ export function ToastViewport({
|
|
|
192
296
|
}
|
|
193
297
|
}, [isTopLayer]);
|
|
194
298
|
|
|
299
|
+
// F6 jumps focus into the toast viewport — the standard "go to
|
|
300
|
+
// notifications" affordance. Focus the first control in the newest toast,
|
|
301
|
+
// or the viewport container if none. Toasts are non-modal, so this only
|
|
302
|
+
// moves focus in; Shift+Tab / Escape let focus leave naturally.
|
|
303
|
+
const hasToasts = toasts.length > 0;
|
|
304
|
+
useEffect(() => {
|
|
305
|
+
if (!hasToasts) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
309
|
+
if (e.key !== 'F6') {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const el = viewportRef.current;
|
|
313
|
+
if (!el) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
// Already inside the viewport — nothing to do.
|
|
317
|
+
const active = document.activeElement;
|
|
318
|
+
if (active instanceof Node && el.contains(active)) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
// Remember where focus was so it can be restored on dismiss.
|
|
323
|
+
if (active instanceof HTMLElement) {
|
|
324
|
+
prevFocusRef.current = active;
|
|
325
|
+
}
|
|
326
|
+
// Newest toast is the last one rendered in the DOM.
|
|
327
|
+
const toastNodes = el.querySelectorAll<HTMLElement>('[data-toast-id]');
|
|
328
|
+
const newest = toastNodes[toastNodes.length - 1] ?? null;
|
|
329
|
+
const focusable = getFocusable(newest) ?? newest ?? el;
|
|
330
|
+
focusable.focus();
|
|
331
|
+
};
|
|
332
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
333
|
+
return () => {
|
|
334
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
335
|
+
};
|
|
336
|
+
}, [hasToasts, getFocusable]);
|
|
337
|
+
|
|
195
338
|
const posStyle =
|
|
196
339
|
position === 'topEnd'
|
|
197
340
|
? styles.topEnd
|
|
@@ -208,6 +351,8 @@ export function ToastViewport({
|
|
|
208
351
|
ref={viewportRef}
|
|
209
352
|
role="region"
|
|
210
353
|
aria-label="Notifications"
|
|
354
|
+
aria-modal={false}
|
|
355
|
+
tabIndex={-1}
|
|
211
356
|
// popover="manual" promotes to the top layer (above dialogs).
|
|
212
357
|
// Omitted inside dialogs where the viewport is already in a top layer.
|
|
213
358
|
popover={isTopLayer ? 'manual' : undefined}
|
|
@@ -223,6 +368,7 @@ export function ToastViewport({
|
|
|
223
368
|
return (
|
|
224
369
|
<div
|
|
225
370
|
key={entry.id}
|
|
371
|
+
data-toast-id={entry.id}
|
|
226
372
|
{...stylex.props(
|
|
227
373
|
styles.toastWrapper,
|
|
228
374
|
isExiting && styles.toastWrapperExiting,
|
|
@@ -34,13 +34,13 @@ export const docs = {
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
name: 'onPressedChange',
|
|
37
|
-
type: '(isPressed: boolean) => void',
|
|
38
|
-
description: 'Called when pressed state should change. Ignored when inside a group.',
|
|
37
|
+
type: '(isPressed: boolean, event: MouseEvent) => void',
|
|
38
|
+
description: 'Called when pressed state should change. Receives the next state and the click event; call event.preventDefault() to skip pressedChangeAction. Ignored when inside a group.',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
name: 'pressedChangeAction',
|
|
42
42
|
type: '(isPressed: boolean) => void | Promise<void>',
|
|
43
|
-
description: 'Action handler for API- or navigation-backed toggles, run in a transition. Shows an optimistic pressed state immediately and a
|
|
43
|
+
description: 'Action handler for API- or navigation-backed toggles, run in a transition. Shows an optimistic pressed state immediately and a spinner while pending; the button stays interruptible by re-clicks.',
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
name: 'size',
|
|
@@ -74,6 +74,12 @@ export const docs = {
|
|
|
74
74
|
},
|
|
75
75
|
],
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
name: 'isIconOnly',
|
|
79
|
+
type: 'boolean',
|
|
80
|
+
description: 'When true, renders as a square icon-only button with `label` as the aria-label and an automatic tooltip from the label.',
|
|
81
|
+
default: 'false',
|
|
82
|
+
},
|
|
77
83
|
{
|
|
78
84
|
name: 'pressedIcon',
|
|
79
85
|
type: 'ReactNode',
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import {describe, it, expect, vi} from 'vitest';
|
|
12
|
-
import {render, screen, act, fireEvent
|
|
12
|
+
import {render, screen, act, fireEvent} from '@testing-library/react';
|
|
13
13
|
import userEvent from '@testing-library/user-event';
|
|
14
|
-
import {useState} from 'react';
|
|
14
|
+
import {useState, type MouseEvent} from 'react';
|
|
15
15
|
import {ToggleButton} from './ToggleButton';
|
|
16
16
|
import {ToggleButtonGroup} from './ToggleButtonGroup';
|
|
17
17
|
|
|
@@ -88,7 +88,7 @@ describe('ToggleButton', () => {
|
|
|
88
88
|
);
|
|
89
89
|
|
|
90
90
|
await user.click(screen.getByRole('button'));
|
|
91
|
-
expect(handleChange).toHaveBeenCalledWith(true);
|
|
91
|
+
expect(handleChange).toHaveBeenCalledWith(true, expect.anything());
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
it('calls onPressedChange with false when clicking pressed button', async () => {
|
|
@@ -103,7 +103,7 @@ describe('ToggleButton', () => {
|
|
|
103
103
|
);
|
|
104
104
|
|
|
105
105
|
await user.click(screen.getByRole('button'));
|
|
106
|
-
expect(handleChange).toHaveBeenCalledWith(false);
|
|
106
|
+
expect(handleChange).toHaveBeenCalledWith(false, expect.anything());
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
it('renders pressedIcon when pressed', () => {
|
|
@@ -193,7 +193,7 @@ describe('ToggleButton', () => {
|
|
|
193
193
|
expect(screen.getByTestId('bold-toggle')).toBeInTheDocument();
|
|
194
194
|
});
|
|
195
195
|
|
|
196
|
-
it('shows the optimistic pressed state
|
|
196
|
+
it('shows the optimistic pressed state and stays interruptible while pending', async () => {
|
|
197
197
|
const user = userEvent.setup();
|
|
198
198
|
let resolveAction: (() => void) | undefined;
|
|
199
199
|
const pressedChangeAction = vi.fn(
|
|
@@ -217,12 +217,13 @@ describe('ToggleButton', () => {
|
|
|
217
217
|
|
|
218
218
|
await user.click(button);
|
|
219
219
|
|
|
220
|
-
// The optimistic state flips immediately
|
|
221
|
-
// button is
|
|
220
|
+
// The optimistic state flips immediately and the spinner shows via
|
|
221
|
+
// aria-busy, but the button is never disabled — it stays clickable so the
|
|
222
|
+
// action can be interrupted by another click.
|
|
222
223
|
expect(pressedChangeAction).toHaveBeenCalledWith(true);
|
|
223
224
|
expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
225
|
+
expect(button).toHaveAttribute('aria-busy', 'true');
|
|
224
226
|
expect(button).not.toBeDisabled();
|
|
225
|
-
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
226
227
|
|
|
227
228
|
// Settle the action so the pending transition doesn't leak into later tests.
|
|
228
229
|
await act(async () => {
|
|
@@ -231,7 +232,7 @@ describe('ToggleButton', () => {
|
|
|
231
232
|
});
|
|
232
233
|
});
|
|
233
234
|
|
|
234
|
-
it('
|
|
235
|
+
it('clears the loading state once the action settles', async () => {
|
|
235
236
|
const user = userEvent.setup();
|
|
236
237
|
let resolveAction: (() => void) | undefined;
|
|
237
238
|
const pressedChangeAction = vi.fn(
|
|
@@ -253,18 +254,15 @@ describe('ToggleButton', () => {
|
|
|
253
254
|
const button = screen.getByRole('button', {name: 'Favorite'});
|
|
254
255
|
await user.click(button);
|
|
255
256
|
|
|
256
|
-
// The optimistic state shows immediately; the spinner is debounced and
|
|
257
|
-
// appears only after the action stays pending past the delay window.
|
|
258
|
-
expect(button).toHaveAttribute('aria-pressed', 'true');
|
|
259
|
-
await waitFor(() => expect(button).toBeDisabled());
|
|
260
257
|
expect(button).toHaveAttribute('aria-busy', 'true');
|
|
258
|
+
expect(button).not.toBeDisabled();
|
|
261
259
|
|
|
262
260
|
await act(async () => {
|
|
263
261
|
resolveAction?.();
|
|
264
262
|
await Promise.resolve();
|
|
265
263
|
});
|
|
266
|
-
expect(button).not.toBeDisabled();
|
|
267
264
|
expect(button).not.toHaveAttribute('aria-busy', 'true');
|
|
265
|
+
expect(button).not.toBeDisabled();
|
|
268
266
|
});
|
|
269
267
|
|
|
270
268
|
it('interrupts an in-flight action on re-click (true -> false -> true)', async () => {
|
|
@@ -290,9 +288,8 @@ describe('ToggleButton', () => {
|
|
|
290
288
|
const button = screen.getByRole('button', {name: 'Favorite'});
|
|
291
289
|
|
|
292
290
|
// Each click derives the next state from the optimistic (in-progress)
|
|
293
|
-
// value, so rapid clicks toggle rather than being dropped.
|
|
294
|
-
//
|
|
295
|
-
// interruptible.
|
|
291
|
+
// value, so rapid clicks toggle rather than being dropped. The button is
|
|
292
|
+
// never disabled while pending, so every click lands and interrupts.
|
|
296
293
|
await act(async () => {
|
|
297
294
|
fireEvent.click(button);
|
|
298
295
|
});
|
|
@@ -335,9 +332,33 @@ describe('ToggleButton', () => {
|
|
|
335
332
|
const button = screen.getByRole('button', {name: 'Favorite'});
|
|
336
333
|
await user.click(button);
|
|
337
334
|
|
|
338
|
-
expect(onPressedChange).toHaveBeenCalledWith(true);
|
|
335
|
+
expect(onPressedChange).toHaveBeenCalledWith(true, expect.anything());
|
|
339
336
|
expect(pressedChangeAction).toHaveBeenCalledWith(true);
|
|
340
337
|
});
|
|
338
|
+
|
|
339
|
+
it('skips pressedChangeAction when onPressedChange calls preventDefault', async () => {
|
|
340
|
+
const user = userEvent.setup();
|
|
341
|
+
const pressedChangeAction = vi.fn();
|
|
342
|
+
const onPressedChange = vi.fn(
|
|
343
|
+
(_next: boolean, event: MouseEvent<HTMLButtonElement>) => {
|
|
344
|
+
event.preventDefault();
|
|
345
|
+
},
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
render(
|
|
349
|
+
<ToggleButton
|
|
350
|
+
label="Favorite"
|
|
351
|
+
isPressed={false}
|
|
352
|
+
onPressedChange={onPressedChange}
|
|
353
|
+
pressedChangeAction={pressedChangeAction}
|
|
354
|
+
/>,
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
await user.click(screen.getByRole('button', {name: 'Favorite'}));
|
|
358
|
+
|
|
359
|
+
expect(onPressedChange).toHaveBeenCalledWith(true, expect.anything());
|
|
360
|
+
expect(pressedChangeAction).not.toHaveBeenCalled();
|
|
361
|
+
});
|
|
341
362
|
});
|
|
342
363
|
|
|
343
364
|
// =============================================================================
|
|
@@ -20,14 +20,7 @@
|
|
|
20
20
|
* - /packages/cli/templates/blocks/components/ToggleButton/ (showcase blocks)
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
import React, {
|
|
24
|
-
useCallback,
|
|
25
|
-
useEffect,
|
|
26
|
-
useOptimistic,
|
|
27
|
-
useState,
|
|
28
|
-
useTransition,
|
|
29
|
-
type ReactNode,
|
|
30
|
-
} from 'react';
|
|
23
|
+
import React, {useOptimistic, type ReactNode} from 'react';
|
|
31
24
|
import * as stylex from '@stylexjs/stylex';
|
|
32
25
|
import {colorVars, fontWeightVars} from '../theme/tokens.stylex';
|
|
33
26
|
|
|
@@ -36,37 +29,6 @@ import {useToggleButtonGroup} from './ToggleButtonGroup';
|
|
|
36
29
|
import type {BaseProps} from '../BaseProps';
|
|
37
30
|
import {themeProps} from '../utils/themeProps';
|
|
38
31
|
|
|
39
|
-
// =============================================================================
|
|
40
|
-
// Constants & helpers
|
|
41
|
-
// =============================================================================
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* The spinner only appears once the action has been pending for this long.
|
|
45
|
-
* A fast action shows the optimistic pressed state immediately with no spinner
|
|
46
|
-
* flash, and rapid re-clicks can interrupt the in-flight action before the
|
|
47
|
-
* button locks behind the spinner.
|
|
48
|
-
*/
|
|
49
|
-
const PENDING_SPINNER_DELAY_MS = 150;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Returns `true` only once `active` has stayed `true` for `delayMs`.
|
|
53
|
-
* Used to debounce the loading spinner so the optimistic state shows first.
|
|
54
|
-
*/
|
|
55
|
-
function useDelayed(active: boolean, delayMs: number): boolean {
|
|
56
|
-
const [delayed, setDelayed] = useState(false);
|
|
57
|
-
useEffect(() => {
|
|
58
|
-
if (!active) {
|
|
59
|
-
return undefined;
|
|
60
|
-
}
|
|
61
|
-
const timer = setTimeout(() => setDelayed(true), delayMs);
|
|
62
|
-
return () => {
|
|
63
|
-
clearTimeout(timer);
|
|
64
|
-
setDelayed(false);
|
|
65
|
-
};
|
|
66
|
-
}, [active, delayMs]);
|
|
67
|
-
return active && delayed;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
32
|
// =============================================================================
|
|
71
33
|
// Styles
|
|
72
34
|
// =============================================================================
|
|
@@ -122,23 +84,24 @@ export interface ToggleButtonProps extends BaseProps<HTMLButtonElement> {
|
|
|
122
84
|
isPressed?: boolean;
|
|
123
85
|
|
|
124
86
|
/**
|
|
125
|
-
* Called when the pressed state should change.
|
|
87
|
+
* Called when the pressed state should change. Receives the next pressed
|
|
88
|
+
* state and the originating click event. Call `event.preventDefault()` to
|
|
89
|
+
* opt out of running `pressedChangeAction` (e.g. to handle the toggle
|
|
90
|
+
* entirely in this callback).
|
|
126
91
|
* When used inside ToggleButtonGroup, this is handled by the group
|
|
127
92
|
* and this prop is ignored.
|
|
128
93
|
*/
|
|
129
|
-
onPressedChange?: (
|
|
94
|
+
onPressedChange?: (
|
|
95
|
+
isPressed: boolean,
|
|
96
|
+
event: React.MouseEvent<HTMLButtonElement>,
|
|
97
|
+
) => void;
|
|
130
98
|
|
|
131
99
|
/**
|
|
132
100
|
* Action handler for API- or navigation-backed toggles, run inside a
|
|
133
|
-
* transition. The button shows a loading spinner while the action
|
|
134
|
-
* pending — whether it returns a promise or synchronously triggers a
|
|
101
|
+
* transition by Button. The button shows a loading spinner while the action
|
|
102
|
+
* is pending — whether it returns a promise or synchronously triggers a
|
|
135
103
|
* suspending update (e.g. a router navigation that suspends on data).
|
|
136
104
|
*
|
|
137
|
-
* Because it runs in a transition, the toggle is *interruptible*: clicking
|
|
138
|
-
* again while an action is pending starts a new transition with the next
|
|
139
|
-
* optimistic state, so the action reflects the latest intent rather than
|
|
140
|
-
* being dropped.
|
|
141
|
-
*
|
|
142
105
|
* @example
|
|
143
106
|
* ```
|
|
144
107
|
* <ToggleButton
|
|
@@ -272,54 +235,52 @@ export function ToggleButton({
|
|
|
272
235
|
const size = sizeProp ?? group?.size ?? 'md';
|
|
273
236
|
const isDisabled = group?.isDisabled ?? isDisabledProp;
|
|
274
237
|
|
|
275
|
-
// Track the pressed state optimistically
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
//
|
|
238
|
+
// Track the pressed state optimistically so the button reflects the intended
|
|
239
|
+
// state immediately while an async action is pending. The optimistic update
|
|
240
|
+
// is applied inside Button's clickAction transition (below), satisfying
|
|
241
|
+
// React's "useOptimistic must run in a transition" rule.
|
|
279
242
|
const [optimisticPressed, setOptimisticPressed] =
|
|
280
243
|
useOptimistic(committedPressed);
|
|
281
244
|
const isPressed = optimisticPressed;
|
|
282
245
|
|
|
246
|
+
// Next state derives from the *optimistic* value, not the committed one, so a
|
|
247
|
+
// re-click while an action is pending reads the in-flight intent and toggles
|
|
248
|
+
// (true -> false -> true) rather than recomputing from the stale committed
|
|
249
|
+
// state. handleClick and clickAction share this so the callback and the
|
|
250
|
+
// optimistic update always agree within a single click.
|
|
251
|
+
const nextPressed = !isPressed;
|
|
252
|
+
|
|
283
253
|
const resolvedIcon = isPressed && pressedIcon ? pressedIcon : icon;
|
|
284
254
|
|
|
285
|
-
//
|
|
286
|
-
//
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
// which means a synchronous-but-suspending handler (e.g. a router navigation
|
|
290
|
-
// that suspends on data) also drives the pending state — not just promises.
|
|
291
|
-
const [isPending, startTransition] = useTransition();
|
|
292
|
-
// Debounce the spinner so a fast action shows the optimistic state without a
|
|
293
|
-
// spinner flash, and rapid re-clicks can interrupt before the button locks.
|
|
294
|
-
const showSpinner = useDelayed(isPending, PENDING_SPINNER_DELAY_MS);
|
|
295
|
-
const isLoadingState = isLoading || showSpinner;
|
|
296
|
-
|
|
297
|
-
const handleClick = useCallback(() => {
|
|
255
|
+
// Synchronous part of the toggle. Button calls onClick before clickAction and
|
|
256
|
+
// skips clickAction when the event is defaultPrevented, so calling
|
|
257
|
+
// preventDefault() inside onPressedChange opts out of pressedChangeAction.
|
|
258
|
+
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
298
259
|
if (isDisabled) {
|
|
299
260
|
return;
|
|
300
261
|
}
|
|
301
|
-
|
|
302
262
|
if (group && value != null) {
|
|
303
263
|
// Group mode delegates selection to the group; no async-action path.
|
|
304
264
|
group.toggle(value);
|
|
265
|
+
event.preventDefault();
|
|
305
266
|
return;
|
|
306
267
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
value
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
268
|
+
onPressedChangeProp?.(nextPressed, event);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Async part of the toggle, run inside Button's transition (so the optimistic
|
|
272
|
+
// update is valid and Button's isPending drives the pending spinner). Skipped
|
|
273
|
+
// automatically by Button when handleClick called preventDefault, and never
|
|
274
|
+
// wired in group mode (where there is no async action). Button is rendered
|
|
275
|
+
// interruptible, so it stays clickable while pending and a re-click starts a
|
|
276
|
+
// fresh transition that interrupts the previous one.
|
|
277
|
+
const clickAction =
|
|
278
|
+
group && value != null
|
|
279
|
+
? undefined
|
|
280
|
+
: async () => {
|
|
281
|
+
setOptimisticPressed(nextPressed);
|
|
282
|
+
await pressedChangeAction?.(nextPressed);
|
|
283
|
+
};
|
|
323
284
|
|
|
324
285
|
// isIconOnly prop is the source of truth for icon-only rendering.
|
|
325
286
|
const labelContent =
|
|
@@ -352,7 +313,8 @@ export function ToggleButton({
|
|
|
352
313
|
variant="ghost"
|
|
353
314
|
size={size}
|
|
354
315
|
isDisabled={isDisabled}
|
|
355
|
-
isLoading={
|
|
316
|
+
isLoading={isLoading}
|
|
317
|
+
isInterruptible
|
|
356
318
|
isIconOnly={isIconOnly}
|
|
357
319
|
aria-pressed={isPressed}
|
|
358
320
|
icon={resolvedIcon}
|
|
@@ -363,6 +325,7 @@ export function ToggleButton({
|
|
|
363
325
|
xstyle={[isPressed ? pressedStyles.background : undefined, xstyle]}
|
|
364
326
|
style={style}
|
|
365
327
|
onClick={handleClick}
|
|
328
|
+
clickAction={clickAction}
|
|
366
329
|
{...props}>
|
|
367
330
|
{labelContent}
|
|
368
331
|
</Button>
|
|
@@ -70,6 +70,12 @@ export const docs = {
|
|
|
70
70
|
description: 'Disables the input and all token interactions.',
|
|
71
71
|
default: 'false',
|
|
72
72
|
},
|
|
73
|
+
{
|
|
74
|
+
name: 'disabledMessage',
|
|
75
|
+
type: 'string',
|
|
76
|
+
description:
|
|
77
|
+
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
|
|
78
|
+
},
|
|
73
79
|
{
|
|
74
80
|
name: 'status',
|
|
75
81
|
type: 'InputStatus',
|
|
@@ -191,6 +197,7 @@ export const docs = {
|
|
|
191
197
|
{guidance: false, description: 'Don\u2019t use Tokenizer for single-item selection \u2014 use Typeahead instead. Tokenizer is for building sets of two or more items.'},
|
|
192
198
|
{guidance: false, description: 'Avoid applying custom colors to individual tokens inside a Tokenizer \u2014 use the default token style for visual consistency across the set.'},
|
|
193
199
|
{guidance: false, description: 'Don\u2019t hide the label \u2014 every Tokenizer needs a visible label so users understand what they are selecting. Use isLabelHidden only when surrounding context makes the purpose obvious.'},
|
|
200
|
+
{guidance: false, description: 'Wrap a disabled Tokenizer in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
|
|
194
201
|
],
|
|
195
202
|
anatomy: [
|
|
196
203
|
{name: 'Label', required: true, description: 'The visible text above the input describing what the user is selecting. Also used as the accessible name.'},
|
|
@@ -270,6 +277,12 @@ export const docsZh = {
|
|
|
270
277
|
description: '\u7981\u7528\u8f93\u5165\u6846\u548c\u6240\u6709\u6807\u8bb0\u4ea4\u4e92\u3002',
|
|
271
278
|
default: 'false',
|
|
272
279
|
},
|
|
280
|
+
{
|
|
281
|
+
name: 'disabledMessage',
|
|
282
|
+
type: 'string',
|
|
283
|
+
description:
|
|
284
|
+
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
|
|
285
|
+
},
|
|
273
286
|
{
|
|
274
287
|
name: 'status',
|
|
275
288
|
type: 'InputStatus',
|
|
@@ -380,6 +393,7 @@ export const docsZh = {
|
|
|
380
393
|
{guidance: false, description: 'Don\u2019t use Tokenizer for single-item selection \u2014 use Typeahead instead. Tokenizer is for building sets of two or more items.'},
|
|
381
394
|
{guidance: false, description: 'Avoid applying custom colors to individual tokens inside a Tokenizer \u2014 use the default token style for visual consistency across the set.'},
|
|
382
395
|
{guidance: false, description: 'Don\u2019t hide the label \u2014 every Tokenizer needs a visible label so users understand what they are selecting. Use isLabelHidden only when surrounding context makes the purpose obvious.'},
|
|
396
|
+
{guidance: false, description: 'Wrap a disabled Tokenizer in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
|
|
383
397
|
],
|
|
384
398
|
anatomy: [
|
|
385
399
|
{name: 'Label', required: true, description: 'The visible text above the input describing what the user is selecting. Also used as the accessible name.'},
|
|
@@ -406,6 +420,7 @@ export const docsDense = {
|
|
|
406
420
|
{guidance: false, description: 'Don\u2019t use for single-item selection \u2014 use Typeahead instead.'},
|
|
407
421
|
{guidance: false, description: 'Avoid custom token colors \u2014 default style for consistency.'},
|
|
408
422
|
{guidance: false, description: 'Don\u2019t hide the label unless context makes purpose obvious.'},
|
|
423
|
+
{guidance: false, description: 'Wrap a disabled Tokenizer in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.'},
|
|
409
424
|
],
|
|
410
425
|
},
|
|
411
426
|
propDescriptions: {
|