@astryxdesign/core 0.1.1 → 0.1.2-canary.04e71b2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +131 -13
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +11 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
- package/dist/Banner/Banner.d.ts +7 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +9 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +24 -5
- package/dist/Button/Button.d.ts +12 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +53 -17
- package/dist/Calendar/Calendar.d.ts +5 -4
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +82 -43
- package/dist/Calendar/hooks/index.d.ts +0 -2
- package/dist/Calendar/hooks/index.d.ts.map +1 -1
- package/dist/Calendar/hooks/index.js +1 -2
- package/dist/Calendar/index.d.ts +3 -3
- package/dist/Calendar/index.d.ts.map +1 -1
- package/dist/Calendar/index.js +1 -1
- package/dist/Calendar/styles.d.ts +3 -9
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +3 -11
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +17 -3
- package/dist/Center/Center.d.ts +11 -1
- package/dist/Center/Center.d.ts.map +1 -1
- package/dist/Center/Center.js +9 -3
- package/dist/Chat/ChatMessageList.d.ts +14 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +2 -0
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +4 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts +23 -2
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +51 -9
- package/dist/CheckboxList/CheckboxList.d.ts +13 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +39 -9
- package/dist/CheckboxList/CheckboxListContext.d.ts +7 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +3 -3
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +49 -37
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +5 -5
- package/dist/ContextMenu/ContextMenu.d.ts +4 -5
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +93 -11
- package/dist/DateInput/DateInput.d.ts +23 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -8
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +42 -9
- package/dist/DateTimeInput/DateTimeInput.d.ts +35 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +78 -15
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +12 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts +1 -8
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +42 -14
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +7 -1
- package/dist/Field/Field.d.ts +19 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +4 -0
- package/dist/Field/FieldLabel.d.ts +21 -2
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +41 -26
- package/dist/FileInput/FileInput.d.ts +22 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +56 -10
- package/dist/Grid/Grid.d.ts +11 -1
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +8 -0
- package/dist/HoverCard/HoverCard.d.ts +2 -2
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +18 -6
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -3
- package/dist/InputGroup/InputGroup.d.ts +2 -2
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +14 -5
- package/dist/InputGroup/InputGroupContext.d.ts +4 -0
- package/dist/InputGroup/InputGroupContext.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupContext.js +2 -2
- package/dist/InputGroup/index.d.ts +1 -0
- package/dist/InputGroup/index.d.ts.map +1 -1
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +34 -2
- package/dist/Layer/anchorName.d.ts +20 -0
- package/dist/Layer/anchorName.d.ts.map +1 -0
- package/dist/Layer/anchorName.js +36 -0
- package/dist/Layer/layerAnimations.stylex.d.ts +4 -0
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +8 -4
- package/dist/Layer/useLayer.d.ts +29 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +55 -11
- package/dist/Layout/Layout.d.ts +4 -11
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +10 -11
- package/dist/Layout/LayoutFooter.d.ts +2 -2
- package/dist/Layout/LayoutFooter.d.ts.map +1 -1
- package/dist/Layout/LayoutHeader.d.ts +2 -2
- package/dist/Layout/LayoutHeader.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.d.ts +2 -2
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.d.ts +51 -0
- package/dist/Layout/padding.stylex.d.ts.map +1 -1
- package/dist/Layout/padding.stylex.js +63 -0
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -2
- package/dist/Link/Link.d.ts +17 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +20 -9
- package/dist/Link/LinkProvider.d.ts +1 -0
- package/dist/Link/LinkProvider.d.ts.map +1 -1
- package/dist/Link/LinkProvider.js +1 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +18 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +13 -0
- package/dist/MoreMenu/MoreMenu.d.ts +1 -7
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MoreMenu/MoreMenu.js +0 -2
- package/dist/MultiSelector/MultiSelector.d.ts +25 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +103 -22
- package/dist/MultiSelector/hooks.d.ts +12 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +14 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +34 -3
- package/dist/NumberInput/NumberInput.d.ts +23 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +62 -12
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +46 -28
- package/dist/Popover/usePopover.d.ts +25 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +18 -6
- package/dist/PowerSearch/PowerSearch.d.ts +11 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +6 -1
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +3 -5
- package/dist/RadioList/RadioList.d.ts +20 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +105 -9
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts +13 -2
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +78 -44
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +7 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +13 -2
- package/dist/Selector/Selector.d.ts +22 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +84 -23
- package/dist/Selector/hooks.d.ts +8 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +14 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +1 -1
- package/dist/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/Skeleton/Skeleton.js +8 -2
- package/dist/Slider/Slider.d.ts +21 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +38 -11
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +1 -1
- package/dist/Stack/Stack.d.ts +38 -23
- package/dist/Stack/Stack.d.ts.map +1 -1
- package/dist/Stack/Stack.js +25 -1
- package/dist/Stack/StackItem.d.ts +12 -23
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +8 -1
- package/dist/Switch/Switch.d.ts +23 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -11
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +6 -0
- package/dist/TabList/TabList.d.ts +16 -4
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +86 -10
- package/dist/TabList/TabListContext.d.ts +5 -0
- package/dist/TabList/TabListContext.d.ts.map +1 -1
- package/dist/TabList/TabListContext.js +5 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +38 -16
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +36 -7
- package/dist/Table/TableCell.d.ts +8 -1
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +10 -10
- package/dist/Table/TableHeaderCell.d.ts +8 -1
- package/dist/Table/TableHeaderCell.d.ts.map +1 -1
- package/dist/Table/TableHeaderCell.js +16 -16
- package/dist/Table/TableRow.d.ts +6 -1
- package/dist/Table/TableRow.d.ts.map +1 -1
- package/dist/Table/TableRow.js +15 -7
- package/dist/Table/index.d.ts +4 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +3 -2
- package/dist/Table/plugins/pagination/paginateData.d.ts +2 -1
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +8 -3
- package/dist/Table/plugins/pagination/useTablePagination.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +6 -1
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +59 -3
- package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
- package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/index.js +3 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +369 -0
- package/dist/Table/tableContextMenu.d.ts +33 -0
- package/dist/Table/tableContextMenu.d.ts.map +1 -0
- package/dist/Table/tableContextMenu.js +133 -0
- package/dist/Table/types.d.ts +161 -5
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +1 -1
- package/dist/Text/text.stylex.d.ts +2 -2
- package/dist/Text/text.stylex.js +2 -2
- package/dist/TextArea/TextArea.d.ts +22 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +41 -9
- package/dist/TextInput/TextInput.d.ts +23 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +55 -10
- package/dist/TimeInput/TimeInput.d.ts +23 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +53 -10
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +28 -3
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +14 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +132 -3
- package/dist/ToggleButton/ToggleButton.d.ts +7 -9
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +34 -57
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +27 -5
- package/dist/Toolbar/Toolbar.d.ts +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +51 -7
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +57 -9
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +72 -2
- package/dist/TreeList/TreeListItem.d.ts +11 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +51 -12
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +16 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +1 -0
- package/dist/TreeList/treeListItem.markers.stylex.js +22 -0
- package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +67 -6
- package/dist/Typeahead/Typeahead.d.ts +24 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +29 -5
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +61 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +65 -0
- package/dist/VisuallyHidden/index.d.ts +11 -0
- package/dist/VisuallyHidden/index.d.ts.map +1 -0
- package/dist/VisuallyHidden/index.js +13 -0
- package/dist/astryx.css +40 -1
- package/dist/astryx.umd.js +147 -0
- package/dist/astryx.umd.js.map +7 -0
- package/dist/hooks/focusableSelector.d.ts +22 -0
- package/dist/hooks/focusableSelector.d.ts.map +1 -0
- package/dist/hooks/focusableSelector.js +24 -0
- package/dist/hooks/index.d.ts +12 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -2
- package/dist/hooks/useAnnounce.d.ts +40 -0
- package/dist/hooks/useAnnounce.d.ts.map +1 -0
- package/dist/hooks/useAnnounce.js +142 -0
- package/dist/hooks/useClickableContainer.d.ts +16 -1
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +16 -4
- package/dist/hooks/useEntryAnimation.d.ts.map +1 -1
- package/dist/hooks/useEntryAnimation.js +4 -4
- package/dist/hooks/useFocusTrap.d.ts +18 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +87 -3
- package/dist/hooks/useGridFocus.d.ts +88 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +261 -62
- package/dist/hooks/useKeyboardHint.d.ts +82 -0
- package/dist/hooks/useKeyboardHint.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHint.js +220 -0
- package/dist/hooks/useListFocus.d.ts +78 -7
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +305 -52
- package/dist/hooks/useLongPress.d.ts +21 -0
- package/dist/hooks/useLongPress.d.ts.map +1 -0
- package/dist/hooks/useLongPress.js +89 -0
- package/dist/hooks/useTreeFocus.d.ts +157 -0
- package/dist/hooks/useTreeFocus.d.ts.map +1 -0
- package/dist/hooks/useTreeFocus.js +337 -0
- package/dist/hooks/useTypeahead.d.ts +63 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +117 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/syntax/SyntaxTheme.d.ts +1 -1
- package/dist/theme/syntax/SyntaxTheme.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -2
- package/dist/theme/syntax/presets.d.ts +1 -1
- package/dist/theme/syntax/presets.d.ts.map +1 -1
- package/dist/theme/syntax/presets.js +1 -1
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.js +1 -1
- package/dist/theme/types.d.ts +1 -1
- package/dist/utils/dateTypes.d.ts +12 -0
- package/dist/utils/dateTypes.d.ts.map +1 -1
- package/dist/utils/dateTypes.js +41 -1
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/inputAria.d.ts +29 -0
- package/dist/utils/inputAria.d.ts.map +1 -0
- package/dist/utils/inputAria.js +30 -0
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +5 -2
- package/package.json +15 -5
- package/src/Avatar/Avatar.test.tsx +37 -0
- package/src/Avatar/Avatar.tsx +10 -5
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +16 -7
- package/src/Banner/Banner.tsx +9 -2
- package/src/Breadcrumbs/BreadcrumbItem.tsx +25 -7
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +31 -10
- package/src/Button/Button.doc.mjs +6 -0
- package/src/Button/Button.test.tsx +105 -11
- package/src/Button/Button.tsx +76 -21
- package/src/Calendar/Calendar.doc.mjs +4 -4
- package/src/Calendar/Calendar.test.tsx +168 -30
- package/src/Calendar/Calendar.tsx +121 -66
- package/src/Calendar/hooks/index.ts +0 -6
- package/src/Calendar/index.ts +1 -3
- package/src/Calendar/styles.ts +4 -9
- package/src/Carousel/Carousel.doc.mjs +7 -1
- package/src/Carousel/Carousel.test.tsx +20 -0
- package/src/Carousel/Carousel.tsx +16 -1
- package/src/Center/Center.doc.mjs +12 -2
- package/src/Center/Center.tsx +28 -3
- package/src/Chat/ChatComposer.doc.mjs +3 -0
- package/src/Chat/ChatComposerDrawer.doc.mjs +12 -0
- package/src/Chat/ChatMessageList.doc.mjs +8 -0
- package/src/Chat/ChatMessageList.test.tsx +18 -0
- package/src/Chat/ChatMessageList.tsx +16 -0
- package/src/Chat/useTriggerMenu.tsx +3 -0
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +172 -27
- package/src/CheckboxInput/CheckboxInput.tsx +78 -6
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxList.test.tsx +169 -16
- package/src/CheckboxList/CheckboxList.tsx +56 -3
- package/src/CheckboxList/CheckboxListContext.tsx +7 -0
- package/src/Citation/Citation.doc.mjs +10 -0
- package/src/Citation/Citation.test.tsx +117 -0
- package/src/Citation/Citation.tsx +9 -1
- package/src/ClickableCard/ClickableCard.doc.mjs +15 -0
- package/src/CodeBlock/CodeBlock.test.tsx +115 -0
- package/src/CodeBlock/CodeBlock.tsx +61 -33
- package/src/CommandPalette/CommandPalette.test.tsx +47 -1
- package/src/CommandPalette/CommandPalette.tsx +9 -21
- package/src/ContextMenu/ContextMenu.doc.mjs +4 -4
- package/src/ContextMenu/ContextMenu.test.tsx +155 -1
- package/src/ContextMenu/ContextMenu.tsx +113 -16
- package/src/DateInput/DateInput.doc.mjs +281 -56
- package/src/DateInput/DateInput.test.tsx +188 -2
- package/src/DateInput/DateInput.tsx +89 -10
- package/src/DateRangeInput/DateRangeInput.doc.mjs +251 -46
- package/src/DateRangeInput/DateRangeInput.test.tsx +182 -20
- package/src/DateRangeInput/DateRangeInput.tsx +63 -5
- package/src/DateTimeInput/DateTimeInput.doc.mjs +368 -67
- package/src/DateTimeInput/DateTimeInput.test.tsx +279 -11
- package/src/DateTimeInput/DateTimeInput.tsx +125 -17
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.tsx +12 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -8
- package/src/DropdownMenu/DropdownMenu.test.tsx +56 -42
- package/src/DropdownMenu/DropdownMenu.tsx +52 -18
- package/src/EmptyState/EmptyState.test.tsx +4 -2
- package/src/EmptyState/EmptyState.tsx +6 -2
- package/src/Field/Field.test.tsx +32 -0
- package/src/Field/Field.tsx +23 -5
- package/src/Field/FieldLabel.tsx +55 -17
- package/src/FileInput/FileInput.doc.mjs +17 -0
- package/src/FileInput/FileInput.test.tsx +283 -49
- package/src/FileInput/FileInput.tsx +76 -4
- package/src/Grid/Grid.doc.mjs +14 -4
- package/src/Grid/Grid.tsx +20 -0
- package/src/HoverCard/HoverCard.doc.mjs +3 -0
- package/src/HoverCard/HoverCard.test.tsx +189 -2
- package/src/HoverCard/HoverCard.tsx +20 -16
- package/src/HoverCard/useHoverCard.tsx +13 -10
- package/src/Icon/Icon.doc.mjs +8 -0
- package/src/InputGroup/InputGroup.doc.mjs +2 -2
- package/src/InputGroup/InputGroup.test.tsx +98 -60
- package/src/InputGroup/InputGroup.tsx +21 -4
- package/src/InputGroup/InputGroupContext.ts +9 -4
- package/src/InputGroup/index.ts +1 -0
- package/src/Kbd/Kbd.test.tsx +22 -4
- package/src/Kbd/Kbd.tsx +37 -12
- package/src/Layer/anchorName.test.ts +146 -0
- package/src/Layer/anchorName.ts +46 -0
- package/src/Layer/layerAnimations.stylex.ts +20 -4
- package/src/Layer/useLayer.doc.mjs +12 -2
- package/src/Layer/useLayer.tsx +100 -15
- package/src/Layout/Layout.doc.mjs +1 -1
- package/src/Layout/Layout.tsx +8 -16
- package/src/Layout/LayoutFooter.doc.mjs +4 -4
- package/src/Layout/LayoutFooter.tsx +3 -3
- package/src/Layout/LayoutHeader.doc.mjs +4 -4
- package/src/Layout/LayoutHeader.tsx +3 -3
- package/src/Layout/LayoutPanel.tsx +3 -3
- package/src/Layout/padding.stylex.ts +52 -0
- package/src/Lightbox/Lightbox.doc.mjs +9 -2
- package/src/Lightbox/Lightbox.test.tsx +53 -5
- package/src/Lightbox/Lightbox.tsx +9 -4
- package/src/Link/Link.doc.mjs +14 -0
- package/src/Link/Link.test.tsx +52 -2
- package/src/Link/Link.tsx +42 -7
- package/src/Link/LinkProvider.tsx +1 -0
- package/src/List/List.doc.mjs +7 -0
- package/src/Markdown/Markdown.doc.mjs +2 -0
- package/src/Markdown/Markdown.test.tsx +28 -26
- package/src/Markdown/Markdown.tsx +21 -6
- package/src/MetadataList/MetadataListItem.doc.mjs +4 -0
- package/src/MobileNav/MobileNav.doc.mjs +8 -8
- package/src/MobileNav/MobileNav.tsx +13 -0
- package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -17
- package/src/MoreMenu/MoreMenu.tsx +0 -9
- package/src/MultiSelector/MultiSelector.doc.mjs +25 -0
- package/src/MultiSelector/MultiSelector.test.tsx +375 -8
- package/src/MultiSelector/MultiSelector.tsx +145 -21
- package/src/MultiSelector/hooks.ts +27 -0
- package/src/NavMenu/NavHeadingMenu.test.tsx +77 -1
- package/src/NavMenu/NavHeadingMenu.tsx +50 -3
- package/src/NumberInput/NumberInput.doc.mjs +17 -0
- package/src/NumberInput/NumberInput.test.tsx +242 -40
- package/src/NumberInput/NumberInput.tsx +89 -11
- package/src/OverflowList/OverflowList.doc.mjs +17 -0
- package/src/Pagination/Pagination.doc.mjs +3 -3
- package/src/Pagination/Pagination.test.tsx +250 -14
- package/src/Pagination/Pagination.tsx +54 -29
- package/src/Popover/usePopover.doc.mjs +7 -3
- package/src/Popover/usePopover.tsx +49 -6
- package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
- package/src/PowerSearch/PowerSearch.test.tsx +97 -1
- package/src/PowerSearch/PowerSearch.tsx +16 -3
- package/src/ProgressBar/ProgressBar.test.tsx +45 -27
- package/src/ProgressBar/ProgressBar.tsx +3 -4
- package/src/RadioList/RadioList.doc.mjs +9 -0
- package/src/RadioList/RadioList.test.tsx +252 -16
- package/src/RadioList/RadioList.tsx +166 -10
- package/src/RadioList/RadioListItem.tsx +14 -2
- package/src/Resizable/Resizable.doc.mjs +1 -1
- package/src/Section/Section.doc.mjs +11 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +9 -0
- package/src/SegmentedControl/SegmentedControl.test.tsx +214 -42
- package/src/SegmentedControl/SegmentedControl.tsx +102 -54
- package/src/SegmentedControl/SegmentedControlContext.ts +7 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +14 -1
- package/src/SelectableCard/SelectableCard.doc.mjs +15 -0
- package/src/Selector/Selector.doc.mjs +25 -0
- package/src/Selector/Selector.test.tsx +322 -15
- package/src/Selector/Selector.tsx +126 -40
- package/src/Selector/hooks.ts +23 -0
- package/src/SideNav/SideNav.test.tsx +16 -0
- package/src/SideNav/SideNavItem.tsx +2 -4
- package/src/Skeleton/Skeleton.doc.mjs +11 -1
- package/src/Skeleton/Skeleton.test.tsx +25 -0
- package/src/Skeleton/Skeleton.tsx +11 -1
- package/src/Slider/Slider.doc.mjs +19 -0
- package/src/Slider/Slider.test.tsx +158 -18
- package/src/Slider/Slider.tsx +54 -6
- package/src/Spinner/Spinner.tsx +7 -1
- package/src/Stack/Stack.doc.mjs +77 -0
- package/src/Stack/Stack.test.tsx +55 -5
- package/src/Stack/Stack.tsx +73 -24
- package/src/Stack/StackItem.test.tsx +23 -0
- package/src/Stack/StackItem.tsx +20 -23
- package/src/Switch/Switch.doc.mjs +15 -0
- package/src/Switch/Switch.test.tsx +162 -27
- package/src/Switch/Switch.tsx +61 -21
- package/src/TabList/Tab.tsx +6 -0
- package/src/TabList/TabList.doc.mjs +12 -0
- package/src/TabList/TabList.test.tsx +208 -0
- package/src/TabList/TabList.tsx +102 -12
- package/src/TabList/TabListContext.ts +7 -3
- package/src/TabList/TabMenu.tsx +6 -3
- package/src/Table/BaseTable.tsx +72 -41
- package/src/Table/Table.doc.mjs +14 -0
- package/src/Table/Table.test.tsx +39 -30
- package/src/Table/Table.tsx +27 -1
- package/src/Table/TableCell.tsx +25 -23
- package/src/Table/TableHeaderCell.tsx +28 -29
- package/src/Table/TableRow.tsx +37 -7
- package/src/Table/index.ts +6 -2
- package/src/Table/plugins/pagination/paginateData.ts +10 -3
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +16 -0
- package/src/Table/plugins/pagination/useTablePagination.tsx +8 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +91 -2
- package/src/Table/plugins/sortable/useTableSortable.tsx +53 -1
- package/src/Table/plugins/stickyColumns/index.ts +4 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +407 -0
- package/src/Table/tableContextMenu.test.tsx +157 -0
- package/src/Table/tableContextMenu.tsx +142 -0
- package/src/Table/types.ts +175 -4
- package/src/Table/useBaseTablePlugins.ts +1 -0
- package/src/Table/useTableColumnResize.doc.mjs +96 -0
- package/src/Table/useTableStickyColumns.doc.mjs +59 -0
- package/src/Text/Heading.doc.mjs +15 -2
- package/src/Text/Text.doc.mjs +7 -1
- package/src/Text/text.stylex.ts +2 -2
- package/src/TextArea/TextArea.doc.mjs +17 -0
- package/src/TextArea/TextArea.test.tsx +167 -35
- package/src/TextArea/TextArea.tsx +62 -15
- package/src/TextInput/TextInput.doc.mjs +17 -0
- package/src/TextInput/TextInput.test.tsx +168 -34
- package/src/TextInput/TextInput.tsx +77 -9
- package/src/TimeInput/TimeInput.doc.mjs +335 -60
- package/src/TimeInput/TimeInput.test.tsx +144 -7
- package/src/TimeInput/TimeInput.tsx +74 -5
- package/src/Timestamp/Timestamp.doc.mjs +9 -0
- package/src/Timestamp/Timestamp.test.tsx +44 -18
- package/src/Timestamp/Timestamp.tsx +30 -10
- package/src/Toast/Toast.tsx +14 -0
- package/src/Toast/ToastViewport.test.tsx +204 -0
- package/src/Toast/ToastViewport.tsx +167 -21
- package/src/ToggleButton/ToggleButton.doc.mjs +9 -3
- package/src/ToggleButton/ToggleButton.test.tsx +39 -18
- package/src/ToggleButton/ToggleButton.tsx +46 -83
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -0
- package/src/Tokenizer/Tokenizer.test.tsx +105 -1
- package/src/Tokenizer/Tokenizer.tsx +41 -2
- package/src/Toolbar/Toolbar.doc.mjs +65 -5
- package/src/Toolbar/Toolbar.test.tsx +109 -6
- package/src/Toolbar/Toolbar.tsx +59 -5
- package/src/Tooltip/Tooltip.test.tsx +81 -0
- package/src/Tooltip/useTooltip.tsx +57 -11
- package/src/TreeList/TreeList.test.tsx +295 -6
- package/src/TreeList/TreeList.tsx +73 -1
- package/src/TreeList/TreeListItem.tsx +51 -5
- package/src/TreeList/treeListItem.markers.stylex.ts +20 -0
- package/src/Typeahead/BaseTypeahead.tsx +86 -9
- package/src/Typeahead/Typeahead.doc.mjs +136 -30
- package/src/Typeahead/Typeahead.test.tsx +331 -1
- package/src/Typeahead/Typeahead.tsx +52 -1
- package/src/VisuallyHidden/VisuallyHidden.doc.mjs +80 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +76 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +113 -0
- package/src/VisuallyHidden/index.ts +15 -0
- package/src/hooks/focusableSelector.ts +25 -0
- package/src/hooks/index.ts +28 -2
- package/src/hooks/useAnnounce.test.tsx +101 -0
- package/src/hooks/useAnnounce.ts +168 -0
- package/src/hooks/useClickableContainer.ts +16 -4
- package/src/hooks/useEntryAnimation.ts +16 -4
- package/src/hooks/useFocusTrap.test.tsx +132 -0
- package/src/hooks/useFocusTrap.ts +98 -4
- package/src/hooks/useGridFocus.doc.mjs +40 -2
- package/src/hooks/useGridFocus.test.tsx +132 -0
- package/src/hooks/useGridFocus.ts +343 -67
- package/src/hooks/useImageMode.test.ts +133 -0
- package/src/hooks/useKeyboardHint.doc.mjs +101 -0
- package/src/hooks/useKeyboardHint.test.tsx +70 -0
- package/src/hooks/useKeyboardHint.tsx +332 -0
- package/src/hooks/useListFocus.doc.mjs +50 -10
- package/src/hooks/useListFocus.test.tsx +375 -0
- package/src/hooks/useListFocus.ts +395 -57
- package/src/hooks/useLongPress.test.tsx +134 -0
- package/src/hooks/useLongPress.ts +119 -0
- package/src/hooks/useTreeFocus.doc.mjs +140 -0
- package/src/hooks/useTreeFocus.test.tsx +214 -0
- package/src/hooks/useTreeFocus.ts +559 -0
- package/src/hooks/useTypeahead.test.tsx +109 -0
- package/src/hooks/useTypeahead.ts +183 -0
- package/src/index.ts +1 -0
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/generateThemeRules.test.ts +7 -8
- package/src/theme/generateThemeRules.ts +1 -1
- package/src/theme/syntax/SyntaxTheme.tsx +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +20 -11
- package/src/theme/syntax/presets.ts +5 -2
- package/src/theme/syntax/tokens.ts +1 -1
- package/src/theme/types.ts +1 -1
- package/src/utils/dateTypes.test.ts +40 -0
- package/src/utils/dateTypes.ts +40 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/inputAria.test.ts +39 -0
- package/src/utils/inputAria.ts +58 -0
- package/src/utils/timeParser.test.ts +10 -0
- package/src/utils/timeParser.ts +5 -2
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts +0 -57
- package/dist/Calendar/hooks/useCalendarRovingTabindex.d.ts.map +0 -1
- package/dist/Calendar/hooks/useCalendarRovingTabindex.js +0 -96
- package/src/Calendar/hooks/useCalendarRovingTabindex.ts +0 -118
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file 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
|
*
|
|
@@ -22,6 +22,9 @@ import { colorVars, sizeVars, radiusVars, typographyVars, typeScaleVars, borderV
|
|
|
22
22
|
import { Field, inputWrapperStyles, inputStatusBorderStyles, inputStatusHoverShadowStyles, inputStatusFocusWithinStyles } from "../Field/index.js";
|
|
23
23
|
import { Icon, renderIconSlot } from "../Icon/index.js";
|
|
24
24
|
import { Spinner } from "../Spinner/index.js";
|
|
25
|
+
import { useTooltip } from "../Tooltip/index.js";
|
|
26
|
+
import { VisuallyHidden } from "../VisuallyHidden/index.js";
|
|
27
|
+
import { getInputARIA } from "../utils/index.js";
|
|
25
28
|
const sizeStyles = {
|
|
26
29
|
sm: {
|
|
27
30
|
kZKoxP: "x6k0iem",
|
|
@@ -45,7 +48,7 @@ import { useSize } from "../SizeContext/SizeContext.js";
|
|
|
45
48
|
import { useInputContainer } from "../hooks/useInputContainer.js";
|
|
46
49
|
import { useInputGroup } from "../InputGroup/InputGroupContext.js";
|
|
47
50
|
import { themeProps } from "../utils/themeProps.js";
|
|
48
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
51
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
49
52
|
/**
|
|
50
53
|
* A text input component for collecting user input.
|
|
51
54
|
*
|
|
@@ -63,6 +66,7 @@ export function TextInput({
|
|
|
63
66
|
isOptional = false,
|
|
64
67
|
isRequired = false,
|
|
65
68
|
isDisabled = false,
|
|
69
|
+
disabledMessage,
|
|
66
70
|
startIcon,
|
|
67
71
|
status,
|
|
68
72
|
size: sizeProp,
|
|
@@ -86,6 +90,7 @@ export function TextInput({
|
|
|
86
90
|
}) {
|
|
87
91
|
const size = useSize(sizeProp, 'md');
|
|
88
92
|
const id = useId();
|
|
93
|
+
const inputLabelID = useId();
|
|
89
94
|
const descriptionID = useId();
|
|
90
95
|
const statusMessageID = useId();
|
|
91
96
|
const inputRef = useRef(null);
|
|
@@ -94,6 +99,20 @@ export function TextInput({
|
|
|
94
99
|
const [, startTransition] = useTransition();
|
|
95
100
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
96
101
|
const isBusy = isLoading || optimisticValue !== value;
|
|
102
|
+
|
|
103
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
104
|
+
// tooltip listeners attach to the input container (which already exists) and
|
|
105
|
+
// the input stays perceivable via aria-disabled instead of the native
|
|
106
|
+
// disabled attribute. The field is made read-only so it can't be typed into,
|
|
107
|
+
// and value mutation is blocked by the isDisabled guard in handleChange.
|
|
108
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
109
|
+
const disabledMessageTooltip = useTooltip({
|
|
110
|
+
placement: 'above',
|
|
111
|
+
// The container div is not naturally focusable; focusin bubbles up from
|
|
112
|
+
// the input, so always attach focus listeners.
|
|
113
|
+
focusTrigger: 'always',
|
|
114
|
+
isEnabled: showsDisabledMessage
|
|
115
|
+
});
|
|
97
116
|
const statusIconMap = {
|
|
98
117
|
warning: 'warning',
|
|
99
118
|
error: 'error',
|
|
@@ -104,8 +123,17 @@ export function TextInput({
|
|
|
104
123
|
error: 'error',
|
|
105
124
|
success: 'success'
|
|
106
125
|
};
|
|
107
|
-
const
|
|
126
|
+
const {
|
|
127
|
+
ariaLabelledBy,
|
|
128
|
+
ariaDescribedBy
|
|
129
|
+
} = getInputARIA(inputLabelID, [description ? descriptionID : null, status?.message ? statusMessageID : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null], inputGroup);
|
|
108
130
|
const handleChange = e => {
|
|
131
|
+
// Value can't change while showing a disabled message (the field is
|
|
132
|
+
// read-only and non-native-disabled), but guard the handler too so the
|
|
133
|
+
// optimistic value and callbacks never fire.
|
|
134
|
+
if (isDisabled) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
109
137
|
const newValue = e.target.value;
|
|
110
138
|
onChange?.(newValue, e);
|
|
111
139
|
if (changeAction && !e.defaultPrevented) {
|
|
@@ -132,7 +160,13 @@ export function TextInput({
|
|
|
132
160
|
disabled: isDisabled
|
|
133
161
|
});
|
|
134
162
|
const inputWrapper = /*#__PURE__*/_jsxs("div", {
|
|
135
|
-
ref:
|
|
163
|
+
ref: el => {
|
|
164
|
+
containerRef.current = el;
|
|
165
|
+
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
166
|
+
// Handlers are gated internally by isEnabled, and anchor names
|
|
167
|
+
// compose, so attaching unconditionally is safe.
|
|
168
|
+
disabledMessageTooltip.ref(el);
|
|
169
|
+
},
|
|
136
170
|
onClick: handleWrapperClick,
|
|
137
171
|
onMouseUp: handleWrapperMouseUp,
|
|
138
172
|
...mergeProps(themeProps('text-input', {
|
|
@@ -142,6 +176,9 @@ export function TextInput({
|
|
|
142
176
|
children: [startIcon && renderIconSlot(startIcon, {
|
|
143
177
|
size: 'sm',
|
|
144
178
|
color: 'secondary'
|
|
179
|
+
}), inputGroup && /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
180
|
+
id: inputLabelID,
|
|
181
|
+
children: label
|
|
145
182
|
}), /*#__PURE__*/_jsx("input", {
|
|
146
183
|
...rest,
|
|
147
184
|
ref: mergeRefs(ref, inputRef),
|
|
@@ -156,15 +193,21 @@ export function TextInput({
|
|
|
156
193
|
}
|
|
157
194
|
onKeyDown?.(e);
|
|
158
195
|
} : undefined,
|
|
159
|
-
placeholder: placeholder
|
|
160
|
-
disabled
|
|
196
|
+
placeholder: placeholder
|
|
197
|
+
// With a disabledMessage the input keeps focusability via aria-disabled
|
|
198
|
+
// so the reason is focus-discoverable; readOnly + the handleChange guard
|
|
199
|
+
// keep the value from changing.
|
|
200
|
+
,
|
|
201
|
+
disabled: isDisabled && !showsDisabledMessage,
|
|
202
|
+
"aria-disabled": showsDisabledMessage ? 'true' : undefined,
|
|
203
|
+
readOnly: showsDisabledMessage || undefined,
|
|
161
204
|
autoFocus: hasAutoFocus,
|
|
162
205
|
"data-autofocus": hasAutoFocus || undefined,
|
|
163
206
|
"aria-describedby": ariaDescribedBy,
|
|
164
207
|
"aria-required": isRequired === true ? 'true' : undefined,
|
|
165
208
|
"aria-invalid": status?.type === 'error' ? 'true' : undefined,
|
|
166
209
|
"aria-busy": isBusy || undefined,
|
|
167
|
-
"aria-
|
|
210
|
+
"aria-labelledby": ariaLabelledBy,
|
|
168
211
|
...{
|
|
169
212
|
0: {
|
|
170
213
|
className: "x1lliihq x98rzlu xeuugli xc342km xng3xce x1717udv x9ynric xjm74w1 x6pjikd xw6l6zx x1tgivj0 xjbqb8w x1a2a7pz xeyghm5"
|
|
@@ -194,9 +237,11 @@ export function TextInput({
|
|
|
194
237
|
})]
|
|
195
238
|
});
|
|
196
239
|
if (inputGroup) {
|
|
197
|
-
return
|
|
240
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
241
|
+
children: [inputWrapper, showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
242
|
+
});
|
|
198
243
|
}
|
|
199
|
-
return /*#__PURE__*/
|
|
244
|
+
return /*#__PURE__*/_jsxs(Field, {
|
|
200
245
|
label: label,
|
|
201
246
|
isLabelHidden: isLabelHidden,
|
|
202
247
|
description: description,
|
|
@@ -212,7 +257,7 @@ export function TextInput({
|
|
|
212
257
|
} : undefined,
|
|
213
258
|
labelTooltip: labelTooltip,
|
|
214
259
|
width: width,
|
|
215
|
-
children: inputWrapper
|
|
260
|
+
children: [inputWrapper, showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
216
261
|
});
|
|
217
262
|
}
|
|
218
263
|
TextInput.displayName = 'TextInput';
|
|
@@ -51,6 +51,28 @@ export interface TimeInputProps extends Omit<BaseProps, 'onChange' | 'defaultVal
|
|
|
51
51
|
* @default false
|
|
52
52
|
*/
|
|
53
53
|
isDisabled?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Explains why the input is disabled. When set together with
|
|
56
|
+
* `isDisabled`, the input shows a tooltip with this text on hover and
|
|
57
|
+
* keyboard focus, and the field stays focusable (via `aria-disabled`)
|
|
58
|
+
* so the reason is discoverable by keyboard and assistive technology.
|
|
59
|
+
* Typing and arrow-key adjustment stay blocked.
|
|
60
|
+
*
|
|
61
|
+
* Use this instead of wrapping a disabled input in `Tooltip` — disabled
|
|
62
|
+
* controls don't emit the pointer events an external tooltip needs.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```
|
|
66
|
+
* <TimeInput
|
|
67
|
+
* label="Start time"
|
|
68
|
+
* value={time}
|
|
69
|
+
* onChange={setTime}
|
|
70
|
+
* isDisabled
|
|
71
|
+
* disabledMessage="You need the Editor role to change this"
|
|
72
|
+
* />
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
disabledMessage?: string;
|
|
54
76
|
/**
|
|
55
77
|
* The selected time in ISO format (HH:MM or HH:MM:SS).
|
|
56
78
|
*/
|
|
@@ -147,7 +169,7 @@ export interface TimeInputProps extends Omit<BaseProps, 'onChange' | 'defaultVal
|
|
|
147
169
|
* />
|
|
148
170
|
* ```
|
|
149
171
|
*/
|
|
150
|
-
export declare function TimeInput({ label, isLabelHidden, description, isOptional, isRequired, isDisabled, value, onChange, changeAction, isLoading, min, max, hasSeconds, hasClear, hasAutoFocus, hourFormat, increment, placeholder, size: sizeProp, status, labelTooltip, width, xstyle, className, style, ref, }: TimeInputProps): import("react").JSX.Element;
|
|
172
|
+
export declare function TimeInput({ label, isLabelHidden, description, isOptional, isRequired, isDisabled, disabledMessage, value, onChange, changeAction, isLoading, min, max, hasSeconds, hasClear, hasAutoFocus, hourFormat, increment, placeholder, size: sizeProp, status, labelTooltip, width, xstyle, className, style, ref, }: TimeInputProps): import("react").JSX.Element;
|
|
151
173
|
export declare namespace TimeInput {
|
|
152
174
|
var displayName: string;
|
|
153
175
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeInput.d.ts","sourceRoot":"","sources":["../../src/TimeInput/TimeInput.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAU3C,OAAO,EAEL,KAAK,WAAW,EAMjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,KAAK,aAAa,EASnB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"TimeInput.d.ts","sourceRoot":"","sources":["../../src/TimeInput/TimeInput.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAU3C,OAAO,EAEL,KAAK,WAAW,EAMjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,KAAK,aAAa,EASnB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AA0D9C,QAAA,MAAM,UAAU;;;;;;;;;;;;;EAad,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,UAAU,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,KAAK,CAAC;AAIhD,YAAY,EACV,WAAW,IAAI,eAAe,EAC9B,eAAe,IAAI,mBAAmB,GACvC,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,UAAU,GAAG,cAAc,CAC5B;IACC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IAEtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,KAAK,IAAI,CAAC;IAEtD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;OAEG;IACH,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAEjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,UAAkB,EAClB,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,SAAa,EACb,WAA6B,EAC7B,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,YAAY,EACZ,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,GACJ,EAAE,cAAc,+BA6ThB;yBAzVe,SAAS"}
|
|
@@ -25,6 +25,7 @@ import { Spinner } from "../Spinner/index.js";
|
|
|
25
25
|
import { parseTimeInput, formatDisplayTime12h, formatDisplayTime24h, formatISOTime, adjustTime, isTimeInRange, mergeProps, mergeRefs } from "../utils/index.js";
|
|
26
26
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
27
27
|
import { useInputContainer } from "../hooks/useInputContainer.js";
|
|
28
|
+
import { useTooltip } from "../Tooltip/index.js";
|
|
28
29
|
import { themeProps } from "../utils/themeProps.js";
|
|
29
30
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
30
31
|
const sizeStyles = {
|
|
@@ -68,6 +69,7 @@ export function TimeInput({
|
|
|
68
69
|
isOptional = false,
|
|
69
70
|
isRequired = false,
|
|
70
71
|
isDisabled = false,
|
|
72
|
+
disabledMessage,
|
|
71
73
|
value,
|
|
72
74
|
onChange,
|
|
73
75
|
changeAction,
|
|
@@ -99,6 +101,19 @@ export function TimeInput({
|
|
|
99
101
|
const [optimisticValue, setOptimisticValue] = useOptimistic(value);
|
|
100
102
|
const isBusy = isLoading || optimisticValue !== value;
|
|
101
103
|
|
|
104
|
+
// Disabled-reason tooltip. Disabled controls swallow pointer events, so the
|
|
105
|
+
// tooltip listeners attach to the input container (which already exists) and
|
|
106
|
+
// the input stays perceivable via aria-disabled instead of the disabled
|
|
107
|
+
// attribute. Typing is blocked with readOnly and value mutation guards.
|
|
108
|
+
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
109
|
+
const disabledMessageTooltip = useTooltip({
|
|
110
|
+
placement: 'above',
|
|
111
|
+
// The container div is not naturally focusable; focusin bubbles up from
|
|
112
|
+
// the input, so always attach focus listeners.
|
|
113
|
+
focusTrigger: 'always',
|
|
114
|
+
isEnabled: showsDisabledMessage
|
|
115
|
+
});
|
|
116
|
+
|
|
102
117
|
// Status icon mapping
|
|
103
118
|
const statusIconMap = {
|
|
104
119
|
warning: 'warning',
|
|
@@ -110,7 +125,7 @@ export function TimeInput({
|
|
|
110
125
|
error: 'error',
|
|
111
126
|
success: 'success'
|
|
112
127
|
};
|
|
113
|
-
const ariaDescribedBy = [description ? descriptionID : null, status?.message ? statusMessageID : null].filter(Boolean).join(' ') || undefined;
|
|
128
|
+
const ariaDescribedBy = [description ? descriptionID : null, status?.message ? statusMessageID : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null].filter(Boolean).join(' ') || undefined;
|
|
114
129
|
|
|
115
130
|
// Pending input while user is typing (null = show formatted value)
|
|
116
131
|
const [pendingInput, setPendingInput] = useState(null);
|
|
@@ -162,6 +177,11 @@ export function TimeInput({
|
|
|
162
177
|
|
|
163
178
|
// Handle input text change - update immediately if valid
|
|
164
179
|
const handleInputChange = useCallback(e => {
|
|
180
|
+
// With a disabledMessage the input drops `disabled` for focusability, so
|
|
181
|
+
// guard value mutation explicitly (readOnly also blocks typing).
|
|
182
|
+
if (isDisabled) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
165
185
|
const newValue = e.target.value;
|
|
166
186
|
setPendingInput(newValue);
|
|
167
187
|
|
|
@@ -170,12 +190,18 @@ export function TimeInput({
|
|
|
170
190
|
if (parsed && isTimeInRange(parsed, min, max) && parsed !== value) {
|
|
171
191
|
fireChange(parsed);
|
|
172
192
|
}
|
|
173
|
-
}, [hasSeconds, min, max, value, fireChange]);
|
|
193
|
+
}, [hasSeconds, min, max, value, fireChange, isDisabled]);
|
|
174
194
|
|
|
175
195
|
// Handle focus
|
|
176
196
|
const handleFocus = useCallback(() => {
|
|
197
|
+
// A disabled input stays focusable (via aria-disabled) so its reason is
|
|
198
|
+
// discoverable, but it must not present editing affordances — keep the
|
|
199
|
+
// static placeholder rather than swapping in the format hint.
|
|
200
|
+
if (isDisabled) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
177
203
|
setIsFocused(true);
|
|
178
|
-
}, []);
|
|
204
|
+
}, [isDisabled]);
|
|
179
205
|
|
|
180
206
|
// Handle blur - validate and clear pending input
|
|
181
207
|
const handleBlur = useCallback(_e => {
|
|
@@ -204,6 +230,11 @@ export function TimeInput({
|
|
|
204
230
|
|
|
205
231
|
// Handle keyboard navigation on input
|
|
206
232
|
const handleInputKeyDown = useCallback(e => {
|
|
233
|
+
// Arrow-key adjustment mutates the value; block it while showing a
|
|
234
|
+
// disabled reason (the input keeps focusability via aria-disabled).
|
|
235
|
+
if (isDisabled) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
207
238
|
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
208
239
|
e.preventDefault();
|
|
209
240
|
|
|
@@ -225,7 +256,7 @@ export function TimeInput({
|
|
|
225
256
|
fireChange(newTime);
|
|
226
257
|
}
|
|
227
258
|
}
|
|
228
|
-
}, [value, hasSeconds, increment, min, max, fireChange]);
|
|
259
|
+
}, [value, hasSeconds, increment, min, max, fireChange, isDisabled]);
|
|
229
260
|
|
|
230
261
|
// Handle clear button click
|
|
231
262
|
const handleClear = useCallback(() => {
|
|
@@ -242,7 +273,7 @@ export function TimeInput({
|
|
|
242
273
|
inputRef,
|
|
243
274
|
disabled: isDisabled
|
|
244
275
|
});
|
|
245
|
-
return /*#__PURE__*/
|
|
276
|
+
return /*#__PURE__*/_jsxs(Field, {
|
|
246
277
|
label: label,
|
|
247
278
|
isLabelHidden: isLabelHidden,
|
|
248
279
|
description: description,
|
|
@@ -258,8 +289,14 @@ export function TimeInput({
|
|
|
258
289
|
} : undefined,
|
|
259
290
|
labelTooltip: labelTooltip,
|
|
260
291
|
width: width,
|
|
261
|
-
children: /*#__PURE__*/_jsxs("div", {
|
|
262
|
-
ref:
|
|
292
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
293
|
+
ref: el => {
|
|
294
|
+
containerRef.current = el;
|
|
295
|
+
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
296
|
+
// Handlers are gated internally by isEnabled, so attaching
|
|
297
|
+
// unconditionally is safe.
|
|
298
|
+
disabledMessageTooltip.ref(el);
|
|
299
|
+
},
|
|
263
300
|
onClick: handleWrapperClick,
|
|
264
301
|
onMouseUp: handleWrapperMouseUp,
|
|
265
302
|
...mergeProps(themeProps('time-input', {
|
|
@@ -284,8 +321,14 @@ export function TimeInput({
|
|
|
284
321
|
onFocus: handleFocus,
|
|
285
322
|
onBlur: handleBlur,
|
|
286
323
|
onKeyDown: handleInputKeyDown,
|
|
287
|
-
placeholder: displayPlaceholder
|
|
288
|
-
|
|
324
|
+
placeholder: displayPlaceholder
|
|
325
|
+
// With a disabledMessage the input keeps focusability via
|
|
326
|
+
// aria-disabled so the reason is focus-discoverable; typing and
|
|
327
|
+
// arrow-key adjustment are blocked with readOnly and the guards.
|
|
328
|
+
,
|
|
329
|
+
disabled: isDisabled && !showsDisabledMessage,
|
|
330
|
+
"aria-disabled": showsDisabledMessage ? 'true' : undefined,
|
|
331
|
+
readOnly: showsDisabledMessage || undefined,
|
|
289
332
|
autoFocus: hasAutoFocus,
|
|
290
333
|
"data-autofocus": hasAutoFocus || undefined,
|
|
291
334
|
"aria-describedby": ariaDescribedBy,
|
|
@@ -325,7 +368,7 @@ export function TimeInput({
|
|
|
325
368
|
size: "md",
|
|
326
369
|
color: statusIconColorMap[status.type]
|
|
327
370
|
})]
|
|
328
|
-
})
|
|
371
|
+
}), showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
329
372
|
});
|
|
330
373
|
}
|
|
331
374
|
TimeInput.displayName = 'TimeInput';
|
|
@@ -8,7 +8,7 @@ export interface TimestampProps extends BaseProps<HTMLTimeElement> {
|
|
|
8
8
|
value: string | number;
|
|
9
9
|
/**
|
|
10
10
|
* Display format.
|
|
11
|
-
* - `'relative'`: "2 hours ago", "yesterday", "
|
|
11
|
+
* - `'relative'`: "2 hours ago", "yesterday", "now"
|
|
12
12
|
* - `'auto'`: Relative for recent times, `date_time` for older
|
|
13
13
|
* - `'date'`: "Mar 21, 2025"
|
|
14
14
|
* - `'date_time'`: "Mar 21, 2025, 2:51 PM"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../src/Timestamp/Timestamp.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Timestamp.d.ts","sourceRoot":"","sources":["../../src/Timestamp/Timestamp.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE9E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,MAAM,MAAM,eAAe,GACvB,UAAU,GACV,MAAM,GACN,MAAM,GACN,WAAW,GACX,MAAM,GACN,aAAa,GACb,kBAAkB,GAClB,aAAa,CAAC;AAElB,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,eAAe,CAAC;IAChE,kDAAkD;IAClD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC,uFAAuF;IACvF,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;OAEG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA8ND;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,MAAe,EACf,aAAsC,EACtC,UAAiB,EACjB,eAAuB,EACvB,MAAc,EACd,IAAmB,EACnB,IAAI,EACJ,KAAmB,EACnB,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,aAAa,EAAE,MAAM,GACtB,EAAE,cAAc,+BAqFhB;yBArGe,SAAS"}
|
|
@@ -45,6 +45,18 @@ const YEAR = 365 * DAY;
|
|
|
45
45
|
|
|
46
46
|
/** Default auto threshold: 7 days in seconds */
|
|
47
47
|
const DEFAULT_AUTO_THRESHOLD = 7 * DAY;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tolerance (in seconds) for treating a *future* timestamp as the present.
|
|
51
|
+
* A value only a handful of seconds ahead of our reference clock is almost
|
|
52
|
+
* always clock skew — the displayed `now` lagging the real clock, or the value
|
|
53
|
+
* being produced on a slightly faster clock — not a genuine future event, so
|
|
54
|
+
* it reads as "now" rather than a confusing "in a few seconds". The future
|
|
55
|
+
* side gets a wider window than the past (which only needs to absorb the
|
|
56
|
+
* sub-second render-time lag) because future drift is far more likely to be
|
|
57
|
+
* skew than real.
|
|
58
|
+
*/
|
|
59
|
+
const FUTURE_SKEW_TOLERANCE = 30;
|
|
48
60
|
function parseValue(value) {
|
|
49
61
|
if (typeof value === 'number') {
|
|
50
62
|
// Heuristic: if the number is less than 1e12, treat as seconds; otherwise ms.
|
|
@@ -55,9 +67,25 @@ function parseValue(value) {
|
|
|
55
67
|
}
|
|
56
68
|
function getRelativeTimeString(date, now) {
|
|
57
69
|
const diffSeconds = Math.round((now.getTime() - date.getTime()) / 1000);
|
|
70
|
+
|
|
71
|
+
// Treat values at (or a hair before/after) the present as "now". The
|
|
72
|
+
// internal `now` reference is captured at render time, so it can lag the
|
|
73
|
+
// real clock; a value equal to "right now" can land a fraction of a second
|
|
74
|
+
// in the future and round to a small negative delta. Without this clamp,
|
|
75
|
+
// such values fall into the future branch and render "in a few seconds".
|
|
76
|
+
if (Math.abs(diffSeconds) < 10) {
|
|
77
|
+
return 'now';
|
|
78
|
+
}
|
|
58
79
|
if (diffSeconds < 0) {
|
|
59
80
|
// Future dates
|
|
60
81
|
const absDiff = Math.abs(diffSeconds);
|
|
82
|
+
// A value only a few seconds ahead of our clock is almost always skew, not
|
|
83
|
+
// a genuine future event — render it as the present rather than a
|
|
84
|
+
// confusing "in a few seconds". Wider than the past window above on
|
|
85
|
+
// purpose (see FUTURE_SKEW_TOLERANCE).
|
|
86
|
+
if (absDiff <= FUTURE_SKEW_TOLERANCE) {
|
|
87
|
+
return 'now';
|
|
88
|
+
}
|
|
61
89
|
if (absDiff < MINUTE) {
|
|
62
90
|
return 'in a few seconds';
|
|
63
91
|
}
|
|
@@ -80,9 +108,6 @@ function getRelativeTimeString(date, now) {
|
|
|
80
108
|
const years = Math.round(absDiff / YEAR);
|
|
81
109
|
return `in ${years} ${years === 1 ? 'year' : 'years'}`;
|
|
82
110
|
}
|
|
83
|
-
if (diffSeconds < 10) {
|
|
84
|
-
return 'just now';
|
|
85
|
-
}
|
|
86
111
|
if (diffSeconds < MINUTE) {
|
|
87
112
|
return `${diffSeconds} seconds ago`;
|
|
88
113
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/Toast/Toast.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAiBrC,OAAO,KAAK,EAAC,SAAS,EAAE,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAyD3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAiB,EACjB,SAAS,GACV,EAAE,UAAU,+
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/Toast/Toast.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAiBrC,OAAO,KAAK,EAAC,SAAS,EAAE,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAyD3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,IAAI,EACJ,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAiB,EACjB,SAAS,GACV,EAAE,UAAU,+BAiHZ;yBAzHe,KAAK"}
|
package/dist/Toast/Toast.js
CHANGED
|
@@ -88,6 +88,20 @@ export function Toast({
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
}, [autoHideDuration, startTimer]);
|
|
91
|
+
|
|
92
|
+
// Pause the auto-hide timer while the window is not focused, so a toast
|
|
93
|
+
// doesn't silently expire while the user is in another window or tab.
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!isAutoHide) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
window.addEventListener('blur', pauseTimer);
|
|
99
|
+
window.addEventListener('focus', resumeTimer);
|
|
100
|
+
return () => {
|
|
101
|
+
window.removeEventListener('blur', pauseTimer);
|
|
102
|
+
window.removeEventListener('focus', resumeTimer);
|
|
103
|
+
};
|
|
104
|
+
}, [isAutoHide, pauseTimer, resumeTimer]);
|
|
91
105
|
const handleDismiss = useCallback(() => {
|
|
92
106
|
onDismiss('manual');
|
|
93
107
|
}, [onDismiss]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToastViewport.d.ts","sourceRoot":"","sources":["../../src/Toast/ToastViewport.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ToastViewport.d.ts","sourceRoot":"","sources":["../../src/Toast/ToastViewport.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAa,aAAa,EAAqB,MAAM,SAAS,CAAC;AA2D3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;IACtE;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAsB,EACtB,UAAc,EACd,KAAK,EACL,UAAiB,EACjB,QAAQ,GACT,EAAE,kBAAkB,+BAqSpB;yBA3Se,aAAa"}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
'use client';
|
|
4
4
|
|
|
5
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import * as stylex from '@stylexjs/stylex';
|
|
7
7
|
import "../theme/tokens.stylex.js";
|
|
8
8
|
import { spacingVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
|
|
9
9
|
import { mergeProps } from "../utils/index.js";
|
|
10
|
+
import { INTERACTIVE_SELECTORS } from "../hooks/useClickableContainer.js";
|
|
10
11
|
import { Toast } from "./Toast.js";
|
|
11
12
|
import { ToastContext } from "./ToastContext.js";
|
|
12
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -74,6 +75,39 @@ export function ToastViewport({
|
|
|
74
75
|
const [exitingIds, setExitingIds] = useState(new Set());
|
|
75
76
|
const toastsRef = useRef(toasts);
|
|
76
77
|
toastsRef.current = toasts;
|
|
78
|
+
|
|
79
|
+
// Show the popover on mount so it enters the top layer.
|
|
80
|
+
const viewportRef = useRef(null);
|
|
81
|
+
// The element that was focused before the user jumped into the viewport
|
|
82
|
+
// (via F6). Used to restore focus once all toasts are dismissed so focus
|
|
83
|
+
// never falls to <body>.
|
|
84
|
+
const prevFocusRef = useRef(null);
|
|
85
|
+
// When a toast is dismissed while focus lives inside it, we need to move
|
|
86
|
+
// focus to a sensible neighbor after that toast unmounts. This holds the
|
|
87
|
+
// id of the toast whose removal should trigger a focus handoff.
|
|
88
|
+
const focusHandoffIdRef = useRef(null);
|
|
89
|
+
// The next toast id that should receive focus once the dismissed toast has
|
|
90
|
+
// unmounted, or 'restore' to fall back to the previously-focused element.
|
|
91
|
+
const pendingFocusRef = useRef(null);
|
|
92
|
+
|
|
93
|
+
// Collect a focusable control within a toast node, if any.
|
|
94
|
+
// Reuses the canonical INTERACTIVE_SELECTORS list (native controls plus
|
|
95
|
+
// role-based interactive elements) instead of a hand-rolled subset, then
|
|
96
|
+
// narrows to the first candidate that can actually receive focus —
|
|
97
|
+
// excluding elements opted out with `tabindex="-1"` and disabled controls.
|
|
98
|
+
const getFocusable = useCallback(container => {
|
|
99
|
+
if (!container) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const candidates = container.querySelectorAll(INTERACTIVE_SELECTORS);
|
|
103
|
+
for (const candidate of candidates) {
|
|
104
|
+
if (candidate.getAttribute('tabindex') === '-1' || candidate.hasAttribute('disabled') || candidate.getAttribute('aria-disabled') === 'true') {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
return candidate;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}, []);
|
|
77
111
|
const addToast = useCallback(entry => {
|
|
78
112
|
setToasts(prev => {
|
|
79
113
|
const {
|
|
@@ -97,6 +131,25 @@ export function ToastViewport({
|
|
|
97
131
|
if (entry) {
|
|
98
132
|
entry.options.onHide?.(reason);
|
|
99
133
|
}
|
|
134
|
+
// If focus currently lives inside the toast being dismissed, remember
|
|
135
|
+
// that its removal must hand focus off to a neighbor (or the element
|
|
136
|
+
// focused before the user entered the viewport) rather than <body>.
|
|
137
|
+
const el = viewportRef.current;
|
|
138
|
+
const active = document.activeElement;
|
|
139
|
+
const dismissedNode = el?.querySelector(`[data-toast-id="${id}"]`) ?? null;
|
|
140
|
+
if (dismissedNode && active instanceof Node && dismissedNode.contains(active)) {
|
|
141
|
+
focusHandoffIdRef.current = id;
|
|
142
|
+
// Pick the neighbor to receive focus while the DOM is still intact:
|
|
143
|
+
// prefer the next toast, then the previous, else restore.
|
|
144
|
+
const remaining = toastsRef.current.filter(t => t.id !== id);
|
|
145
|
+
if (remaining.length > 0) {
|
|
146
|
+
const dismissedIndex = toastsRef.current.findIndex(t => t.id === id);
|
|
147
|
+
const next = toastsRef.current[dismissedIndex + 1] ?? toastsRef.current[dismissedIndex - 1];
|
|
148
|
+
pendingFocusRef.current = next ? next.id : 'restore';
|
|
149
|
+
} else {
|
|
150
|
+
pendingFocusRef.current = 'restore';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
100
153
|
setExitingIds(prev => {
|
|
101
154
|
if (prev.has(id)) {
|
|
102
155
|
return prev;
|
|
@@ -115,6 +168,41 @@ export function ToastViewport({
|
|
|
115
168
|
});
|
|
116
169
|
setToasts(prev => prev.filter(t => t.id !== id));
|
|
117
170
|
}, []);
|
|
171
|
+
|
|
172
|
+
// After a dismissed toast unmounts, hand focus off so it never falls to
|
|
173
|
+
// <body>. Runs in a layout effect once the toast list no longer contains
|
|
174
|
+
// the dismissed toast.
|
|
175
|
+
useLayoutEffect(() => {
|
|
176
|
+
const handoffId = focusHandoffIdRef.current;
|
|
177
|
+
const target = pendingFocusRef.current;
|
|
178
|
+
if (handoffId == null || target == null) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Wait until the dismissed toast is actually gone from the list.
|
|
182
|
+
if (toasts.some(t => t.id === handoffId)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
focusHandoffIdRef.current = null;
|
|
186
|
+
pendingFocusRef.current = null;
|
|
187
|
+
const el = viewportRef.current;
|
|
188
|
+
if (target !== 'restore' && el) {
|
|
189
|
+
const nextNode = el.querySelector(`[data-toast-id="${target}"]`);
|
|
190
|
+
const focusable = getFocusable(nextNode) ?? nextNode;
|
|
191
|
+
if (focusable) {
|
|
192
|
+
focusable.focus();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// No remaining toast to receive focus — restore the previously-focused
|
|
197
|
+
// element if it's still connected, else fall back to the container.
|
|
198
|
+
const prev = prevFocusRef.current;
|
|
199
|
+
prevFocusRef.current = null;
|
|
200
|
+
if (prev && prev.isConnected) {
|
|
201
|
+
prev.focus();
|
|
202
|
+
} else if (el) {
|
|
203
|
+
el.focus();
|
|
204
|
+
}
|
|
205
|
+
}, [toasts, getFocusable]);
|
|
118
206
|
const findByUniqueID = useCallback(uid => {
|
|
119
207
|
return toastsRef.current.find(t => t.options.uniqueID === uid);
|
|
120
208
|
}, []);
|
|
@@ -139,7 +227,6 @@ export function ToastViewport({
|
|
|
139
227
|
}
|
|
140
228
|
|
|
141
229
|
// Show the popover on mount so it enters the top layer
|
|
142
|
-
const viewportRef = useRef(null);
|
|
143
230
|
useEffect(() => {
|
|
144
231
|
if (!isTopLayer) {
|
|
145
232
|
return;
|
|
@@ -153,13 +240,54 @@ export function ToastViewport({
|
|
|
153
240
|
}
|
|
154
241
|
}
|
|
155
242
|
}, [isTopLayer]);
|
|
243
|
+
|
|
244
|
+
// F6 jumps focus into the toast viewport — the standard "go to
|
|
245
|
+
// notifications" affordance. Focus the first control in the newest toast,
|
|
246
|
+
// or the viewport container if none. Toasts are non-modal, so this only
|
|
247
|
+
// moves focus in; Shift+Tab / Escape let focus leave naturally.
|
|
248
|
+
const hasToasts = toasts.length > 0;
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
if (!hasToasts) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const handleKeyDown = e => {
|
|
254
|
+
if (e.key !== 'F6') {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const el = viewportRef.current;
|
|
258
|
+
if (!el) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
// Already inside the viewport — nothing to do.
|
|
262
|
+
const active = document.activeElement;
|
|
263
|
+
if (active instanceof Node && el.contains(active)) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
e.preventDefault();
|
|
267
|
+
// Remember where focus was so it can be restored on dismiss.
|
|
268
|
+
if (active instanceof HTMLElement) {
|
|
269
|
+
prevFocusRef.current = active;
|
|
270
|
+
}
|
|
271
|
+
// Newest toast is the last one rendered in the DOM.
|
|
272
|
+
const toastNodes = el.querySelectorAll('[data-toast-id]');
|
|
273
|
+
const newest = toastNodes[toastNodes.length - 1] ?? null;
|
|
274
|
+
const focusable = getFocusable(newest) ?? newest ?? el;
|
|
275
|
+
focusable.focus();
|
|
276
|
+
};
|
|
277
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
278
|
+
return () => {
|
|
279
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
280
|
+
};
|
|
281
|
+
}, [hasToasts, getFocusable]);
|
|
156
282
|
const posStyle = position === 'topEnd' ? styles.topEnd : position === 'topStart' ? styles.topStart : position === 'bottomStart' ? styles.bottomStart : styles.bottomEnd;
|
|
157
283
|
return /*#__PURE__*/_jsxs(ToastContext, {
|
|
158
284
|
value: contextValue,
|
|
159
285
|
children: [children, /*#__PURE__*/_jsx("div", {
|
|
160
286
|
ref: viewportRef,
|
|
161
287
|
role: "region",
|
|
162
|
-
"aria-label": "Notifications"
|
|
288
|
+
"aria-label": "Notifications",
|
|
289
|
+
"aria-modal": false,
|
|
290
|
+
tabIndex: -1
|
|
163
291
|
// popover="manual" promotes to the top layer (above dialogs).
|
|
164
292
|
// Omitted inside dialogs where the viewport is already in a top layer.
|
|
165
293
|
,
|
|
@@ -174,6 +302,7 @@ export function ToastViewport({
|
|
|
174
302
|
const dur = o.autoHideDuration ?? 5000;
|
|
175
303
|
const isExiting = exitingIds.has(entry.id);
|
|
176
304
|
return /*#__PURE__*/_jsx("div", {
|
|
305
|
+
"data-toast-id": entry.id,
|
|
177
306
|
...{
|
|
178
307
|
0: {
|
|
179
308
|
className: "x67bb7w xrvj5dj x1tu4anv xvmdzux xjshnde xuedmi6 xsagj69 xlr8y92 x1sopeo2 x5rzir7"
|