@astryxdesign/core 0.1.2 → 0.1.3
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 +165 -0
- package/README.md +12 -12
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- 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.map +1 -1
- package/dist/Button/Button.js +2 -4
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +0 -1
- 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/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +0 -1
- 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 +8 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -3
- 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/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +0 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +9 -5
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +51 -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 +167 -99
- 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/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 +32 -6
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +16 -6
- 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/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +3 -3
- 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 +33 -1
- 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 +10 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -9
- 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 +16 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +18 -7
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -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 +27 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +141 -42
- 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 +15 -1
- package/dist/Popover/Popover.d.ts +18 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +5 -2
- package/dist/Popover/usePopover.d.ts +38 -3
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +24 -9
- 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 +24 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +122 -43
- 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/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +2 -0
- 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 +36 -9
- 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 +87 -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 +11 -8
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +10 -1
- 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/index.d.ts +2 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -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/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 +66 -0
- package/dist/Table/types.d.ts.map +1 -1
- 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 +147 -76
- 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 +131 -3
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +26 -4
- 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 +56 -9
- package/dist/TopNav/TopNavHeading.d.ts +7 -1
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +8 -0
- 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 +13 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +69 -6
- package/dist/Typeahead/Typeahead.d.ts +26 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +65 -29
- 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 +18 -0
- package/dist/astryx.umd.js +55 -55
- package/dist/astryx.umd.js.map +4 -4
- 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/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/docs.mjs +2 -2
- package/package.json +12 -8
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.tsx +3 -16
- package/src/ButtonGroup/ButtonGroup.test.tsx +9 -9
- package/src/ButtonGroup/ButtonGroup.tsx +0 -1
- 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/ChatComposerInput.test.tsx +26 -7
- package/src/Chat/ChatComposerInput.tsx +0 -1
- package/src/Chat/ChatDictationButton.doc.mjs +1 -1
- 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 +22 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +10 -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 +192 -26
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/CheckboxList/CheckboxListItem.tsx +0 -3
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +121 -0
- package/src/Citation/Citation.tsx +15 -3
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +63 -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 +286 -56
- package/src/DateInput/DateInput.test.tsx +248 -2
- package/src/DateInput/DateInput.tsx +196 -100
- 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/Field/Field.doc.mjs +59 -18
- 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 +17 -4
- package/src/Grid/Grid.test.tsx +43 -30
- package/src/Grid/Grid.tsx +38 -3
- package/src/Icon/Icon.doc.mjs +3 -3
- package/src/InputGroup/InputGroup.doc.mjs +111 -23
- package/src/InputGroup/InputGroup.test.tsx +257 -60
- package/src/InputGroup/InputGroup.tsx +23 -5
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/groupStyles.ts +7 -1
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +35 -3
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +5 -0
- package/src/Layer/useLayer.test.tsx +111 -0
- package/src/Layer/useLayer.tsx +90 -9
- 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 -0
- 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 +50 -0
- package/src/Link/Link.tsx +39 -4
- package/src/Markdown/Markdown.test.tsx +11 -0
- package/src/Markdown/Markdown.tsx +7 -0
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +30 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +194 -48
- 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/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +117 -5
- package/src/Pagination/Pagination.tsx +21 -1
- package/src/Popover/Popover.doc.mjs +26 -0
- package/src/Popover/Popover.test.tsx +121 -0
- package/src/Popover/Popover.tsx +23 -2
- package/src/Popover/usePopover.doc.mjs +9 -3
- package/src/Popover/usePopover.tsx +70 -12
- 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 +34 -26
- 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/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 +1 -1
- package/src/Selector/Selector.doc.mjs +26 -0
- package/src/Selector/Selector.test.tsx +387 -15
- package/src/Selector/Selector.tsx +175 -67
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +48 -0
- package/src/SideNav/SideNavHeading.tsx +8 -2
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +15 -0
- package/src/Slider/Slider.test.tsx +155 -2
- package/src/Slider/Slider.tsx +53 -5
- 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 +6 -0
- package/src/TabList/TabList.test.tsx +251 -0
- package/src/TabList/TabList.tsx +103 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +21 -17
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.test.tsx +10 -0
- package/src/Table/Table.tsx +8 -0
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/index.ts +3 -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/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +74 -0
- package/src/Table/useTableColumnResize.doc.mjs +3 -3
- package/src/Table/useTableStickyColumns.doc.mjs +2 -2
- package/src/Text/Text.doc.mjs +18 -18
- 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/Thumbnail/Thumbnail.doc.mjs +4 -4
- package/src/TimeInput/TimeInput.doc.mjs +340 -60
- package/src/TimeInput/TimeInput.test.tsx +255 -7
- package/src/TimeInput/TimeInput.tsx +176 -70
- package/src/Timestamp/Timestamp.doc.mjs +19 -19
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +214 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/Tokenizer/Tokenizer.doc.mjs +29 -14
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +37 -1
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +68 -0
- package/src/Tooltip/useTooltip.tsx +55 -8
- package/src/TopNav/TopNav.test.tsx +50 -0
- package/src/TopNav/TopNavHeading.tsx +17 -1
- 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 +93 -9
- package/src/Typeahead/Typeahead.doc.mjs +141 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +105 -33
- 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/docs-script.test.mjs +50 -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/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 +10 -5
- 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
|
@@ -9,41 +9,56 @@
|
|
|
9
9
|
* SYNC: When CheckboxInput.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
13
|
+
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {CheckboxInput} from './CheckboxInput';
|
|
16
16
|
|
|
17
|
+
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
18
|
+
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
21
|
+
this.setAttribute('popover-open', '');
|
|
22
|
+
const event = new Event('toggle', {bubbles: false});
|
|
23
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
24
|
+
this.dispatchEvent(event);
|
|
25
|
+
});
|
|
26
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
27
|
+
this.removeAttribute('popover-open');
|
|
28
|
+
const event = new Event('toggle', {bubbles: false});
|
|
29
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
30
|
+
this.dispatchEvent(event);
|
|
31
|
+
});
|
|
32
|
+
const originalMatches = HTMLElement.prototype.matches;
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
(HTMLElement.prototype as any).matches = function (
|
|
35
|
+
selector: string,
|
|
36
|
+
): boolean {
|
|
37
|
+
if (selector === ':popover-open') {
|
|
38
|
+
return this.hasAttribute('popover-open');
|
|
39
|
+
}
|
|
40
|
+
return originalMatches.call(this, selector);
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
17
44
|
describe('CheckboxInput', () => {
|
|
18
45
|
it('renders with label', () => {
|
|
19
46
|
render(
|
|
20
|
-
<CheckboxInput
|
|
21
|
-
label="Accept terms"
|
|
22
|
-
value={false}
|
|
23
|
-
onChange={() => {}}
|
|
24
|
-
/>,
|
|
47
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
25
48
|
);
|
|
26
49
|
expect(screen.getByLabelText('Accept terms')).toBeInTheDocument();
|
|
27
50
|
});
|
|
28
51
|
|
|
29
52
|
it('renders as unchecked by default', () => {
|
|
30
53
|
render(
|
|
31
|
-
<CheckboxInput
|
|
32
|
-
label="Accept terms"
|
|
33
|
-
value={false}
|
|
34
|
-
onChange={() => {}}
|
|
35
|
-
/>,
|
|
54
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
36
55
|
);
|
|
37
56
|
expect(screen.getByRole('checkbox')).not.toBeChecked();
|
|
38
57
|
});
|
|
39
58
|
|
|
40
59
|
it('renders as checked when value prop is true', () => {
|
|
41
60
|
render(
|
|
42
|
-
<CheckboxInput
|
|
43
|
-
label="Accept terms"
|
|
44
|
-
value={true}
|
|
45
|
-
onChange={() => {}}
|
|
46
|
-
/>,
|
|
61
|
+
<CheckboxInput label="Accept terms" value={true} onChange={() => {}} />,
|
|
47
62
|
);
|
|
48
63
|
expect(screen.getByRole('checkbox')).toBeChecked();
|
|
49
64
|
});
|
|
@@ -182,11 +197,7 @@ describe('CheckboxInput', () => {
|
|
|
182
197
|
|
|
183
198
|
it('shows label visually by default', () => {
|
|
184
199
|
render(
|
|
185
|
-
<CheckboxInput
|
|
186
|
-
label="Accept terms"
|
|
187
|
-
value={false}
|
|
188
|
-
onChange={() => {}}
|
|
189
|
-
/>,
|
|
200
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
190
201
|
);
|
|
191
202
|
const label = screen.getByText('Accept terms');
|
|
192
203
|
expect(label).toBeVisible();
|
|
@@ -204,7 +215,7 @@ describe('CheckboxInput', () => {
|
|
|
204
215
|
expect(screen.getByRole('checkbox')).toHaveAttribute('aria-busy', 'true');
|
|
205
216
|
});
|
|
206
217
|
|
|
207
|
-
it('
|
|
218
|
+
it('exposes indeterminate state via the native indeterminate property', () => {
|
|
208
219
|
render(
|
|
209
220
|
<CheckboxInput
|
|
210
221
|
label="Select all"
|
|
@@ -212,10 +223,15 @@ describe('CheckboxInput', () => {
|
|
|
212
223
|
onChange={() => {}}
|
|
213
224
|
/>,
|
|
214
225
|
);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
)
|
|
226
|
+
const checkbox = screen.getByRole('checkbox');
|
|
227
|
+
// Native checkboxes expose mixed state through the DOM indeterminate
|
|
228
|
+
// property, which browsers map to aria-checked="mixed". A redundant
|
|
229
|
+
// aria-checked attribute is intentionally NOT set (forms-16).
|
|
230
|
+
expect(checkbox).toBeInstanceOf(HTMLInputElement);
|
|
231
|
+
if (checkbox instanceof HTMLInputElement) {
|
|
232
|
+
expect(checkbox.indeterminate).toBe(true);
|
|
233
|
+
}
|
|
234
|
+
expect(checkbox).not.toHaveAttribute('aria-checked');
|
|
219
235
|
});
|
|
220
236
|
|
|
221
237
|
it('renders semantic labelIcon names as icons', () => {
|
|
@@ -247,4 +263,133 @@ describe('CheckboxInput', () => {
|
|
|
247
263
|
'true',
|
|
248
264
|
);
|
|
249
265
|
});
|
|
266
|
+
|
|
267
|
+
describe('disabledMessage', () => {
|
|
268
|
+
const h = {hidden: true} as const;
|
|
269
|
+
|
|
270
|
+
function getRow(): HTMLElement {
|
|
271
|
+
return screen.getByRole('checkbox', h).closest('div')!.parentElement!;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
275
|
+
render(
|
|
276
|
+
<CheckboxInput
|
|
277
|
+
label="Accept terms"
|
|
278
|
+
value={false}
|
|
279
|
+
onChange={() => {}}
|
|
280
|
+
isDisabled
|
|
281
|
+
disabledMessage="Terms are managed by your administrator"
|
|
282
|
+
/>,
|
|
283
|
+
);
|
|
284
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
285
|
+
expect(tooltip).toHaveTextContent(
|
|
286
|
+
'Terms are managed by your administrator',
|
|
287
|
+
);
|
|
288
|
+
fireEvent.mouseEnter(getRow());
|
|
289
|
+
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
290
|
+
fireEvent.mouseLeave(getRow());
|
|
291
|
+
await waitFor(() => expect(tooltip).not.toHaveAttribute('popover-open'));
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it('shows the reason tooltip on keyboard focus', async () => {
|
|
295
|
+
const user = userEvent.setup();
|
|
296
|
+
render(
|
|
297
|
+
<CheckboxInput
|
|
298
|
+
label="Accept terms"
|
|
299
|
+
value={false}
|
|
300
|
+
onChange={() => {}}
|
|
301
|
+
isDisabled
|
|
302
|
+
disabledMessage="Terms are managed by your administrator"
|
|
303
|
+
/>,
|
|
304
|
+
);
|
|
305
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
306
|
+
await user.tab();
|
|
307
|
+
expect(screen.getByRole('checkbox', h)).toHaveFocus();
|
|
308
|
+
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('does not render a tooltip when not disabled', () => {
|
|
312
|
+
render(
|
|
313
|
+
<CheckboxInput
|
|
314
|
+
label="Accept terms"
|
|
315
|
+
value={false}
|
|
316
|
+
onChange={() => {}}
|
|
317
|
+
disabledMessage="Terms are managed by your administrator"
|
|
318
|
+
/>,
|
|
319
|
+
);
|
|
320
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('does not render a tooltip when disabled without a reason', () => {
|
|
324
|
+
render(
|
|
325
|
+
<CheckboxInput
|
|
326
|
+
label="Accept terms"
|
|
327
|
+
value={false}
|
|
328
|
+
onChange={() => {}}
|
|
329
|
+
isDisabled
|
|
330
|
+
/>,
|
|
331
|
+
);
|
|
332
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('keeps the checkbox focusable via aria-disabled when a reason is provided', () => {
|
|
336
|
+
render(
|
|
337
|
+
<CheckboxInput
|
|
338
|
+
label="Accept terms"
|
|
339
|
+
value={false}
|
|
340
|
+
onChange={() => {}}
|
|
341
|
+
isDisabled
|
|
342
|
+
disabledMessage="Terms are managed by your administrator"
|
|
343
|
+
/>,
|
|
344
|
+
);
|
|
345
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
346
|
+
expect(checkbox).not.toBeDisabled();
|
|
347
|
+
expect(checkbox).toHaveAttribute('aria-disabled', 'true');
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('links the reason tooltip via aria-describedby', () => {
|
|
351
|
+
render(
|
|
352
|
+
<CheckboxInput
|
|
353
|
+
label="Accept terms"
|
|
354
|
+
value={false}
|
|
355
|
+
onChange={() => {}}
|
|
356
|
+
isDisabled
|
|
357
|
+
disabledMessage="Terms are managed by your administrator"
|
|
358
|
+
/>,
|
|
359
|
+
);
|
|
360
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
361
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
362
|
+
expect(checkbox.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
it('blocks toggling while focusable-disabled', async () => {
|
|
366
|
+
const user = userEvent.setup();
|
|
367
|
+
const onChange = vi.fn();
|
|
368
|
+
render(
|
|
369
|
+
<CheckboxInput
|
|
370
|
+
label="Accept terms"
|
|
371
|
+
value={false}
|
|
372
|
+
onChange={onChange}
|
|
373
|
+
isDisabled
|
|
374
|
+
disabledMessage="Terms are managed by your administrator"
|
|
375
|
+
/>,
|
|
376
|
+
);
|
|
377
|
+
const checkbox = screen.getByRole('checkbox', h);
|
|
378
|
+
await user.click(checkbox);
|
|
379
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
380
|
+
expect(checkbox).not.toBeChecked();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('remains natively disabled when disabled without a reason', () => {
|
|
384
|
+
render(
|
|
385
|
+
<CheckboxInput
|
|
386
|
+
label="Accept terms"
|
|
387
|
+
value={false}
|
|
388
|
+
onChange={() => {}}
|
|
389
|
+
isDisabled
|
|
390
|
+
/>,
|
|
391
|
+
);
|
|
392
|
+
expect(screen.getByRole('checkbox')).toBeDisabled();
|
|
393
|
+
});
|
|
394
|
+
});
|
|
250
395
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file CheckboxInput.tsx
|
|
7
|
-
* @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus
|
|
7
|
+
* @input Uses React, useId, ChangeEvent, FieldLabel, FieldStatus, IconType, InputStatus, useTooltip
|
|
8
8
|
* @output Exports CheckboxInput component, CheckboxInputProps
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by CheckboxInput.test.tsx
|
|
10
10
|
*
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import {
|
|
20
20
|
useId,
|
|
21
21
|
useCallback,
|
|
22
|
+
use,
|
|
22
23
|
useOptimistic,
|
|
23
24
|
useTransition,
|
|
24
25
|
type ChangeEvent,
|
|
@@ -44,9 +45,11 @@ import {FieldStatus} from '../FieldStatus/FieldStatus';
|
|
|
44
45
|
import type {IconType} from '../Icon';
|
|
45
46
|
import type {InputStatus} from '../Field/types';
|
|
46
47
|
import {Spinner} from '../Spinner';
|
|
48
|
+
import {useTooltip} from '../Tooltip';
|
|
47
49
|
import {mergeProps, mergeRefs} from '../utils';
|
|
48
50
|
import {checkboxScope} from './checkbox.markers.stylex';
|
|
49
51
|
import {themeProps} from '../utils/themeProps';
|
|
52
|
+
import {CheckboxListContext} from '../CheckboxList/CheckboxListContext';
|
|
50
53
|
|
|
51
54
|
const styles = stylex.create({
|
|
52
55
|
container: {
|
|
@@ -269,6 +272,27 @@ export interface CheckboxInputProps extends Omit<BaseProps, 'onChange'> {
|
|
|
269
272
|
* @default false
|
|
270
273
|
*/
|
|
271
274
|
isDisabled?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Explains why the checkbox is disabled. When set together with
|
|
277
|
+
* `isDisabled`, the checkbox shows a tooltip with this text on hover and
|
|
278
|
+
* keyboard focus, and the control stays focusable (via `aria-disabled`) so
|
|
279
|
+
* the reason is discoverable by keyboard and assistive technology.
|
|
280
|
+
* Activation stays blocked.
|
|
281
|
+
*
|
|
282
|
+
* Use this instead of wrapping a disabled checkbox in `Tooltip` — disabled
|
|
283
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```
|
|
287
|
+
* <CheckboxInput
|
|
288
|
+
* label="Accept terms"
|
|
289
|
+
* value={accepted}
|
|
290
|
+
* isDisabled
|
|
291
|
+
* disabledMessage="Terms are managed by your administrator"
|
|
292
|
+
* />
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
disabledMessage?: string;
|
|
272
296
|
/**
|
|
273
297
|
* Whether the checkbox is read-only.
|
|
274
298
|
* Displays the current state at full opacity but prevents interaction.
|
|
@@ -350,6 +374,7 @@ export function CheckboxInput({
|
|
|
350
374
|
isLoading = false,
|
|
351
375
|
value,
|
|
352
376
|
isDisabled = false,
|
|
377
|
+
disabledMessage,
|
|
353
378
|
isReadOnly = false,
|
|
354
379
|
isOptional = false,
|
|
355
380
|
isRequired = false,
|
|
@@ -372,11 +397,37 @@ export function CheckboxInput({
|
|
|
372
397
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
373
398
|
const isBusy = isLoading || optimisticValue !== value;
|
|
374
399
|
|
|
400
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
401
|
+
// tooltip listeners attach to the checkbox row (which already exists) and the
|
|
402
|
+
// native checkbox stays perceivable via aria-disabled instead of the disabled
|
|
403
|
+
// attribute. Value mutation is blocked by the isDisabled guard in onChange.
|
|
404
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
405
|
+
// Keep the native checkbox focusable via aria-disabled either when it renders
|
|
406
|
+
// its own reason tooltip, or when it sits in a CheckboxList whose whole-group
|
|
407
|
+
// `disabledMessage` (shown on the group container) needs each checkbox to
|
|
408
|
+
// stay keyboard-perceivable. The group signals this through context rather
|
|
409
|
+
// than a public prop.
|
|
410
|
+
const checkboxListContext = use(CheckboxListContext);
|
|
411
|
+
const isFocusableDisabled =
|
|
412
|
+
isDisabled &&
|
|
413
|
+
(showsDisabledMessage ||
|
|
414
|
+
(checkboxListContext?.hasDisabledMessage ?? false));
|
|
415
|
+
const disabledMessageTooltip = useTooltip({
|
|
416
|
+
placement: 'above',
|
|
417
|
+
// The container row is not naturally focusable; focusin bubbles up from the
|
|
418
|
+
// native checkbox, so always attach focus listeners.
|
|
419
|
+
focusTrigger: 'always',
|
|
420
|
+
isEnabled: showsDisabledMessage,
|
|
421
|
+
});
|
|
422
|
+
|
|
375
423
|
const isIndeterminate = optimisticValue === 'indeterminate';
|
|
376
424
|
const isChecked = optimisticValue === true;
|
|
377
425
|
const isCheckedOrIndeterminate = isChecked || isIndeterminate;
|
|
378
426
|
|
|
379
|
-
// Sync the native indeterminate DOM property (can't be set via JSX
|
|
427
|
+
// Sync the native indeterminate DOM property (can't be set via JSX
|
|
428
|
+
// attribute). On a native checkbox this is the authoritative way to expose
|
|
429
|
+
// the mixed state — a separate aria-checked="mixed" would be redundant and
|
|
430
|
+
// can desync from / override the native state (forms-16), so it is omitted.
|
|
380
431
|
const indeterminateRef = useCallback(
|
|
381
432
|
(el: HTMLInputElement | null) => {
|
|
382
433
|
if (el) {
|
|
@@ -395,6 +446,9 @@ export function CheckboxInput({
|
|
|
395
446
|
if (status?.message) {
|
|
396
447
|
describedByParts.push(statusMessageID);
|
|
397
448
|
}
|
|
449
|
+
if (showsDisabledMessage) {
|
|
450
|
+
describedByParts.push(disabledMessageTooltip.describedBy);
|
|
451
|
+
}
|
|
398
452
|
const ariaDescribedBy =
|
|
399
453
|
describedByParts.length > 0 ? describedByParts.join(' ') : undefined;
|
|
400
454
|
|
|
@@ -407,6 +461,15 @@ export function CheckboxInput({
|
|
|
407
461
|
style,
|
|
408
462
|
)}>
|
|
409
463
|
<div
|
|
464
|
+
ref={el => {
|
|
465
|
+
// Interaction (hover/focus) listeners for the disabled-message
|
|
466
|
+
// tooltip attach to the whole row for a larger trigger target;
|
|
467
|
+
// positioning anchors on the checkbox itself (below) so the tooltip
|
|
468
|
+
// appears next to the control, not the far edge of the row.
|
|
469
|
+
// Handlers are gated internally by isEnabled, so attaching
|
|
470
|
+
// unconditionally is safe.
|
|
471
|
+
disabledMessageTooltip.interactionRef(el);
|
|
472
|
+
}}
|
|
410
473
|
{...stylex.props(
|
|
411
474
|
styles.container,
|
|
412
475
|
isLabelHidden && styles.containerLabelHidden,
|
|
@@ -414,15 +477,23 @@ export function CheckboxInput({
|
|
|
414
477
|
)}>
|
|
415
478
|
<div {...stylex.props(styles.checkboxWrapper, wrapperSizeStyles[size])}>
|
|
416
479
|
<input
|
|
417
|
-
ref={mergeRefs(
|
|
480
|
+
ref={mergeRefs(
|
|
481
|
+
ref,
|
|
482
|
+
indeterminateRef,
|
|
483
|
+
disabledMessageTooltip.positionRef,
|
|
484
|
+
)}
|
|
418
485
|
id={id}
|
|
419
486
|
type="checkbox"
|
|
420
487
|
checked={isChecked}
|
|
421
|
-
|
|
488
|
+
// With a disabledMessage the checkbox keeps focusability via
|
|
489
|
+
// aria-disabled so the reason is focus-discoverable; toggling is
|
|
490
|
+
// still blocked by the isDisabled guard in onChange below.
|
|
491
|
+
disabled={isDisabled && !isFocusableDisabled}
|
|
492
|
+
aria-disabled={isFocusableDisabled ? 'true' : undefined}
|
|
422
493
|
readOnly={isReadOnly}
|
|
423
494
|
required={isRequired}
|
|
424
495
|
onChange={e => {
|
|
425
|
-
if (isBusy || isReadOnly) {
|
|
496
|
+
if (isDisabled || isBusy || isReadOnly) {
|
|
426
497
|
return;
|
|
427
498
|
}
|
|
428
499
|
const checked = e.target.checked;
|
|
@@ -436,7 +507,6 @@ export function CheckboxInput({
|
|
|
436
507
|
}}
|
|
437
508
|
onFocus={onFocus}
|
|
438
509
|
onBlur={onBlur}
|
|
439
|
-
aria-checked={isIndeterminate ? 'mixed' : undefined}
|
|
440
510
|
aria-readonly={isReadOnly || undefined}
|
|
441
511
|
aria-describedby={ariaDescribedBy}
|
|
442
512
|
aria-invalid={status?.type === 'error' ? true : undefined}
|
|
@@ -525,6 +595,8 @@ export function CheckboxInput({
|
|
|
525
595
|
variant="detached"
|
|
526
596
|
/>
|
|
527
597
|
)}
|
|
598
|
+
{showsDisabledMessage &&
|
|
599
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
528
600
|
</div>
|
|
529
601
|
);
|
|
530
602
|
}
|
|
@@ -77,6 +77,12 @@ export const docs = {
|
|
|
77
77
|
description: 'Whether all checkbox items are disabled.',
|
|
78
78
|
default: 'false',
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
name: 'disabledMessage',
|
|
82
|
+
type: 'string',
|
|
83
|
+
description:
|
|
84
|
+
'Explains why the group is disabled. Applies to the whole-group disabled state (isDisabled), not per item. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the checkboxes focusable via aria-disabled (toggling stays blocked). Use this instead of wrapping a disabled CheckboxList in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
|
|
85
|
+
},
|
|
80
86
|
{
|
|
81
87
|
name: 'status',
|
|
82
88
|
type: 'InputStatus',
|
|
@@ -99,6 +105,7 @@ export const docs = {
|
|
|
99
105
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
100
106
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
101
107
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
108
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
102
109
|
],
|
|
103
110
|
},
|
|
104
111
|
};
|
|
@@ -113,6 +120,7 @@ export const docsZh = {
|
|
|
113
120
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
114
121
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
115
122
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
123
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
116
124
|
],
|
|
117
125
|
},
|
|
118
126
|
};
|
|
@@ -129,6 +137,7 @@ export const docsDense = {
|
|
|
129
137
|
{ guidance: true, description: 'Write a group label that says what the choices represent: "Export formats" tells users more than "Options".' },
|
|
130
138
|
{ guidance: false, description: 'Show a CheckboxList when the user can only pick one thing; that is what RadioList is for.' },
|
|
131
139
|
{ guidance: false, description: 'Put buttons or links inside the trailing slot (endContent); the whole row is already tappable, so a nested button creates two competing click targets.' },
|
|
140
|
+
{ guidance: false, description: 'Wrap a disabled CheckboxList in Tooltip to explain why it is disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead.' },
|
|
132
141
|
],
|
|
133
142
|
},
|
|
134
143
|
};
|