@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
|
@@ -9,12 +9,43 @@
|
|
|
9
9
|
* SYNC: When TextInput.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi} from 'vitest';
|
|
13
|
-
import {render, screen, fireEvent} 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 {MagnifyingGlassIcon} from '@heroicons/react/24/outline';
|
|
16
16
|
import {TextInput} from './TextInput';
|
|
17
17
|
|
|
18
|
+
// Mock showPopover/hidePopover since jsdom does not implement them. Used by the
|
|
19
|
+
// disabledMessage tooltip.
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
22
|
+
this.setAttribute('popover-open', '');
|
|
23
|
+
const event = new Event('toggle', {bubbles: false});
|
|
24
|
+
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
25
|
+
this.dispatchEvent(event);
|
|
26
|
+
});
|
|
27
|
+
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
28
|
+
this.removeAttribute('popover-open');
|
|
29
|
+
const event = new Event('toggle', {bubbles: false});
|
|
30
|
+
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
31
|
+
this.dispatchEvent(event);
|
|
32
|
+
});
|
|
33
|
+
const originalMatches = HTMLElement.prototype.matches;
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
(HTMLElement.prototype as any).matches = function (
|
|
36
|
+
selector: string,
|
|
37
|
+
): boolean {
|
|
38
|
+
if (selector === ':popover-open') {
|
|
39
|
+
return this.hasAttribute('popover-open');
|
|
40
|
+
}
|
|
41
|
+
return originalMatches.call(this, selector);
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// jsdom popover content is in the DOM but may not be "visible" in the
|
|
46
|
+
// accessibility tree. Use hidden: true to find it.
|
|
47
|
+
const h = {hidden: true} as const;
|
|
48
|
+
|
|
18
49
|
describe('TextInput', () => {
|
|
19
50
|
it('renders with label', () => {
|
|
20
51
|
render(<TextInput label="Name" value="" onChange={() => {}} />);
|
|
@@ -62,31 +93,20 @@ describe('TextInput', () => {
|
|
|
62
93
|
|
|
63
94
|
it('displays controlled value', () => {
|
|
64
95
|
render(
|
|
65
|
-
<TextInput
|
|
66
|
-
label="Name"
|
|
67
|
-
value="Controlled value"
|
|
68
|
-
onChange={() => {}}
|
|
69
|
-
/>,
|
|
96
|
+
<TextInput label="Name" value="Controlled value" onChange={() => {}} />,
|
|
70
97
|
);
|
|
71
98
|
expect(screen.getByRole('textbox')).toHaveValue('Controlled value');
|
|
72
99
|
});
|
|
73
100
|
|
|
74
101
|
it('forwards ref correctly', () => {
|
|
75
102
|
const ref = vi.fn();
|
|
76
|
-
render(
|
|
77
|
-
<TextInput ref={ref} label="Name" value="" onChange={() => {}} />,
|
|
78
|
-
);
|
|
103
|
+
render(<TextInput ref={ref} label="Name" value="" onChange={() => {}} />);
|
|
79
104
|
expect(ref).toHaveBeenCalledWith(expect.any(HTMLInputElement));
|
|
80
105
|
});
|
|
81
106
|
|
|
82
107
|
it('visually hides label when isLabelHidden is true', () => {
|
|
83
108
|
render(
|
|
84
|
-
<TextInput
|
|
85
|
-
label="Search"
|
|
86
|
-
isLabelHidden
|
|
87
|
-
value=""
|
|
88
|
-
onChange={() => {}}
|
|
89
|
-
/>,
|
|
109
|
+
<TextInput label="Search" isLabelHidden value="" onChange={() => {}} />,
|
|
90
110
|
);
|
|
91
111
|
const label = screen.getByText('Search');
|
|
92
112
|
expect(label).toBeInTheDocument();
|
|
@@ -116,9 +136,7 @@ describe('TextInput', () => {
|
|
|
116
136
|
});
|
|
117
137
|
|
|
118
138
|
it('sets disabled attribute when isDisabled is true', () => {
|
|
119
|
-
render(
|
|
120
|
-
<TextInput label="Name" isDisabled value="" onChange={() => {}} />,
|
|
121
|
-
);
|
|
139
|
+
render(<TextInput label="Name" isDisabled value="" onChange={() => {}} />);
|
|
122
140
|
expect(screen.getByRole('textbox')).toBeDisabled();
|
|
123
141
|
});
|
|
124
142
|
|
|
@@ -410,12 +428,7 @@ describe('TextInput', () => {
|
|
|
410
428
|
describe('hasClear', () => {
|
|
411
429
|
it('shows clear button when hasClear is true and value is non-empty', () => {
|
|
412
430
|
render(
|
|
413
|
-
<TextInput
|
|
414
|
-
label="Name"
|
|
415
|
-
value="hello"
|
|
416
|
-
onChange={() => {}}
|
|
417
|
-
hasClear
|
|
418
|
-
/>,
|
|
431
|
+
<TextInput label="Name" value="hello" onChange={() => {}} hasClear />,
|
|
419
432
|
);
|
|
420
433
|
expect(
|
|
421
434
|
screen.getByRole('button', {name: 'Clear Name'}),
|
|
@@ -423,9 +436,7 @@ describe('TextInput', () => {
|
|
|
423
436
|
});
|
|
424
437
|
|
|
425
438
|
it('does not show clear button when value is empty', () => {
|
|
426
|
-
render(
|
|
427
|
-
<TextInput label="Name" value="" onChange={() => {}} hasClear />,
|
|
428
|
-
);
|
|
439
|
+
render(<TextInput label="Name" value="" onChange={() => {}} hasClear />);
|
|
429
440
|
expect(
|
|
430
441
|
screen.queryByRole('button', {name: 'Clear Name'}),
|
|
431
442
|
).not.toBeInTheDocument();
|
|
@@ -457,12 +468,7 @@ describe('TextInput', () => {
|
|
|
457
468
|
const user = userEvent.setup();
|
|
458
469
|
const onChange = vi.fn();
|
|
459
470
|
render(
|
|
460
|
-
<TextInput
|
|
461
|
-
label="Name"
|
|
462
|
-
value="hello"
|
|
463
|
-
onChange={onChange}
|
|
464
|
-
hasClear
|
|
465
|
-
/>,
|
|
471
|
+
<TextInput label="Name" value="hello" onChange={onChange} hasClear />,
|
|
466
472
|
);
|
|
467
473
|
await user.click(screen.getByRole('button', {name: 'Clear Name'}));
|
|
468
474
|
expect(onChange).toHaveBeenCalledWith('', null);
|
|
@@ -524,4 +530,132 @@ describe('TextInput', () => {
|
|
|
524
530
|
expect(fieldRoot.getAttribute('style') ?? '').not.toContain('100%');
|
|
525
531
|
});
|
|
526
532
|
});
|
|
533
|
+
|
|
534
|
+
describe('disabledMessage', () => {
|
|
535
|
+
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
536
|
+
render(
|
|
537
|
+
<TextInput
|
|
538
|
+
label="Owner"
|
|
539
|
+
value=""
|
|
540
|
+
onChange={() => {}}
|
|
541
|
+
isDisabled
|
|
542
|
+
disabledMessage="You need the Editor role"
|
|
543
|
+
/>,
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
const input = screen.getByRole('textbox');
|
|
547
|
+
const container = input.parentElement as HTMLElement;
|
|
548
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
549
|
+
expect(tooltip).toHaveTextContent('You need the Editor role');
|
|
550
|
+
|
|
551
|
+
fireEvent.mouseEnter(container);
|
|
552
|
+
await waitFor(() => {
|
|
553
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
fireEvent.mouseLeave(container);
|
|
557
|
+
await waitFor(() => {
|
|
558
|
+
expect(tooltip).not.toHaveAttribute('popover-open');
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it('shows the reason tooltip on keyboard focus', async () => {
|
|
563
|
+
const user = userEvent.setup();
|
|
564
|
+
render(
|
|
565
|
+
<TextInput
|
|
566
|
+
label="Owner"
|
|
567
|
+
value=""
|
|
568
|
+
onChange={() => {}}
|
|
569
|
+
isDisabled
|
|
570
|
+
disabledMessage="You need the Editor role"
|
|
571
|
+
/>,
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
575
|
+
await user.tab();
|
|
576
|
+
expect(screen.getByRole('textbox')).toHaveFocus();
|
|
577
|
+
await waitFor(() => {
|
|
578
|
+
expect(tooltip).toHaveAttribute('popover-open');
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('does not render a tooltip when not disabled', () => {
|
|
583
|
+
render(
|
|
584
|
+
<TextInput
|
|
585
|
+
label="Owner"
|
|
586
|
+
value=""
|
|
587
|
+
onChange={() => {}}
|
|
588
|
+
disabledMessage="You need the Editor role"
|
|
589
|
+
/>,
|
|
590
|
+
);
|
|
591
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
592
|
+
});
|
|
593
|
+
|
|
594
|
+
it('does not render a tooltip when disabled without a reason', () => {
|
|
595
|
+
render(
|
|
596
|
+
<TextInput label="Owner" value="" onChange={() => {}} isDisabled />,
|
|
597
|
+
);
|
|
598
|
+
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it('keeps the input focusable via aria-disabled when a reason is provided', () => {
|
|
602
|
+
render(
|
|
603
|
+
<TextInput
|
|
604
|
+
label="Owner"
|
|
605
|
+
value=""
|
|
606
|
+
onChange={() => {}}
|
|
607
|
+
isDisabled
|
|
608
|
+
disabledMessage="You need the Editor role"
|
|
609
|
+
/>,
|
|
610
|
+
);
|
|
611
|
+
const input = screen.getByRole('textbox');
|
|
612
|
+
expect(input).not.toBeDisabled();
|
|
613
|
+
expect(input).toHaveAttribute('aria-disabled', 'true');
|
|
614
|
+
expect(input).toHaveAttribute('readonly');
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it('links the reason tooltip from the input via aria-describedby', () => {
|
|
618
|
+
render(
|
|
619
|
+
<TextInput
|
|
620
|
+
label="Owner"
|
|
621
|
+
value=""
|
|
622
|
+
onChange={() => {}}
|
|
623
|
+
isDisabled
|
|
624
|
+
disabledMessage="You need the Editor role"
|
|
625
|
+
/>,
|
|
626
|
+
);
|
|
627
|
+
const input = screen.getByRole('textbox');
|
|
628
|
+
const tooltip = screen.getByRole('tooltip', h);
|
|
629
|
+
expect(input.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it('blocks value changes while focusable-disabled', async () => {
|
|
633
|
+
const user = userEvent.setup();
|
|
634
|
+
const onChange = vi.fn();
|
|
635
|
+
render(
|
|
636
|
+
<TextInput
|
|
637
|
+
label="Owner"
|
|
638
|
+
value=""
|
|
639
|
+
onChange={onChange}
|
|
640
|
+
isDisabled
|
|
641
|
+
disabledMessage="You need the Editor role"
|
|
642
|
+
/>,
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
const input = screen.getByRole('textbox');
|
|
646
|
+
await user.click(input);
|
|
647
|
+
await user.keyboard('hello');
|
|
648
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
649
|
+
expect(input).toHaveValue('');
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it('remains natively disabled when disabled without a reason', () => {
|
|
653
|
+
render(
|
|
654
|
+
<TextInput label="Owner" value="" onChange={() => {}} isDisabled />,
|
|
655
|
+
);
|
|
656
|
+
const input = screen.getByRole('textbox');
|
|
657
|
+
expect(input).toBeDisabled();
|
|
658
|
+
expect(input).not.toHaveAttribute('aria-disabled');
|
|
659
|
+
});
|
|
660
|
+
});
|
|
527
661
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file TextInput.tsx
|
|
7
|
-
* @input Uses React, useId, ChangeEvent, Field, Icon
|
|
7
|
+
* @input Uses React, useId, ChangeEvent, Field, Icon, InputGroupContext
|
|
8
8
|
* @output Exports TextInput component, TextInputProps
|
|
9
9
|
* @position Core implementation; consumed by index.ts, tested by TextInput.test.tsx
|
|
10
10
|
*
|
|
@@ -47,6 +47,9 @@ import {
|
|
|
47
47
|
} from '../Field';
|
|
48
48
|
import {Icon, renderIconSlot, type IconType} from '../Icon';
|
|
49
49
|
import {Spinner} from '../Spinner';
|
|
50
|
+
import {useTooltip} from '../Tooltip';
|
|
51
|
+
import {VisuallyHidden} from '../VisuallyHidden';
|
|
52
|
+
import {getInputARIA} from '../utils';
|
|
50
53
|
|
|
51
54
|
const styles = stylex.create({
|
|
52
55
|
clearButton: {
|
|
@@ -162,6 +165,27 @@ export interface TextInputProps extends Omit<
|
|
|
162
165
|
* @default false
|
|
163
166
|
*/
|
|
164
167
|
isDisabled?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Explains why the input is disabled. When set together with `isDisabled`,
|
|
170
|
+
* the input shows a tooltip with this text on hover and keyboard focus, and
|
|
171
|
+
* stays focusable (via `aria-disabled`) so the reason is discoverable by
|
|
172
|
+
* keyboard and assistive technology. The field cannot be edited (it becomes
|
|
173
|
+
* read-only) while disabled.
|
|
174
|
+
*
|
|
175
|
+
* Use this instead of wrapping a disabled input in `Tooltip` — disabled
|
|
176
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```
|
|
180
|
+
* <TextInput
|
|
181
|
+
* label="Owner"
|
|
182
|
+
* value={owner}
|
|
183
|
+
* isDisabled
|
|
184
|
+
* disabledMessage="You need the Editor role to change this"
|
|
185
|
+
* />
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
disabledMessage?: string;
|
|
165
189
|
/**
|
|
166
190
|
* Icon to display at the start of the input.
|
|
167
191
|
* Accepts a ReactNode (e.g. `<Icon icon={SearchIcon} />`) or an SVG icon component directly.
|
|
@@ -252,6 +276,7 @@ export function TextInput({
|
|
|
252
276
|
isOptional = false,
|
|
253
277
|
isRequired = false,
|
|
254
278
|
isDisabled = false,
|
|
279
|
+
disabledMessage,
|
|
255
280
|
startIcon,
|
|
256
281
|
status,
|
|
257
282
|
size: sizeProp,
|
|
@@ -276,6 +301,7 @@ export function TextInput({
|
|
|
276
301
|
const size = useSize(sizeProp, 'md');
|
|
277
302
|
|
|
278
303
|
const id = useId();
|
|
304
|
+
const inputLabelID = useId();
|
|
279
305
|
const descriptionID = useId();
|
|
280
306
|
const statusMessageID = useId();
|
|
281
307
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
@@ -286,6 +312,20 @@ export function TextInput({
|
|
|
286
312
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
287
313
|
const isBusy = isLoading || optimisticValue !== value;
|
|
288
314
|
|
|
315
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
316
|
+
// tooltip listeners attach to the input container (which already exists) and
|
|
317
|
+
// the input stays perceivable via aria-disabled instead of the native
|
|
318
|
+
// disabled attribute. The field is made read-only so it can't be typed into,
|
|
319
|
+
// and value mutation is blocked by the isDisabled guard in handleChange.
|
|
320
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
321
|
+
const disabledMessageTooltip = useTooltip({
|
|
322
|
+
placement: 'above',
|
|
323
|
+
// The container div is not naturally focusable; focusin bubbles up from
|
|
324
|
+
// the input, so always attach focus listeners.
|
|
325
|
+
focusTrigger: 'always',
|
|
326
|
+
isEnabled: showsDisabledMessage,
|
|
327
|
+
});
|
|
328
|
+
|
|
289
329
|
const statusIconMap: Record<InputStatusType, IconName> = {
|
|
290
330
|
warning: 'warning',
|
|
291
331
|
error: 'error',
|
|
@@ -301,15 +341,23 @@ export function TextInput({
|
|
|
301
341
|
success: 'success',
|
|
302
342
|
};
|
|
303
343
|
|
|
304
|
-
const ariaDescribedBy =
|
|
344
|
+
const {ariaLabelledBy, ariaDescribedBy} = getInputARIA(
|
|
345
|
+
inputLabelID,
|
|
305
346
|
[
|
|
306
347
|
description ? descriptionID : null,
|
|
307
348
|
status?.message ? statusMessageID : null,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
349
|
+
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
350
|
+
],
|
|
351
|
+
inputGroup,
|
|
352
|
+
);
|
|
311
353
|
|
|
312
354
|
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
355
|
+
// Value can't change while showing a disabled message (the field is
|
|
356
|
+
// read-only and non-native-disabled), but guard the handler too so the
|
|
357
|
+
// optimistic value and callbacks never fire.
|
|
358
|
+
if (isDisabled) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
313
361
|
const newValue = e.target.value;
|
|
314
362
|
onChange?.(newValue, e);
|
|
315
363
|
if (changeAction && !e.defaultPrevented) {
|
|
@@ -336,7 +384,13 @@ export function TextInput({
|
|
|
336
384
|
|
|
337
385
|
const inputWrapper = (
|
|
338
386
|
<div
|
|
339
|
-
ref={
|
|
387
|
+
ref={el => {
|
|
388
|
+
containerRef.current = el;
|
|
389
|
+
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
390
|
+
// Handlers are gated internally by isEnabled, and anchor names
|
|
391
|
+
// compose, so attaching unconditionally is safe.
|
|
392
|
+
disabledMessageTooltip.ref(el);
|
|
393
|
+
}}
|
|
340
394
|
onClick={handleWrapperClick}
|
|
341
395
|
onMouseUp={handleWrapperMouseUp}
|
|
342
396
|
{...mergeProps(
|
|
@@ -355,6 +409,7 @@ export function TextInput({
|
|
|
355
409
|
style,
|
|
356
410
|
)}>
|
|
357
411
|
{startIcon && renderIconSlot(startIcon, {size: 'sm', color: 'secondary'})}
|
|
412
|
+
{inputGroup && <VisuallyHidden id={inputLabelID}>{label}</VisuallyHidden>}
|
|
358
413
|
<input
|
|
359
414
|
{...rest}
|
|
360
415
|
ref={mergeRefs(ref, inputRef)}
|
|
@@ -374,14 +429,19 @@ export function TextInput({
|
|
|
374
429
|
: undefined
|
|
375
430
|
}
|
|
376
431
|
placeholder={placeholder}
|
|
377
|
-
disabled
|
|
432
|
+
// With a disabledMessage the input keeps focusability via aria-disabled
|
|
433
|
+
// so the reason is focus-discoverable; readOnly + the handleChange guard
|
|
434
|
+
// keep the value from changing.
|
|
435
|
+
disabled={isDisabled && !showsDisabledMessage}
|
|
436
|
+
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
437
|
+
readOnly={showsDisabledMessage || undefined}
|
|
378
438
|
autoFocus={hasAutoFocus}
|
|
379
439
|
data-autofocus={hasAutoFocus || undefined}
|
|
380
440
|
aria-describedby={ariaDescribedBy}
|
|
381
441
|
aria-required={isRequired === true ? 'true' : undefined}
|
|
382
442
|
aria-invalid={status?.type === 'error' ? 'true' : undefined}
|
|
383
443
|
aria-busy={isBusy || undefined}
|
|
384
|
-
aria-
|
|
444
|
+
aria-labelledby={ariaLabelledBy}
|
|
385
445
|
{...stylex.props(styles.input, isDisabled && styles.inputDisabled)}
|
|
386
446
|
/>
|
|
387
447
|
{hasClear && value !== '' && !isDisabled && (
|
|
@@ -405,7 +465,13 @@ export function TextInput({
|
|
|
405
465
|
);
|
|
406
466
|
|
|
407
467
|
if (inputGroup) {
|
|
408
|
-
return
|
|
468
|
+
return (
|
|
469
|
+
<>
|
|
470
|
+
{inputWrapper}
|
|
471
|
+
{showsDisabledMessage &&
|
|
472
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
473
|
+
</>
|
|
474
|
+
);
|
|
409
475
|
}
|
|
410
476
|
|
|
411
477
|
return (
|
|
@@ -430,6 +496,8 @@ export function TextInput({
|
|
|
430
496
|
labelTooltip={labelTooltip}
|
|
431
497
|
width={width}>
|
|
432
498
|
{inputWrapper}
|
|
499
|
+
{showsDisabledMessage &&
|
|
500
|
+
disabledMessageTooltip.renderTooltip(disabledMessage)}
|
|
433
501
|
</Field>
|
|
434
502
|
);
|
|
435
503
|
}
|
|
@@ -126,11 +126,11 @@ export const docsDense = {
|
|
|
126
126
|
description:
|
|
127
127
|
'Compact square image preview. Shimmer while uploading, image on success, placeholder when empty. Use in chat composers, file lists, or small media previews.',
|
|
128
128
|
bestPractices: [
|
|
129
|
-
{guidance: true, description: 'Always set label (file name) for a11y
|
|
129
|
+
{guidance: true, description: 'Always set label (file name) for a11y; powers screen reader announce + hover tooltip.'},
|
|
130
130
|
{guidance: true, description: 'isLoading w/o src \u2192 skeleton; isLoading w/ src \u2192 spinner overlay. Two distinct loading states.'},
|
|
131
|
-
{guidance: true, description: 'onClick adds button semantics + hover shadow
|
|
132
|
-
{guidance: false, description: "Don't use for non-image files (PDF, xlsx)
|
|
133
|
-
{guidance: false, description: "Don't omit alt when src present
|
|
131
|
+
{guidance: true, description: 'onClick adds button semantics + hover shadow; pair with lightbox for full preview.'},
|
|
132
|
+
{guidance: false, description: "Don't use for non-image files (PDF, xlsx); use file attachment component with icon instead."},
|
|
133
|
+
{guidance: false, description: "Don't omit alt when src present; screen readers need image content description, not just label."},
|
|
134
134
|
],
|
|
135
135
|
},
|
|
136
136
|
propDescriptions: {
|