@astryxdesign/core 0.1.2 → 0.1.3-canary.6d57c8d
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
|
@@ -10,12 +10,43 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {useState} from 'react';
|
|
13
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
14
|
-
import {render, screen, fireEvent} from '@testing-library/react';
|
|
13
|
+
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
14
|
+
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
15
15
|
import userEvent from '@testing-library/user-event';
|
|
16
16
|
import {MagnifyingGlassIcon} from '@heroicons/react/24/outline';
|
|
17
17
|
import {TextArea} from './TextArea';
|
|
18
18
|
|
|
19
|
+
// Mock showPopover/hidePopover since jsdom does not implement them. Used by the
|
|
20
|
+
// disabledMessage tooltip.
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
23
|
+
this.setAttribute('popover-open', '');
|
|
24
|
+
const event = new Event('toggle', {bubbles: false});
|
|
25
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
26
|
+
this.dispatchEvent(event);
|
|
27
|
+
});
|
|
28
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
29
|
+
this.removeAttribute('popover-open');
|
|
30
|
+
const event = new Event('toggle', {bubbles: false});
|
|
31
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
32
|
+
this.dispatchEvent(event);
|
|
33
|
+
});
|
|
34
|
+
const originalMatches = HTMLElement.prototype.matches;
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
(HTMLElement.prototype as any).matches = function (
|
|
37
|
+
selector: string,
|
|
38
|
+
): boolean {
|
|
39
|
+
if (selector === ':popover-open') {
|
|
40
|
+
return this.hasAttribute('popover-open');
|
|
41
|
+
}
|
|
42
|
+
return originalMatches.call(this, selector);
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// jsdom popover content is in the DOM but may not be "visible" in the
|
|
47
|
+
// accessibility tree. Use hidden: true to find it.
|
|
48
|
+
const h = {hidden: true} as const;
|
|
49
|
+
|
|
19
50
|
describe('TextArea', () => {
|
|
20
51
|
it('renders with label', () => {
|
|
21
52
|
render(<TextArea label="Description" value="" onChange={() => {}} />);
|
|
@@ -39,9 +70,7 @@ describe('TextArea', () => {
|
|
|
39
70
|
it('calls onChange with value and event when typing', async () => {
|
|
40
71
|
const user = userEvent.setup();
|
|
41
72
|
const handleChange = vi.fn();
|
|
42
|
-
render(
|
|
43
|
-
<TextArea label="Description" value="" onChange={handleChange} />,
|
|
44
|
-
);
|
|
73
|
+
render(<TextArea label="Description" value="" onChange={handleChange} />);
|
|
45
74
|
|
|
46
75
|
const textarea = screen.getByRole('textbox');
|
|
47
76
|
await user.type(textarea, 'Hi');
|
|
@@ -73,24 +102,14 @@ describe('TextArea', () => {
|
|
|
73
102
|
it('forwards ref correctly', () => {
|
|
74
103
|
const ref = vi.fn();
|
|
75
104
|
render(
|
|
76
|
-
<TextArea
|
|
77
|
-
ref={ref}
|
|
78
|
-
label="Description"
|
|
79
|
-
value=""
|
|
80
|
-
onChange={() => {}}
|
|
81
|
-
/>,
|
|
105
|
+
<TextArea ref={ref} label="Description" value="" onChange={() => {}} />,
|
|
82
106
|
);
|
|
83
107
|
expect(ref).toHaveBeenCalledWith(expect.any(HTMLTextAreaElement));
|
|
84
108
|
});
|
|
85
109
|
|
|
86
110
|
it('visually hides label when isLabelHidden is true', () => {
|
|
87
111
|
render(
|
|
88
|
-
<TextArea
|
|
89
|
-
label="Comments"
|
|
90
|
-
isLabelHidden
|
|
91
|
-
value=""
|
|
92
|
-
onChange={() => {}}
|
|
93
|
-
/>,
|
|
112
|
+
<TextArea label="Comments" isLabelHidden value="" onChange={() => {}} />,
|
|
94
113
|
);
|
|
95
114
|
const label = screen.getByText('Comments');
|
|
96
115
|
expect(label).toBeInTheDocument();
|
|
@@ -133,12 +152,7 @@ describe('TextArea', () => {
|
|
|
133
152
|
|
|
134
153
|
it('is disabled when isDisabled is true', () => {
|
|
135
154
|
render(
|
|
136
|
-
<TextArea
|
|
137
|
-
label="Description"
|
|
138
|
-
isDisabled
|
|
139
|
-
value=""
|
|
140
|
-
onChange={() => {}}
|
|
141
|
-
/>,
|
|
155
|
+
<TextArea label="Description" isDisabled value="" onChange={() => {}} />,
|
|
142
156
|
);
|
|
143
157
|
expect(screen.getByRole('textbox')).toBeDisabled();
|
|
144
158
|
});
|
|
@@ -150,12 +164,7 @@ describe('TextArea', () => {
|
|
|
150
164
|
|
|
151
165
|
it('shows aria-busy when isLoading is true', () => {
|
|
152
166
|
render(
|
|
153
|
-
<TextArea
|
|
154
|
-
label="Description"
|
|
155
|
-
isLoading
|
|
156
|
-
value=""
|
|
157
|
-
onChange={() => {}}
|
|
158
|
-
/>,
|
|
167
|
+
<TextArea label="Description" isLoading value="" onChange={() => {}} />,
|
|
159
168
|
);
|
|
160
169
|
expect(screen.getByRole('textbox')).toHaveAttribute('aria-busy', 'true');
|
|
161
170
|
expect(screen.getByRole('textbox')).not.toBeDisabled();
|
|
@@ -340,12 +349,7 @@ describe('TextArea', () => {
|
|
|
340
349
|
|
|
341
350
|
it('renders with size="lg"', () => {
|
|
342
351
|
render(
|
|
343
|
-
<TextArea
|
|
344
|
-
label="Description"
|
|
345
|
-
value=""
|
|
346
|
-
onChange={() => {}}
|
|
347
|
-
size="lg"
|
|
348
|
-
/>,
|
|
352
|
+
<TextArea label="Description" value="" onChange={() => {}} size="lg" />,
|
|
349
353
|
);
|
|
350
354
|
expect(screen.getByLabelText('Description')).toBeInTheDocument();
|
|
351
355
|
});
|
|
@@ -595,4 +599,132 @@ describe('TextArea', () => {
|
|
|
595
599
|
expect(textarea).toHaveFocus();
|
|
596
600
|
});
|
|
597
601
|
});
|
|
602
|
+
|
|
603
|
+
describe('disabledMessage', () => {
|
|
604
|
+
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
605
|
+
render(
|
|
606
|
+
<TextArea
|
|
607
|
+
label="Notes"
|
|
608
|
+
value=""
|
|
609
|
+
onChange={() => {}}
|
|
610
|
+
isDisabled
|
|
611
|
+
disabledMessage="You need the Editor role"
|
|
612
|
+
/>,
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
const textarea = screen.getByRole('textbox');
|
|
616
|
+
const container = textarea.parentElement as HTMLElement;
|
|
617
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
618
|
+
expect(tooltip).toHaveTextContent('You need the Editor role');
|
|
619
|
+
|
|
620
|
+
fireEvent.mouseEnter(container);
|
|
621
|
+
await waitFor(() => {
|
|
622
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
fireEvent.mouseLeave(container);
|
|
626
|
+
await waitFor(() => {
|
|
627
|
+
expect(tooltip).not.toHaveAttribute('popover-open');
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('shows the reason tooltip on keyboard focus', async () => {
|
|
632
|
+
const user = userEvent.setup();
|
|
633
|
+
render(
|
|
634
|
+
<TextArea
|
|
635
|
+
label="Notes"
|
|
636
|
+
value=""
|
|
637
|
+
onChange={() => {}}
|
|
638
|
+
isDisabled
|
|
639
|
+
disabledMessage="You need the Editor role"
|
|
640
|
+
/>,
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
644
|
+
await user.tab();
|
|
645
|
+
expect(screen.getByRole('textbox')).toHaveFocus();
|
|
646
|
+
await waitFor(() => {
|
|
647
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it('does not render a tooltip when not disabled', () => {
|
|
652
|
+
render(
|
|
653
|
+
<TextArea
|
|
654
|
+
label="Notes"
|
|
655
|
+
value=""
|
|
656
|
+
onChange={() => {}}
|
|
657
|
+
disabledMessage="You need the Editor role"
|
|
658
|
+
/>,
|
|
659
|
+
);
|
|
660
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('does not render a tooltip when disabled without a reason', () => {
|
|
664
|
+
render(
|
|
665
|
+
<TextArea label="Notes" value="" onChange={() => {}} isDisabled />,
|
|
666
|
+
);
|
|
667
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it('keeps the textarea focusable via aria-disabled when a reason is provided', () => {
|
|
671
|
+
render(
|
|
672
|
+
<TextArea
|
|
673
|
+
label="Notes"
|
|
674
|
+
value=""
|
|
675
|
+
onChange={() => {}}
|
|
676
|
+
isDisabled
|
|
677
|
+
disabledMessage="You need the Editor role"
|
|
678
|
+
/>,
|
|
679
|
+
);
|
|
680
|
+
const textarea = screen.getByRole('textbox');
|
|
681
|
+
expect(textarea).not.toBeDisabled();
|
|
682
|
+
expect(textarea).toHaveAttribute('aria-disabled', 'true');
|
|
683
|
+
expect(textarea).toHaveAttribute('readonly');
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
it('links the reason tooltip from the textarea via aria-describedby', () => {
|
|
687
|
+
render(
|
|
688
|
+
<TextArea
|
|
689
|
+
label="Notes"
|
|
690
|
+
value=""
|
|
691
|
+
onChange={() => {}}
|
|
692
|
+
isDisabled
|
|
693
|
+
disabledMessage="You need the Editor role"
|
|
694
|
+
/>,
|
|
695
|
+
);
|
|
696
|
+
const textarea = screen.getByRole('textbox');
|
|
697
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
698
|
+
expect(textarea.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
it('blocks value changes while focusable-disabled', async () => {
|
|
702
|
+
const user = userEvent.setup();
|
|
703
|
+
const onChange = vi.fn();
|
|
704
|
+
render(
|
|
705
|
+
<TextArea
|
|
706
|
+
label="Notes"
|
|
707
|
+
value=""
|
|
708
|
+
onChange={onChange}
|
|
709
|
+
isDisabled
|
|
710
|
+
disabledMessage="You need the Editor role"
|
|
711
|
+
/>,
|
|
712
|
+
);
|
|
713
|
+
|
|
714
|
+
const textarea = screen.getByRole('textbox');
|
|
715
|
+
await user.click(textarea);
|
|
716
|
+
await user.keyboard('hello');
|
|
717
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
718
|
+
expect(textarea).toHaveValue('');
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it('remains natively disabled when disabled without a reason', () => {
|
|
722
|
+
render(
|
|
723
|
+
<TextArea label="Notes" value="" onChange={() => {}} isDisabled />,
|
|
724
|
+
);
|
|
725
|
+
const textarea = screen.getByRole('textbox');
|
|
726
|
+
expect(textarea).toBeDisabled();
|
|
727
|
+
expect(textarea).not.toHaveAttribute('aria-disabled');
|
|
728
|
+
});
|
|
729
|
+
});
|
|
598
730
|
});
|
|
@@ -43,12 +43,14 @@ import {
|
|
|
43
43
|
} from '../Field';
|
|
44
44
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
45
45
|
import {Spinner} from '../Spinner';
|
|
46
|
+
import {useTooltip} from '../Tooltip';
|
|
46
47
|
import {mergeProps, mergeRefs} from '../utils';
|
|
47
48
|
import type {BaseProps} from '../BaseProps';
|
|
48
49
|
import type {SizeValue} from '../utils/types';
|
|
49
50
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
50
51
|
import {useSize} from '../SizeContext/SizeContext';
|
|
51
52
|
import {themeProps} from '../utils/themeProps';
|
|
53
|
+
import {VisuallyHidden} from '../VisuallyHidden';
|
|
52
54
|
|
|
53
55
|
const COUNTER_WARNING_THRESHOLD = 0.8;
|
|
54
56
|
|
|
@@ -93,17 +95,6 @@ const styles = stylex.create({
|
|
|
93
95
|
counterError: {
|
|
94
96
|
color: colorVars['--color-error'],
|
|
95
97
|
},
|
|
96
|
-
srOnly: {
|
|
97
|
-
position: 'absolute',
|
|
98
|
-
width: '1px',
|
|
99
|
-
height: '1px',
|
|
100
|
-
padding: 0,
|
|
101
|
-
margin: '-1px',
|
|
102
|
-
overflow: 'hidden',
|
|
103
|
-
clip: 'rect(0,0,0,0)',
|
|
104
|
-
whiteSpace: 'nowrap',
|
|
105
|
-
borderWidth: 0,
|
|
106
|
-
},
|
|
107
98
|
statusIcon: {
|
|
108
99
|
position: 'absolute',
|
|
109
100
|
top: spacingVars['--spacing-2'],
|
|
@@ -199,6 +190,27 @@ export interface TextAreaProps extends Omit<
|
|
|
199
190
|
* @default false
|
|
200
191
|
*/
|
|
201
192
|
isDisabled?: boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Explains why the textarea is disabled. When set together with
|
|
195
|
+
* `isDisabled`, the textarea shows a tooltip with this text on hover and
|
|
196
|
+
* keyboard focus, and stays focusable (via `aria-disabled`) so the reason is
|
|
197
|
+
* discoverable by keyboard and assistive technology. The field cannot be
|
|
198
|
+
* edited (it becomes read-only) while disabled.
|
|
199
|
+
*
|
|
200
|
+
* Use this instead of wrapping a disabled textarea in `Tooltip` — disabled
|
|
201
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```
|
|
205
|
+
* <TextArea
|
|
206
|
+
* label="Notes"
|
|
207
|
+
* value={notes}
|
|
208
|
+
* isDisabled
|
|
209
|
+
* disabledMessage="Notes are locked after submission"
|
|
210
|
+
* />
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
disabledMessage?: string;
|
|
202
214
|
/**
|
|
203
215
|
* Status indicator for the textarea.
|
|
204
216
|
* When set, displays a colored border and status icon.
|
|
@@ -284,6 +296,7 @@ export function TextArea({
|
|
|
284
296
|
placeholder,
|
|
285
297
|
rows = 3,
|
|
286
298
|
isDisabled = false,
|
|
299
|
+
disabledMessage,
|
|
287
300
|
status,
|
|
288
301
|
labelTooltip,
|
|
289
302
|
startIcon,
|
|
@@ -314,6 +327,20 @@ export function TextArea({
|
|
|
314
327
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
315
328
|
const isBusy = isLoading || optimisticValue !== value;
|
|
316
329
|
|
|
330
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
331
|
+
// tooltip listeners attach to the textarea container (which already exists)
|
|
332
|
+
// and the textarea stays perceivable via aria-disabled instead of the native
|
|
333
|
+
// disabled attribute. The field is made read-only so it can't be typed into,
|
|
334
|
+
// and value mutation is blocked by the isDisabled guard in handleChange.
|
|
335
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
336
|
+
const disabledMessageTooltip = useTooltip({
|
|
337
|
+
placement: 'above',
|
|
338
|
+
// The container div is not naturally focusable; focusin bubbles up from
|
|
339
|
+
// the textarea, so always attach focus listeners.
|
|
340
|
+
focusTrigger: 'always',
|
|
341
|
+
isEnabled: showsDisabledMessage,
|
|
342
|
+
});
|
|
343
|
+
|
|
317
344
|
const statusIconMap: Record<TextAreaStatusType, IconName> = {
|
|
318
345
|
warning: 'warning',
|
|
319
346
|
error: 'error',
|
|
@@ -334,11 +361,18 @@ export function TextArea({
|
|
|
334
361
|
description ? descriptionID : null,
|
|
335
362
|
status?.message ? statusMessageID : null,
|
|
336
363
|
maxLength != null ? counterID : null,
|
|
364
|
+
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
337
365
|
]
|
|
338
366
|
.filter(Boolean)
|
|
339
367
|
.join(' ') || undefined;
|
|
340
368
|
|
|
341
369
|
const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
|
|
370
|
+
// Value can't change while showing a disabled message (the field is
|
|
371
|
+
// read-only and non-native-disabled), but guard the handler too so the
|
|
372
|
+
// optimistic value and callbacks never fire.
|
|
373
|
+
if (isDisabled) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
342
376
|
const newValue = e.target.value;
|
|
343
377
|
onChange?.(newValue, e);
|
|
344
378
|
if (changeAction && !e.defaultPrevented) {
|
|
@@ -381,7 +415,13 @@ export function TextArea({
|
|
|
381
415
|
labelTooltip={labelTooltip}
|
|
382
416
|
width={width}>
|
|
383
417
|
<div
|
|
384
|
-
ref={
|
|
418
|
+
ref={el => {
|
|
419
|
+
containerRef.current = el;
|
|
420
|
+
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
421
|
+
// Handlers are gated internally by isEnabled, and anchor names
|
|
422
|
+
// compose, so attaching unconditionally is safe.
|
|
423
|
+
disabledMessageTooltip.ref(el);
|
|
424
|
+
}}
|
|
385
425
|
onClick={handleWrapperClick}
|
|
386
426
|
onMouseUp={handleWrapperMouseUp}
|
|
387
427
|
{...mergeProps(
|
|
@@ -413,7 +453,12 @@ export function TextArea({
|
|
|
413
453
|
onBlur={onBlur}
|
|
414
454
|
placeholder={placeholder}
|
|
415
455
|
rows={rows}
|
|
416
|
-
|
|
456
|
+
// With a disabledMessage the textarea keeps focusability via
|
|
457
|
+
// aria-disabled so the reason is focus-discoverable; readOnly + the
|
|
458
|
+
// handleChange guard keep the value from changing.
|
|
459
|
+
disabled={isDisabled && !showsDisabledMessage}
|
|
460
|
+
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
461
|
+
readOnly={showsDisabledMessage || undefined}
|
|
417
462
|
spellCheck={hasSpellCheck}
|
|
418
463
|
autoFocus={hasAutoFocus}
|
|
419
464
|
data-autofocus={hasAutoFocus || undefined}
|
|
@@ -451,15 +496,17 @@ export function TextArea({
|
|
|
451
496
|
optimisticValue.length > maxLength && styles.counterError,
|
|
452
497
|
)}>
|
|
453
498
|
{optimisticValue.length}/{maxLength}
|
|
454
|
-
<
|
|
499
|
+
<VisuallyHidden aria-live="polite">
|
|
455
500
|
{optimisticValue.length >= maxLength * COUNTER_WARNING_THRESHOLD
|
|
456
501
|
? optimisticValue.length > maxLength
|
|
457
502
|
? `${optimisticValue.length - maxLength} characters over limit`
|
|
458
503
|
: `${maxLength - optimisticValue.length} characters remaining`
|
|
459
504
|
: ''}
|
|
460
|
-
</
|
|
505
|
+
</VisuallyHidden>
|
|
461
506
|
</div>
|
|
462
507
|
)}
|
|
508
|
+
{showsDisabledMessage &&
|
|
509
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
463
510
|
</Field>
|
|
464
511
|
);
|
|
465
512
|
}
|
|
@@ -78,6 +78,12 @@ export const docs = {
|
|
|
78
78
|
'Disables the input, preventing interaction and dimming the element.',
|
|
79
79
|
default: 'false',
|
|
80
80
|
},
|
|
81
|
+
{
|
|
82
|
+
name: 'disabledMessage',
|
|
83
|
+
type: 'string',
|
|
84
|
+
description:
|
|
85
|
+
'Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (the field becomes read-only). Use this instead of wrapping a disabled TextInput in Tooltip — disabled controls swallow the hover events an external Tooltip needs.',
|
|
86
|
+
},
|
|
81
87
|
{
|
|
82
88
|
name: 'isLoading',
|
|
83
89
|
type: 'boolean',
|
|
@@ -144,6 +150,7 @@ export const docs = {
|
|
|
144
150
|
{guidance: false, description: "Don't use placeholder text as a replacement for a label; placeholders disappear on focus and are not reliably read by screen readers."},
|
|
145
151
|
{guidance: false, description: "Don't use TextInput for multi-line content like comments or descriptions; use TextArea instead."},
|
|
146
152
|
{guidance: false, description: "Don't mark every field as required; only flag mandatory fields so users are not overwhelmed by validation errors."},
|
|
153
|
+
{guidance: false, description: "Don't wrap a disabled TextInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead."},
|
|
147
154
|
],
|
|
148
155
|
anatomy: [
|
|
149
156
|
{name: 'Label', required: true, description: 'Text that identifies the field. Always rendered for accessibility even when visually hidden.'},
|
|
@@ -231,6 +238,12 @@ export const docsZh = {
|
|
|
231
238
|
'禁用输入框,阻止交互并使元素变暗。',
|
|
232
239
|
default: 'false',
|
|
233
240
|
},
|
|
241
|
+
{
|
|
242
|
+
name: 'disabledMessage',
|
|
243
|
+
type: 'string',
|
|
244
|
+
description:
|
|
245
|
+
'说明输入框被禁用的原因。与 isDisabled 一起使用时,在悬停/键盘聚焦时显示工具提示,并通过 aria-disabled 保持输入框可聚焦(字段变为只读)。请使用此属性,而不是用 Tooltip 包裹已禁用的 TextInput——已禁用的控件会吞掉外部 Tooltip 所需的悬停事件。',
|
|
246
|
+
},
|
|
234
247
|
{
|
|
235
248
|
name: 'isLoading',
|
|
236
249
|
type: 'boolean',
|
|
@@ -296,6 +309,7 @@ export const docsZh = {
|
|
|
296
309
|
{guidance: false, description: "Don't use placeholder text as a replacement for a label; placeholders disappear on focus and are not reliably read by screen readers."},
|
|
297
310
|
{guidance: false, description: "Don't use TextInput for multi-line content like comments or descriptions; use TextArea instead."},
|
|
298
311
|
{guidance: false, description: "Don't mark every field as required; only flag mandatory fields so users are not overwhelmed by validation errors."},
|
|
312
|
+
{guidance: false, description: "Don't wrap a disabled TextInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead."},
|
|
299
313
|
],
|
|
300
314
|
anatomy: [
|
|
301
315
|
{name: 'Label', required: true, description: 'Text that identifies the field. Always rendered for accessibility even when visually hidden.'},
|
|
@@ -323,6 +337,7 @@ export const docsDense = {
|
|
|
323
337
|
{guidance: false, description: "Don't use placeholder text as a replacement for a label; placeholders disappear on focus and are not reliably read by screen readers."},
|
|
324
338
|
{guidance: false, description: "Don't use TextInput for multi-line content like comments or descriptions; use TextArea instead."},
|
|
325
339
|
{guidance: false, description: "Don't mark every field as required; only flag mandatory fields so users are not overwhelmed by validation errors."},
|
|
340
|
+
{guidance: false, description: "Don't wrap a disabled TextInput in Tooltip to explain why it's disabled; disabled controls swallow the hover events the wrapper needs. Use the disabledMessage prop instead."},
|
|
326
341
|
],
|
|
327
342
|
anatomy: [
|
|
328
343
|
{name: 'Label', required: true, description: 'Text that identifies the field. Always rendered for accessibility even when visually hidden.'},
|
|
@@ -346,6 +361,8 @@ export const docsDense = {
|
|
|
346
361
|
isOptional: 'Shows "Optional" indicator. Mutually exclusive w/ isRequired.',
|
|
347
362
|
isRequired: 'Shows "Required" indicator+sets aria-required. Mutually exclusive w/ isOptional.',
|
|
348
363
|
isDisabled: 'Disables input, prevents interaction, dims element.',
|
|
364
|
+
disabledMessage:
|
|
365
|
+
'Explains why input is disabled. With isDisabled, shows tooltip on hover/focus + keeps input focusable via aria-disabled (field becomes read-only). Use instead of wrapping a disabled TextInput in Tooltip.',
|
|
349
366
|
isLoading: 'Loading state w/ spinner+aria-busy.',
|
|
350
367
|
placeholder: 'Placeholder when input empty.',
|
|
351
368
|
labelTooltip: 'Tooltip in info icon at label end.',
|