@astryxdesign/core 0.1.3 → 0.1.4-canary.01e5b29
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 +51 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +20 -18
- package/dist/AlertDialog/useImperativeAlertDialog.js +3 -3
- package/dist/AppShell/AppShell.d.ts +1 -1
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +55 -53
- package/dist/AspectRatio/AspectRatio.js +5 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +27 -25
- package/dist/Avatar/AvatarStatusDot.js +5 -5
- package/dist/AvatarGroup/AvatarGroup.js +5 -5
- package/dist/AvatarGroup/AvatarGroupOverflow.js +5 -5
- package/dist/Badge/Badge.js +3 -3
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +32 -25
- package/dist/Blockquote/Blockquote.js +7 -7
- package/dist/Breadcrumbs/BreadcrumbItem.js +17 -17
- package/dist/Breadcrumbs/Breadcrumbs.js +7 -7
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +47 -26
- package/dist/ButtonGroup/ButtonGroup.js +7 -7
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +108 -64
- package/dist/Calendar/dayCellUtils.d.ts +67 -5
- package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
- package/dist/Calendar/dayCellUtils.js +139 -18
- package/dist/Calendar/styles.d.ts +2 -2
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +2 -2
- package/dist/Card/Card.d.ts +4 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +18 -10
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +20 -19
- package/dist/Center/Center.js +3 -3
- package/dist/Chat/ChatComposer.js +23 -23
- package/dist/Chat/ChatComposerDrawer.js +14 -14
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +27 -15
- package/dist/Chat/ChatDictationButton.d.ts +1 -1
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +13 -11
- package/dist/Chat/ChatLayout.js +17 -17
- package/dist/Chat/ChatLayoutScrollButton.d.ts +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +12 -10
- package/dist/Chat/ChatMessage.js +12 -12
- package/dist/Chat/ChatMessageBubble.js +7 -7
- package/dist/Chat/ChatMessageList.js +14 -14
- package/dist/Chat/ChatMessageMetadata.d.ts +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatMessageMetadata.js +14 -12
- package/dist/Chat/ChatPastedTextToken.js +13 -13
- package/dist/Chat/ChatSendButton.js +3 -3
- package/dist/Chat/ChatSystemMessage.d.ts +1 -1
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +17 -17
- package/dist/Chat/ChatTokenizedText.d.ts +1 -1
- package/dist/Chat/ChatTokenizedText.d.ts.map +1 -1
- package/dist/Chat/ChatTokenizedText.js +24 -15
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +81 -74
- package/dist/Chat/index.d.ts +1 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -15
- package/dist/CheckboxInput/CheckboxInput.d.ts +6 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +32 -24
- package/dist/CheckboxList/CheckboxList.js +9 -9
- package/dist/CheckboxList/CheckboxListItem.d.ts +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +8 -6
- package/dist/Citation/Citation.js +10 -10
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +32 -9
- package/dist/Code/Code.d.ts +15 -1
- package/dist/Code/Code.d.ts.map +1 -1
- package/dist/Code/Code.js +35 -5
- package/dist/Code/index.d.ts +1 -1
- package/dist/Code/index.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.d.ts +10 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +88 -52
- package/dist/CodeBlock/index.d.ts +1 -1
- package/dist/CodeBlock/index.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.d.ts +9 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +110 -22
- package/dist/Collapsible/CollapsibleGroup.d.ts +39 -7
- package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +73 -12
- package/dist/Collapsible/CollapsibleGroupContext.d.ts +31 -0
- package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +33 -3
- package/dist/Collapsible/index.d.ts +1 -0
- package/dist/Collapsible/index.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.d.ts +4 -1
- package/dist/Collapsible/useCollapsible.d.ts.map +1 -1
- package/dist/Collapsible/useCollapsible.js +20 -6
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +36 -34
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteEmpty.js +27 -7
- package/dist/CommandPalette/CommandPaletteFooter.js +16 -16
- package/dist/CommandPalette/CommandPaletteGroup.js +5 -5
- package/dist/CommandPalette/CommandPaletteInput.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.js +3 -3
- package/dist/CommandPalette/CommandPaletteList.js +3 -3
- package/dist/ContextMenu/ContextMenu.d.ts +9 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +16 -11
- package/dist/DateInput/DateInput.js +18 -18
- package/dist/DateRangeInput/DateRangeInput.js +23 -23
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -7
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +30 -26
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +9 -9
- package/dist/Dialog/DialogHeader.js +16 -16
- package/dist/Dialog/useImperativeDialog.js +3 -3
- package/dist/Divider/Divider.d.ts +0 -22
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +7 -7
- package/dist/DropdownMenu/DropdownMenu.js +10 -10
- package/dist/DropdownMenu/DropdownMenuItem.d.ts +2 -17
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +3 -3
- package/dist/DropdownMenu/renderDropdownItems.js +10 -10
- package/dist/EmptyState/EmptyState.js +9 -9
- package/dist/Field/Field.js +17 -17
- package/dist/Field/FieldLabel.js +15 -15
- package/dist/Field/InputClearButton.js +5 -5
- package/dist/FieldStatus/FieldStatus.js +3 -3
- package/dist/FileInput/FileInput.js +29 -29
- package/dist/FormLayout/FormLayout.js +5 -5
- package/dist/Grid/Grid.d.ts +4 -3
- package/dist/Grid/Grid.d.ts.map +1 -1
- package/dist/Grid/Grid.js +29 -12
- package/dist/Grid/GridSpan.js +3 -3
- package/dist/HStack/HStack.js +3 -3
- package/dist/Heading/Heading.js +10 -10
- package/dist/HoverCard/HoverCard.js +9 -9
- package/dist/HoverCard/useHoverCard.js +3 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +16 -12
- package/dist/Icon/defaultIcons.js +116 -116
- package/dist/IconButton/IconButton.js +3 -3
- package/dist/InputGroup/InputGroup.js +11 -11
- package/dist/InputGroup/InputGroupText.js +3 -3
- package/dist/Item/Item.js +18 -18
- package/dist/Kbd/Kbd.js +5 -5
- package/dist/Layer/LayerProvider.js +7 -7
- package/dist/Layer/useLayer.js +5 -5
- package/dist/Layout/Layout.js +21 -21
- package/dist/Layout/LayoutContent.js +3 -3
- package/dist/Layout/LayoutFooter.js +5 -5
- package/dist/Layout/LayoutHeader.js +5 -5
- package/dist/Layout/LayoutPanel.js +3 -3
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +55 -31
- package/dist/Lightbox/useLightbox.js +3 -3
- package/dist/Link/Link.js +15 -15
- package/dist/Link/LinkProvider.js +3 -3
- package/dist/Link/useLinkify.js +3 -3
- package/dist/List/List.js +11 -11
- package/dist/List/ListItem.js +11 -11
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +102 -102
- package/dist/Markdown/parser.d.ts +7 -0
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +300 -6
- package/dist/MetadataList/MetadataList.js +10 -10
- package/dist/MetadataList/MetadataListItem.js +15 -15
- package/dist/MobileNav/MobileNav.js +15 -15
- package/dist/MobileNav/MobileNavToggle.js +5 -5
- package/dist/MoreMenu/MoreMenu.js +3 -3
- package/dist/MultiSelector/MultiSelector.d.ts +7 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +64 -55
- package/dist/NavIcon/NavIcon.js +3 -3
- package/dist/NavMenu/NavHeadingMenu.js +5 -5
- package/dist/NavMenu/NavHeadingMenuItem.js +8 -8
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +48 -32
- package/dist/Outline/Outline.js +15 -15
- package/dist/OverflowList/OverflowList.js +8 -8
- package/dist/Overlay/Overlay.js +3 -3
- package/dist/Overlay/OverlayScrim.js +5 -5
- package/dist/Overlay/useOverlay.js +3 -3
- package/dist/Pagination/Pagination.d.ts +1 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +125 -72
- package/dist/Popover/Popover.js +16 -16
- package/dist/Popover/usePopover.js +7 -7
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +110 -92
- package/dist/PowerSearch/PowerSearchEditPopover.js +84 -84
- package/dist/PowerSearch/PowerSearchFilterEditor.js +3 -3
- package/dist/PowerSearch/PowerSearchToken.js +5 -5
- package/dist/PowerSearch/PowerSearchValueEditor.js +54 -54
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +25 -18
- package/dist/RadioList/RadioList.d.ts +7 -1
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +10 -8
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +30 -22
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +28 -10
- package/dist/Section/Section.js +5 -5
- package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +32 -10
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +18 -12
- package/dist/SelectableCard/SelectableCard.js +5 -5
- package/dist/Selector/Selector.d.ts +6 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +54 -45
- package/dist/Selector/SelectorOption.js +3 -3
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +38 -34
- package/dist/SideNav/SideNavCollapseButton.d.ts +1 -1
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +8 -6
- package/dist/SideNav/SideNavHeading.js +87 -87
- package/dist/SideNav/SideNavItem.js +42 -42
- package/dist/SideNav/SideNavSection.d.ts +1 -1
- package/dist/SideNav/SideNavSection.d.ts.map +1 -1
- package/dist/SideNav/SideNavSection.js +18 -16
- package/dist/Skeleton/Skeleton.js +3 -3
- package/dist/Slider/Slider.d.ts +6 -0
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +31 -22
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +10 -10
- package/dist/StatusDot/StatusDot.js +5 -5
- package/dist/Switch/Switch.d.ts +13 -4
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +41 -30
- package/dist/TabList/Tab.js +18 -18
- package/dist/TabList/TabList.js +5 -5
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +57 -30
- package/dist/TabList/tab.markers.stylex.d.ts +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +51 -39
- package/dist/Table/Table.js +7 -7
- package/dist/Table/TableBody.d.ts +1 -1
- package/dist/Table/TableBody.d.ts.map +1 -1
- package/dist/Table/TableBody.js +9 -5
- package/dist/Table/TableCell.d.ts.map +1 -1
- package/dist/Table/TableCell.js +76 -7
- package/dist/Table/TableFooter.d.ts +1 -1
- package/dist/Table/TableFooter.d.ts.map +1 -1
- package/dist/Table/TableFooter.js +9 -5
- package/dist/Table/TableHeader.d.ts +1 -1
- package/dist/Table/TableHeader.d.ts.map +1 -1
- package/dist/Table/TableHeader.js +9 -5
- package/dist/Table/TableHeaderCell.js +3 -3
- package/dist/Table/TableRow.js +5 -5
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +1 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +14 -11
- package/dist/Table/plugins/filtering/useTableFiltering.js +71 -71
- package/dist/Table/plugins/pagination/paginateData.d.ts.map +1 -1
- package/dist/Table/plugins/pagination/paginateData.js +5 -1
- package/dist/Table/plugins/pagination/useTablePagination.js +7 -7
- package/dist/Table/plugins/rowExpansion/index.d.ts +3 -0
- package/dist/Table/plugins/rowExpansion/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/index.js +3 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +90 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -0
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +398 -0
- package/dist/Table/plugins/selection/useTableSelection.js +18 -18
- package/dist/Table/plugins/selection/useTableSelectionState.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelectionState.js +11 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +17 -17
- package/dist/Table/plugins/sortable/useTableSortableState.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortableState.js +8 -4
- package/dist/Table/tableContextMenu.d.ts +5 -1
- package/dist/Table/tableContextMenu.d.ts.map +1 -1
- package/dist/Table/tableContextMenu.js +19 -12
- package/dist/Text/Text.d.ts +1 -1
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +14 -13
- package/dist/Text/text.stylex.d.ts +35 -0
- package/dist/Text/text.stylex.d.ts.map +1 -1
- package/dist/Text/text.stylex.js +52 -1
- package/dist/TextArea/TextArea.js +14 -14
- package/dist/TextInput/TextInput.js +15 -15
- package/dist/Thumbnail/Thumbnail.d.ts +3 -2
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +30 -29
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +26 -21
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +37 -26
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +25 -17
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +23 -11
- package/dist/Toast/useToast.js +4 -4
- package/dist/ToggleButton/ToggleButton.js +12 -12
- package/dist/ToggleButton/ToggleButtonGroup.js +5 -5
- package/dist/Token/Token.js +21 -21
- package/dist/Tokenizer/Tokenizer.d.ts +6 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +38 -29
- package/dist/Toolbar/Toolbar.js +18 -18
- package/dist/Tooltip/Tooltip.js +11 -11
- package/dist/Tooltip/useTooltip.js +3 -3
- package/dist/TopNav/TopNav.js +32 -32
- package/dist/TopNav/TopNavHeading.js +67 -67
- package/dist/TopNav/TopNavItem.js +5 -5
- package/dist/TopNav/TopNavMegaMenu.js +30 -30
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +25 -14
- package/dist/TopNav/TopNavMegaMenuItem.js +16 -16
- package/dist/TopNav/TopNavMenu.js +32 -32
- package/dist/TreeList/TreeList.js +8 -8
- package/dist/TreeList/TreeListBranches.js +11 -11
- package/dist/TreeList/TreeListItem.js +30 -30
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +23 -20
- package/dist/Typeahead/Typeahead.js +12 -12
- package/dist/Typeahead/TypeaheadItem.js +10 -10
- package/dist/VStack/VStack.js +3 -3
- package/dist/astryx.css +23 -0
- package/dist/astryx.umd.js +60 -58
- package/dist/astryx.umd.js.map +4 -4
- package/dist/docs-types.d.ts +13 -1
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.d.ts +1 -1
- package/dist/hooks/focusableSelector.d.ts.map +1 -1
- package/dist/hooks/focusableSelector.js +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useFocusTrap.d.ts +3 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +38 -1
- package/dist/hooks/useHotkeys.d.ts +51 -0
- package/dist/hooks/useHotkeys.d.ts.map +1 -0
- package/dist/hooks/useHotkeys.js +160 -0
- package/dist/hooks/useInteractiveRole.d.ts +6 -2
- package/dist/hooks/useInteractiveRole.d.ts.map +1 -1
- package/dist/hooks/useInteractiveRole.js +6 -2
- package/dist/hooks/useKeyboardHint.js +9 -9
- package/dist/hooks/useStreamingText.d.ts +3 -1
- package/dist/hooks/useStreamingText.d.ts.map +1 -1
- package/dist/hooks/useStreamingText.js +14 -5
- package/dist/theme/MediaTheme.js +3 -3
- package/dist/theme/Theme.js +7 -7
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +10 -3
- package/dist/theme/hct.d.ts +0 -15
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +9 -9
- package/dist/theme/syntax/SyntaxTheme.js +5 -5
- package/dist/theme/tokens.d.ts +10 -2
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +220 -4
- package/dist/utils/color.d.ts +42 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/color.js +150 -0
- package/dist/utils/composeEventHandlers.d.ts +30 -0
- package/dist/utils/composeEventHandlers.d.ts.map +1 -0
- package/dist/utils/composeEventHandlers.js +40 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -1
- package/dist/utils/timeParser.d.ts.map +1 -1
- package/dist/utils/timeParser.js +8 -5
- package/package.json +3 -3
- package/src/AlertDialog/AlertDialog.tsx +2 -0
- package/src/AppShell/AppShell.tsx +2 -0
- package/src/AspectRatio/AspectRatio.doc.mjs +1 -1
- package/src/Avatar/Avatar.doc.mjs +13 -2
- package/src/Avatar/Avatar.test.tsx +32 -1
- package/src/Avatar/Avatar.tsx +12 -20
- package/src/Banner/Banner.doc.mjs +8 -0
- package/src/Banner/Banner.test.tsx +38 -0
- package/src/Banner/Banner.tsx +8 -1
- package/src/Button/Button.tsx +39 -6
- package/src/ButtonGroup/ButtonGroup.doc.mjs +1 -1
- package/src/Calendar/Calendar.doc.mjs +1 -1
- package/src/Calendar/Calendar.test.tsx +201 -17
- package/src/Calendar/Calendar.tsx +79 -26
- package/src/Calendar/dayCellUtils.test.ts +306 -1
- package/src/Calendar/dayCellUtils.ts +206 -13
- package/src/Calendar/styles.ts +12 -2
- package/src/Card/Card.doc.mjs +1 -1
- package/src/Card/Card.tsx +16 -6
- package/src/Carousel/Carousel.doc.mjs +12 -12
- package/src/Carousel/Carousel.test.tsx +13 -0
- package/src/Carousel/Carousel.tsx +1 -0
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.test.tsx +24 -0
- package/src/Chat/ChatComposerInput.tsx +17 -1
- package/src/Chat/ChatDictationButton.test.tsx +43 -0
- package/src/Chat/ChatDictationButton.tsx +4 -4
- package/src/Chat/ChatLayoutScrollButton.test.tsx +33 -0
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessageMetadata.test.tsx +32 -0
- package/src/Chat/ChatMessageMetadata.tsx +4 -6
- package/src/Chat/ChatSystemMessage.test.tsx +26 -11
- package/src/Chat/ChatSystemMessage.tsx +7 -7
- package/src/Chat/ChatTokenizedText.test.tsx +29 -16
- package/src/Chat/ChatTokenizedText.tsx +15 -8
- package/src/Chat/ChatToolCalls.test.tsx +55 -0
- package/src/Chat/ChatToolCalls.tsx +10 -12
- package/src/Chat/index.ts +1 -4
- package/src/Chat/useChatNewMessages.test.tsx +4 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +12 -4
- package/src/CheckboxInput/CheckboxInput.test.tsx +103 -0
- package/src/CheckboxInput/CheckboxInput.tsx +13 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +19 -0
- package/src/CheckboxList/CheckboxListItem.tsx +11 -2
- package/src/Citation/Citation.doc.mjs +5 -0
- package/src/ClickableCard/ClickableCard.tsx +45 -2
- package/src/Code/Code.test.tsx +54 -0
- package/src/Code/Code.tsx +48 -4
- package/src/Code/index.ts +1 -1
- package/src/CodeBlock/CodeBlock.doc.mjs +7 -2
- package/src/CodeBlock/CodeBlock.test.tsx +122 -3
- package/src/CodeBlock/CodeBlock.tsx +62 -4
- package/src/CodeBlock/index.ts +1 -1
- package/src/Collapsible/Collapsible.doc.mjs +8 -4
- package/src/Collapsible/Collapsible.test.tsx +405 -0
- package/src/Collapsible/Collapsible.tsx +86 -10
- package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
- package/src/Collapsible/CollapsibleGroup.test.tsx +318 -0
- package/src/Collapsible/CollapsibleGroup.tsx +107 -9
- package/src/Collapsible/CollapsibleGroupContext.tsx +42 -2
- package/src/Collapsible/index.ts +4 -0
- package/src/Collapsible/useCollapsible.ts +20 -6
- package/src/CommandPalette/CommandPalette.tsx +5 -3
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
- package/src/CommandPalette/CommandPaletteEmpty.tsx +15 -1
- package/src/CommandPalette/CommandPaletteGroup.doc.mjs +10 -0
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteItem.doc.mjs +6 -0
- package/src/CommandPalette/CommandPaletteList.doc.mjs +9 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +15 -0
- package/src/ContextMenu/ContextMenu.test.tsx +15 -0
- package/src/ContextMenu/ContextMenu.tsx +19 -1
- package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
- package/src/DateInput/DateInput.doc.mjs +6 -1
- package/src/DateInput/DateInput.test.tsx +11 -20
- package/src/DateRangeInput/DateRangeInput.doc.mjs +1 -1
- package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
- package/src/DateRangeInput/DateRangeInput.tsx +2 -2
- package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -3
- package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
- package/src/DateTimeInput/DateTimeInput.tsx +9 -8
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/DialogHeader.doc.mjs +45 -0
- package/src/Divider/Divider.tsx +1 -23
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +5 -3
- package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
- package/src/EmptyState/EmptyState.doc.mjs +1 -1
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/FieldLabel.test.tsx +2 -2
- package/src/FieldStatus/FieldStatus.test.tsx +282 -0
- package/src/FileInput/FileInput.doc.mjs +1 -1
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
- package/src/Grid/Grid.doc.mjs +3 -3
- package/src/Grid/Grid.test.tsx +43 -18
- package/src/Grid/Grid.tsx +26 -9
- package/src/Icon/Icon.test.tsx +41 -29
- package/src/Icon/Icon.tsx +6 -2
- package/src/InputGroup/InputGroup.tsx +2 -2
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
- package/src/Item/Item.tsx +1 -1
- package/src/Layout/Layout.test.tsx +285 -0
- package/src/Layout/LayoutContent.doc.mjs +12 -0
- package/src/Layout/LayoutPanel.doc.mjs +40 -0
- package/src/Layout/LayoutSlots.test.tsx +364 -0
- package/src/Layout/__tests__/edgeCompensation.test.tsx +72 -0
- package/src/Lightbox/Lightbox.doc.mjs +5 -0
- package/src/Lightbox/Lightbox.test.tsx +123 -2
- package/src/Lightbox/Lightbox.tsx +29 -1
- package/src/Markdown/Markdown.test.tsx +23 -0
- package/src/Markdown/Markdown.tsx +9 -7
- package/src/Markdown/incremental.test.ts +36 -0
- package/src/Markdown/parser.perf.test.ts +34 -12
- package/src/Markdown/parser.test.ts +210 -0
- package/src/Markdown/parser.ts +301 -6
- package/src/MobileNav/MobileNav.doc.mjs +20 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +14 -1
- package/src/MultiSelector/MultiSelector.test.tsx +33 -0
- package/src/MultiSelector/MultiSelector.tsx +20 -0
- package/src/NavMenu/NavMenu.doc.mjs +15 -0
- package/src/NumberInput/NumberInput.test.tsx +48 -3
- package/src/NumberInput/NumberInput.tsx +32 -15
- package/src/Outline/parseOutlineFromMarkdown.test.ts +80 -0
- package/src/OverflowList/OverflowList.test.tsx +416 -0
- package/src/Overlay/Overlay.doc.mjs +6 -0
- package/src/Overlay/Overlay.test.tsx +356 -0
- package/src/Pagination/Pagination.test.tsx +162 -0
- package/src/Pagination/Pagination.tsx +80 -26
- package/src/Popover/Popover.test.tsx +65 -0
- package/src/PowerSearch/PowerSearch.doc.mjs +4 -4
- package/src/PowerSearch/PowerSearch.test.tsx +109 -1
- package/src/PowerSearch/PowerSearch.tsx +37 -16
- package/src/ProgressBar/ProgressBar.test.tsx +30 -0
- package/src/ProgressBar/ProgressBar.tsx +12 -5
- package/src/RadioList/RadioList.doc.mjs +7 -1
- package/src/RadioList/RadioList.test.tsx +65 -0
- package/src/RadioList/RadioList.tsx +10 -1
- package/src/RadioList/RadioListItem.tsx +13 -4
- package/src/Resizable/ResizeHandle.test.tsx +218 -0
- package/src/Resizable/ResizeHandle.tsx +22 -4
- package/src/Section/Section.test.tsx +4 -10
- package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
- package/src/SegmentedControl/SegmentedControl.test.tsx +192 -0
- package/src/SegmentedControl/SegmentedControl.tsx +27 -5
- package/src/SegmentedControl/SegmentedControlItem.tsx +9 -4
- package/src/SelectableCard/SelectableCard.doc.mjs +1 -1
- package/src/Selector/Selector.doc.mjs +12 -1
- package/src/Selector/Selector.test.tsx +30 -0
- package/src/Selector/Selector.tsx +18 -0
- package/src/SideNav/SideNav.doc.mjs +7 -1
- package/src/SideNav/SideNav.test.tsx +66 -0
- package/src/SideNav/SideNav.tsx +6 -2
- package/src/SideNav/SideNavCollapseButton.tsx +4 -3
- package/src/SideNav/SideNavSection.tsx +6 -4
- package/src/SizeContext/SizeContext.test.tsx +226 -0
- package/src/Slider/Slider.doc.mjs +14 -2
- package/src/Slider/Slider.test.tsx +30 -0
- package/src/Slider/Slider.tsx +20 -0
- package/src/Spinner/Spinner.tsx +1 -0
- package/src/Switch/Switch.doc.mjs +21 -9
- package/src/Switch/Switch.test.tsx +137 -0
- package/src/Switch/Switch.tsx +32 -7
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +185 -1
- package/src/TabList/TabMenu.tsx +45 -9
- package/src/Table/BaseTable.tsx +16 -3
- package/src/Table/Table.test.tsx +87 -0
- package/src/Table/TableBody.tsx +15 -2
- package/src/Table/TableCell.tsx +87 -8
- package/src/Table/TableFooter.tsx +15 -2
- package/src/Table/TableHeader.tsx +15 -2
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +13 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +3 -1
- package/src/Table/plugins/pagination/paginateData.ts +5 -1
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
- package/src/Table/plugins/rowExpansion/index.ts +7 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +155 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +590 -0
- package/src/Table/plugins/selection/useTableSelectionState.test.tsx +23 -0
- package/src/Table/plugins/selection/useTableSelectionState.tsx +11 -6
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +35 -1
- package/src/Table/plugins/sortable/useTableSortableState.tsx +8 -4
- package/src/Table/tableContextMenu.test.tsx +27 -3
- package/src/Table/tableContextMenu.tsx +20 -2
- package/src/Table/useTablePagination.doc.mjs +4 -1
- package/src/Table/useTableRowExpansion.doc.mjs +80 -0
- package/src/Table/useTableSortable.doc.mjs +4 -1
- package/src/Text/Text.doc.mjs +2 -2
- package/src/Text/Text.test.tsx +11 -0
- package/src/Text/Text.tsx +4 -2
- package/src/Text/text.stylex.ts +41 -0
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.test.tsx +3 -3
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/TextInput/TextInput.test.tsx +3 -3
- package/src/Thumbnail/Thumbnail.test.tsx +36 -2
- package/src/Thumbnail/Thumbnail.tsx +4 -2
- package/src/TimeInput/TimeInput.doc.mjs +11 -6
- package/src/TimeInput/TimeInput.test.tsx +37 -0
- package/src/TimeInput/TimeInput.tsx +11 -1
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +52 -0
- package/src/Timestamp/Timestamp.tsx +30 -16
- package/src/Toast/Toast.tsx +11 -3
- package/src/Toast/ToastViewport.test.tsx +64 -0
- package/src/Toast/ToastViewport.tsx +12 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -4
- package/src/Tokenizer/Tokenizer.test.tsx +33 -0
- package/src/Tokenizer/Tokenizer.tsx +19 -0
- package/src/Toolbar/Toolbar.test.tsx +1 -1
- package/src/TopNav/TopNav.doc.mjs +1 -1
- package/src/TopNav/TopNav.test.tsx +18 -0
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +9 -2
- package/src/TreeList/TreeList.doc.mjs +2 -2
- package/src/Typeahead/BaseTypeahead.doc.mjs +19 -0
- package/src/Typeahead/BaseTypeahead.tsx +5 -2
- package/src/Typeahead/Typeahead.doc.mjs +7 -2
- package/src/Typeahead/Typeahead.test.tsx +45 -1
- package/src/__tests__/TestIcon.tsx +26 -0
- package/src/__tests__/fastRoleQueries.ts +66 -0
- package/src/docPropReferences.test.ts +178 -0
- package/src/docs-types.ts +14 -0
- package/src/hooks/focusableSelector.ts +1 -1
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useFocusTrap.doc.mjs +4 -2
- package/src/hooks/useFocusTrap.test.tsx +149 -1
- package/src/hooks/useFocusTrap.ts +50 -1
- package/src/hooks/useHotkeys.doc.mjs +52 -0
- package/src/hooks/useHotkeys.test.ts +245 -0
- package/src/hooks/useHotkeys.ts +203 -0
- package/src/hooks/useInteractiveRole.ts +12 -4
- package/src/hooks/useKeyboardHint.doc.mjs +6 -6
- package/src/hooks/useStreamingText.test.ts +54 -19
- package/src/hooks/useStreamingText.ts +16 -5
- package/src/theme/SyntaxTheme.doc.mjs +4 -4
- package/src/theme/defineTheme.ts +4 -13
- package/src/theme/derivedVarRegistry.test.ts +2 -2
- package/src/theme/expandColorScale.test.ts +29 -0
- package/src/theme/expandColorScale.ts +11 -6
- package/src/theme/hct.ts +9 -17
- package/src/theme/tokens.test.ts +182 -9
- package/src/theme/tokens.ts +239 -4
- package/src/theme/useTheme.test.tsx +20 -0
- package/src/utils/color.test.ts +133 -0
- package/src/utils/color.ts +148 -0
- package/src/utils/composeEventHandlers.test.ts +71 -0
- package/src/utils/composeEventHandlers.ts +44 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/mergeProps.test.ts +166 -0
- package/src/utils/sharedResizeObserver.test.ts +2 -2
- package/src/utils/timeParser.test.ts +13 -0
- package/src/utils/timeParser.ts +8 -5
|
@@ -33,6 +33,31 @@ describe('Timestamp', () => {
|
|
|
33
33
|
expect(screen.getByText('2 hours ago')).toBeInTheDocument();
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
it('does not round a tier up past its own boundary', () => {
|
|
37
|
+
// Just under each threshold the count must stay within the tier, e.g.
|
|
38
|
+
// 59.98 minutes is "59 minutes ago", never "60 minutes ago".
|
|
39
|
+
const {rerender} = render(
|
|
40
|
+
<Timestamp value={Date.now() / 1000 - 3599} format="relative" />,
|
|
41
|
+
);
|
|
42
|
+
expect(screen.getByText('59 minutes ago')).toBeInTheDocument();
|
|
43
|
+
|
|
44
|
+
rerender(
|
|
45
|
+
<Timestamp value={Date.now() / 1000 - 86399} format="relative" />,
|
|
46
|
+
);
|
|
47
|
+
expect(screen.getByText('23 hours ago')).toBeInTheDocument();
|
|
48
|
+
|
|
49
|
+
rerender(
|
|
50
|
+
<Timestamp value={Date.now() / 1000 - 2591999} format="relative" />,
|
|
51
|
+
);
|
|
52
|
+
expect(screen.getByText('29 days ago')).toBeInTheDocument();
|
|
53
|
+
|
|
54
|
+
// Same guarantee on the future side.
|
|
55
|
+
rerender(
|
|
56
|
+
<Timestamp value={Date.now() / 1000 + 3599} format="relative" />,
|
|
57
|
+
);
|
|
58
|
+
expect(screen.getByText('in 59 minutes')).toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
|
|
36
61
|
it('renders "now" for very recent times', () => {
|
|
37
62
|
const fiveSecondsAgo = Date.now() / 1000 - 5;
|
|
38
63
|
render(<Timestamp value={fiveSecondsAgo} format="relative" />);
|
|
@@ -290,4 +315,31 @@ describe('Timestamp', () => {
|
|
|
290
315
|
const el = screen.getByRole('time');
|
|
291
316
|
expect(el.textContent).not.toContain('ago');
|
|
292
317
|
});
|
|
318
|
+
|
|
319
|
+
// --- Invalid values ---
|
|
320
|
+
|
|
321
|
+
it('renders nothing instead of crashing on an unparseable string value', () => {
|
|
322
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
323
|
+
try {
|
|
324
|
+
const {container} = render(
|
|
325
|
+
<Timestamp value="not-a-date" data-testid="ts" />,
|
|
326
|
+
);
|
|
327
|
+
expect(container).toBeEmptyDOMElement();
|
|
328
|
+
expect(warn).toHaveBeenCalledWith(
|
|
329
|
+
expect.stringContaining('could not parse value'),
|
|
330
|
+
);
|
|
331
|
+
} finally {
|
|
332
|
+
warn.mockRestore();
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('renders nothing instead of crashing on a NaN value', () => {
|
|
337
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
338
|
+
try {
|
|
339
|
+
const {container} = render(<Timestamp value={NaN} data-testid="ts" />);
|
|
340
|
+
expect(container).toBeEmptyDOMElement();
|
|
341
|
+
} finally {
|
|
342
|
+
warn.mockRestore();
|
|
343
|
+
}
|
|
344
|
+
});
|
|
293
345
|
});
|
|
@@ -180,22 +180,22 @@ function getRelativeTimeString(date: Date, now: Date): string {
|
|
|
180
180
|
return 'in a few seconds';
|
|
181
181
|
}
|
|
182
182
|
if (absDiff < HOUR) {
|
|
183
|
-
const mins = Math.
|
|
183
|
+
const mins = Math.floor(absDiff / MINUTE);
|
|
184
184
|
return `in ${mins} ${mins === 1 ? 'minute' : 'minutes'}`;
|
|
185
185
|
}
|
|
186
186
|
if (absDiff < DAY) {
|
|
187
|
-
const hours = Math.
|
|
187
|
+
const hours = Math.floor(absDiff / HOUR);
|
|
188
188
|
return `in ${hours} ${hours === 1 ? 'hour' : 'hours'}`;
|
|
189
189
|
}
|
|
190
190
|
if (absDiff < MONTH) {
|
|
191
|
-
const days = Math.
|
|
191
|
+
const days = Math.floor(absDiff / DAY);
|
|
192
192
|
return `in ${days} ${days === 1 ? 'day' : 'days'}`;
|
|
193
193
|
}
|
|
194
194
|
if (absDiff < YEAR) {
|
|
195
|
-
const months = Math.
|
|
195
|
+
const months = Math.floor(absDiff / MONTH);
|
|
196
196
|
return `in ${months} ${months === 1 ? 'month' : 'months'}`;
|
|
197
197
|
}
|
|
198
|
-
const years = Math.
|
|
198
|
+
const years = Math.floor(absDiff / YEAR);
|
|
199
199
|
return `in ${years} ${years === 1 ? 'year' : 'years'}`;
|
|
200
200
|
}
|
|
201
201
|
|
|
@@ -203,25 +203,25 @@ function getRelativeTimeString(date: Date, now: Date): string {
|
|
|
203
203
|
return `${diffSeconds} seconds ago`;
|
|
204
204
|
}
|
|
205
205
|
if (diffSeconds < HOUR) {
|
|
206
|
-
const mins = Math.
|
|
206
|
+
const mins = Math.floor(diffSeconds / MINUTE);
|
|
207
207
|
return `${mins} ${mins === 1 ? 'minute' : 'minutes'} ago`;
|
|
208
208
|
}
|
|
209
209
|
if (diffSeconds < DAY) {
|
|
210
|
-
const hours = Math.
|
|
210
|
+
const hours = Math.floor(diffSeconds / HOUR);
|
|
211
211
|
return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;
|
|
212
212
|
}
|
|
213
213
|
if (diffSeconds < 2 * DAY) {
|
|
214
214
|
return 'yesterday';
|
|
215
215
|
}
|
|
216
216
|
if (diffSeconds < MONTH) {
|
|
217
|
-
const days = Math.
|
|
217
|
+
const days = Math.floor(diffSeconds / DAY);
|
|
218
218
|
return `${days} days ago`;
|
|
219
219
|
}
|
|
220
220
|
if (diffSeconds < YEAR) {
|
|
221
|
-
const months = Math.
|
|
221
|
+
const months = Math.floor(diffSeconds / MONTH);
|
|
222
222
|
return `${months} ${months === 1 ? 'month' : 'months'} ago`;
|
|
223
223
|
}
|
|
224
|
-
const years = Math.
|
|
224
|
+
const years = Math.floor(diffSeconds / YEAR);
|
|
225
225
|
return `${years} ${years === 1 ? 'year' : 'years'} ago`;
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -360,7 +360,12 @@ export function Timestamp({
|
|
|
360
360
|
const [now, setNow] = useState(() => new Date());
|
|
361
361
|
|
|
362
362
|
const date = parseValue(value);
|
|
363
|
-
|
|
363
|
+
// An unparseable value (a malformed date string, or a NaN timestamp from
|
|
364
|
+
// missing data) yields an Invalid Date, and formatting one throws "Invalid
|
|
365
|
+
// time value" — crashing the whole tree. Compute nothing from it here and
|
|
366
|
+
// bail out below (after the hooks) instead.
|
|
367
|
+
const isValidDate = !Number.isNaN(date.getTime());
|
|
368
|
+
const isoString = isValidDate ? date.toISOString() : '';
|
|
364
369
|
|
|
365
370
|
// Determine effective format
|
|
366
371
|
const diffSeconds = Math.round((now.getTime() - date.getTime()) / 1000);
|
|
@@ -372,19 +377,20 @@ export function Timestamp({
|
|
|
372
377
|
: format;
|
|
373
378
|
|
|
374
379
|
// Format the display text
|
|
375
|
-
const displayText =
|
|
376
|
-
|
|
380
|
+
const displayText = !isValidDate
|
|
381
|
+
? ''
|
|
382
|
+
: effectiveFormat === 'relative'
|
|
377
383
|
? getRelativeTimeString(date, now)
|
|
378
384
|
: isAbsoluteFormat(effectiveFormat)
|
|
379
385
|
? formatTimestamp(date, effectiveFormat, isTimezoneShown)
|
|
380
386
|
: '';
|
|
381
387
|
|
|
382
388
|
// Full absolute text for tooltip and aria-label
|
|
383
|
-
const fullAbsoluteText = getFullAbsoluteString(date);
|
|
389
|
+
const fullAbsoluteText = isValidDate ? getFullAbsoluteString(date) : '';
|
|
384
390
|
|
|
385
391
|
// Live updates
|
|
386
392
|
useEffect(() => {
|
|
387
|
-
if (!isLive || effectiveFormat !== 'relative') {
|
|
393
|
+
if (!isLive || !isValidDate || effectiveFormat !== 'relative') {
|
|
388
394
|
return;
|
|
389
395
|
}
|
|
390
396
|
|
|
@@ -394,7 +400,15 @@ export function Timestamp({
|
|
|
394
400
|
}, interval);
|
|
395
401
|
|
|
396
402
|
return () => clearInterval(timer);
|
|
397
|
-
}, [isLive, effectiveFormat, diffSeconds]);
|
|
403
|
+
}, [isLive, isValidDate, effectiveFormat, diffSeconds]);
|
|
404
|
+
|
|
405
|
+
// Placed after all hooks so the hook order stays stable across renders.
|
|
406
|
+
if (!isValidDate) {
|
|
407
|
+
console.warn(
|
|
408
|
+
`Timestamp: could not parse value ${JSON.stringify(value)} as a date. Rendering nothing.`,
|
|
409
|
+
);
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
398
412
|
|
|
399
413
|
const showTooltip = hasTooltip && effectiveFormat === 'relative';
|
|
400
414
|
|
package/src/Toast/Toast.tsx
CHANGED
|
@@ -121,8 +121,14 @@ export function Toast({
|
|
|
121
121
|
// Will be initialized by startTimer when actually used
|
|
122
122
|
const startTimeRef = useRef<number | null>(null);
|
|
123
123
|
|
|
124
|
+
// Read onDismiss through a ref: the viewport re-creates it on every render
|
|
125
|
+
// (another toast arriving/exiting), and a startTimer that depends on it
|
|
126
|
+
// would restart — and un-pause — this toast's timer on unrelated renders.
|
|
127
|
+
const onDismissRef = useRef(onDismiss);
|
|
128
|
+
onDismissRef.current = onDismiss;
|
|
129
|
+
|
|
124
130
|
const startTimer = useCallback(() => {
|
|
125
|
-
if (!isAutoHide) {
|
|
131
|
+
if (!isAutoHide || isPausedRef.current) {
|
|
126
132
|
return;
|
|
127
133
|
}
|
|
128
134
|
if (timerRef.current) {
|
|
@@ -130,9 +136,9 @@ export function Toast({
|
|
|
130
136
|
}
|
|
131
137
|
startTimeRef.current = Date.now();
|
|
132
138
|
timerRef.current = setTimeout(() => {
|
|
133
|
-
|
|
139
|
+
onDismissRef.current('auto');
|
|
134
140
|
}, remainingRef.current);
|
|
135
|
-
}, [isAutoHide
|
|
141
|
+
}, [isAutoHide]);
|
|
136
142
|
|
|
137
143
|
const pauseTimer = useCallback(() => {
|
|
138
144
|
if (!isAutoHide || isPausedRef.current) {
|
|
@@ -165,6 +171,8 @@ export function Toast({
|
|
|
165
171
|
clearTimeout(timerRef.current);
|
|
166
172
|
}
|
|
167
173
|
};
|
|
174
|
+
// startTimer's identity is stable per isAutoHide, so this runs on mount
|
|
175
|
+
// and on a genuine duration change — not on unrelated viewport renders.
|
|
168
176
|
}, [autoHideDuration, startTimer]);
|
|
169
177
|
|
|
170
178
|
// Pause the auto-hide timer while the window is not focused, so a toast
|
|
@@ -212,3 +212,67 @@ describe('ToastViewport region ARIA', () => {
|
|
|
212
212
|
expect(region).not.toHaveAttribute('aria-modal');
|
|
213
213
|
});
|
|
214
214
|
});
|
|
215
|
+
|
|
216
|
+
describe('toast timer lifecycle (#3589)', () => {
|
|
217
|
+
it('fires onHide exactly once when dismissed twice during the exit window', () => {
|
|
218
|
+
const onHide = vi.fn();
|
|
219
|
+
renderViewport(
|
|
220
|
+
<ShowToastButton options={{body: 'Once', onHide}} triggerLabel="Show" />,
|
|
221
|
+
);
|
|
222
|
+
act(() => {
|
|
223
|
+
fireEvent.click(screen.getByText('Show'));
|
|
224
|
+
});
|
|
225
|
+
const dismiss = screen.getByRole('button', {name: 'Dismiss notification'});
|
|
226
|
+
act(() => {
|
|
227
|
+
fireEvent.click(dismiss);
|
|
228
|
+
});
|
|
229
|
+
// The toast stays mounted during its exit transition; a second click
|
|
230
|
+
// lands on the same still-mounted button.
|
|
231
|
+
act(() => {
|
|
232
|
+
fireEvent.click(dismiss);
|
|
233
|
+
});
|
|
234
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('keeps a window-blur pause alive when another toast arrives', () => {
|
|
238
|
+
vi.useFakeTimers();
|
|
239
|
+
try {
|
|
240
|
+
const onHide = vi.fn();
|
|
241
|
+
renderViewport(
|
|
242
|
+
<>
|
|
243
|
+
<ShowToastButton
|
|
244
|
+
options={{body: 'Paused', autoHideDuration: 3000, onHide}}
|
|
245
|
+
triggerLabel="Show A"
|
|
246
|
+
/>
|
|
247
|
+
<ShowToastButton options={INFO_B} triggerLabel="Show B" />
|
|
248
|
+
</>,
|
|
249
|
+
);
|
|
250
|
+
act(() => {
|
|
251
|
+
fireEvent.click(screen.getByText('Show A'));
|
|
252
|
+
});
|
|
253
|
+
act(() => {
|
|
254
|
+
fireEvent.blur(window);
|
|
255
|
+
});
|
|
256
|
+
// A second toast arriving re-renders the viewport; the paused timer
|
|
257
|
+
// must not silently restart.
|
|
258
|
+
act(() => {
|
|
259
|
+
fireEvent.click(screen.getByText('Show B'));
|
|
260
|
+
});
|
|
261
|
+
act(() => {
|
|
262
|
+
vi.advanceTimersByTime(60_000);
|
|
263
|
+
});
|
|
264
|
+
expect(onHide).not.toHaveBeenCalled();
|
|
265
|
+
// Focus returns: the remaining time resumes and completes normally.
|
|
266
|
+
act(() => {
|
|
267
|
+
fireEvent.focus(window);
|
|
268
|
+
});
|
|
269
|
+
act(() => {
|
|
270
|
+
vi.advanceTimersByTime(60_000);
|
|
271
|
+
});
|
|
272
|
+
expect(onHide).toHaveBeenCalledTimes(1);
|
|
273
|
+
expect(onHide).toHaveBeenCalledWith('auto');
|
|
274
|
+
} finally {
|
|
275
|
+
vi.useRealTimers();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -114,6 +114,9 @@ export function ToastViewport({
|
|
|
114
114
|
|
|
115
115
|
// Show the popover on mount so it enters the top layer.
|
|
116
116
|
const viewportRef = useRef<HTMLDivElement>(null);
|
|
117
|
+
// Toast ids whose exit has begun — guards onHide from double-firing (see
|
|
118
|
+
// removeToast). Mirrors exitingIds state, readable synchronously.
|
|
119
|
+
const exitingIdsRef = useRef<Set<string>>(new Set());
|
|
117
120
|
// The element that was focused before the user jumped into the viewport
|
|
118
121
|
// (via F6). Used to restore focus once all toasts are dismissed so focus
|
|
119
122
|
// never falls to <body>.
|
|
@@ -171,6 +174,14 @@ export function ToastViewport({
|
|
|
171
174
|
}, []);
|
|
172
175
|
|
|
173
176
|
const removeToast = useCallback((id: string, reason: ToastDismissReason) => {
|
|
177
|
+
// An exiting toast stays in toastsRef until its exit transition ends, so
|
|
178
|
+
// a second dismissal inside that window (double-click, auto-timer plus
|
|
179
|
+
// manual dismiss()) would re-fire onHide. Track exiting ids in a ref —
|
|
180
|
+
// the exitingIds state dedupe below runs too late to protect onHide.
|
|
181
|
+
if (exitingIdsRef.current.has(id)) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
exitingIdsRef.current.add(id);
|
|
174
185
|
const entry = toastsRef.current.find(t => t.id === id);
|
|
175
186
|
if (entry) {
|
|
176
187
|
entry.options.onHide?.(reason);
|
|
@@ -210,6 +221,7 @@ export function ToastViewport({
|
|
|
210
221
|
}, []);
|
|
211
222
|
|
|
212
223
|
const handleExited = useCallback((id: string) => {
|
|
224
|
+
exitingIdsRef.current.delete(id);
|
|
213
225
|
setExitingIds(prev => {
|
|
214
226
|
if (!prev.has(id)) {
|
|
215
227
|
return prev;
|
|
@@ -17,6 +17,7 @@ export const docs = {
|
|
|
17
17
|
theming: {
|
|
18
18
|
targets: [
|
|
19
19
|
{className: 'astryx-toggle-button-group'},
|
|
20
|
+
{className: 'astryx-toggle-button', states: ['isPressed']},
|
|
20
21
|
],
|
|
21
22
|
},
|
|
22
23
|
description: 'A button that toggles between pressed and unpressed states. Thin wrapper over Button with controlled toggle pattern, icon swap, and font weight emphasis.',
|
|
@@ -70,11 +70,17 @@ export const docs = {
|
|
|
70
70
|
description: 'Disables the input and all token interactions.',
|
|
71
71
|
default: 'false',
|
|
72
72
|
},
|
|
73
|
+
{
|
|
74
|
+
name: 'htmlName',
|
|
75
|
+
type: 'string',
|
|
76
|
+
description:
|
|
77
|
+
'The HTML name attribute for form submissions. Renders one hidden input per selected item id.',
|
|
78
|
+
},
|
|
73
79
|
{
|
|
74
80
|
name: 'disabledMessage',
|
|
75
81
|
type: 'string',
|
|
76
82
|
description:
|
|
77
|
-
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip
|
|
83
|
+
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
78
84
|
},
|
|
79
85
|
{
|
|
80
86
|
name: 'status',
|
|
@@ -183,7 +189,7 @@ export const docs = {
|
|
|
183
189
|
],
|
|
184
190
|
theming: {
|
|
185
191
|
targets: [
|
|
186
|
-
{className: 'astryx-tokenizer', visualProps: ['size']},
|
|
192
|
+
{className: 'astryx-tokenizer', visualProps: ['size', 'status']},
|
|
187
193
|
],
|
|
188
194
|
},
|
|
189
195
|
usage: {
|
|
@@ -277,11 +283,16 @@ export const docsZh = {
|
|
|
277
283
|
description: '\u7981\u7528\u8f93\u5165\u6846\u548c\u6240\u6709\u6807\u8bb0\u4ea4\u4e92\u3002',
|
|
278
284
|
default: 'false',
|
|
279
285
|
},
|
|
286
|
+
{
|
|
287
|
+
name: 'htmlName',
|
|
288
|
+
type: 'string',
|
|
289
|
+
description: '用于表单提交的 HTML name 属性。为每个已选项目的 id 渲染一个隐藏输入。',
|
|
290
|
+
},
|
|
280
291
|
{
|
|
281
292
|
name: 'disabledMessage',
|
|
282
293
|
type: 'string',
|
|
283
294
|
description:
|
|
284
|
-
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip
|
|
295
|
+
'Explains why the tokenizer is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the input focusable via aria-disabled (input stays blocked). Use this instead of wrapping a disabled Tokenizer in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
285
296
|
},
|
|
286
297
|
{
|
|
287
298
|
name: 'status',
|
|
@@ -379,7 +390,7 @@ export const docsZh = {
|
|
|
379
390
|
],
|
|
380
391
|
theming: {
|
|
381
392
|
targets: [
|
|
382
|
-
{className: 'astryx-tokenizer', visualProps: ['size']},
|
|
393
|
+
{className: 'astryx-tokenizer', visualProps: ['size', 'status']},
|
|
383
394
|
],
|
|
384
395
|
},
|
|
385
396
|
usage: {
|
|
@@ -435,6 +446,7 @@ export const docsDense = {
|
|
|
435
446
|
renderToken: 'Custom token render. Default renders Token w/ label+onRemove.',
|
|
436
447
|
renderItem: 'Custom dropdown item render. Default renders TypeaheadItem.',
|
|
437
448
|
isDisabled: 'Disables input+all token interactions.',
|
|
449
|
+
htmlName: 'HTML name attr; one hidden input per selected item id.',
|
|
438
450
|
status: 'Validation status w/ type+message for error/warning/success.',
|
|
439
451
|
isLabelHidden: 'Visually hides label; keeps a11y.',
|
|
440
452
|
description: 'Helper text below label.',
|
|
@@ -867,4 +867,37 @@ describe('Tokenizer', () => {
|
|
|
867
867
|
expect(screen.getByRole('combobox')).toBeDisabled();
|
|
868
868
|
});
|
|
869
869
|
});
|
|
870
|
+
describe('form participation', () => {
|
|
871
|
+
it('submits one entry per token id under htmlName', () => {
|
|
872
|
+
const {container} = render(
|
|
873
|
+
<form>
|
|
874
|
+
<Tokenizer
|
|
875
|
+
label="Users"
|
|
876
|
+
htmlName="users"
|
|
877
|
+
searchSource={userSource}
|
|
878
|
+
value={[users[0], users[1]]}
|
|
879
|
+
onChange={() => {}}
|
|
880
|
+
/>
|
|
881
|
+
</form>,
|
|
882
|
+
);
|
|
883
|
+
const data = new FormData(container.querySelector('form')!);
|
|
884
|
+
expect(data.getAll('users')).toEqual([users[0].id, users[1].id]);
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
it('is excluded from form data when disabled', () => {
|
|
888
|
+
const {container} = render(
|
|
889
|
+
<form>
|
|
890
|
+
<Tokenizer
|
|
891
|
+
label="Users"
|
|
892
|
+
htmlName="users"
|
|
893
|
+
searchSource={userSource}
|
|
894
|
+
value={[users[0]]}
|
|
895
|
+
onChange={() => {}}
|
|
896
|
+
isDisabled
|
|
897
|
+
/>
|
|
898
|
+
</form>,
|
|
899
|
+
);
|
|
900
|
+
expect([...new FormData(container.querySelector('form')!).keys()]).toEqual([]);
|
|
901
|
+
});
|
|
902
|
+
});
|
|
870
903
|
});
|
|
@@ -128,6 +128,12 @@ export interface TokenizerProps<T extends SearchableItem> extends Omit<
|
|
|
128
128
|
searchSource: SearchSource<T>;
|
|
129
129
|
/** Currently selected items. */
|
|
130
130
|
value: T[];
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The HTML name attribute for form submissions. When set, hidden inputs
|
|
134
|
+
* carry one entry per selected item's id under this name.
|
|
135
|
+
*/
|
|
136
|
+
htmlName?: string;
|
|
131
137
|
/** Callback when selection changes. Includes change metadata. */
|
|
132
138
|
onChange: (items: T[], change: TokenizerChange<T>) => void;
|
|
133
139
|
/** Render function for dropdown items. Default: TypeaheadItem. */
|
|
@@ -377,6 +383,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
377
383
|
maxMenuItems,
|
|
378
384
|
emptySearchResultsText,
|
|
379
385
|
isDisabled = false,
|
|
386
|
+
htmlName,
|
|
380
387
|
disabledMessage,
|
|
381
388
|
hasClear = false,
|
|
382
389
|
endContent,
|
|
@@ -760,6 +767,18 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
760
767
|
: undefined
|
|
761
768
|
}
|
|
762
769
|
/>
|
|
770
|
+
{htmlName != null &&
|
|
771
|
+
value.map(item => (
|
|
772
|
+
<input
|
|
773
|
+
key={item.id}
|
|
774
|
+
type="hidden"
|
|
775
|
+
name={htmlName}
|
|
776
|
+
value={item.id}
|
|
777
|
+
// Disabled native controls are excluded from form submission;
|
|
778
|
+
// mirror that for the hidden carriers.
|
|
779
|
+
disabled={isDisabled}
|
|
780
|
+
/>
|
|
781
|
+
))}
|
|
763
782
|
{(endContent || (hasClear && value.length > 0 && !isDisabled)) && (
|
|
764
783
|
<div {...stylex.props(styles.endSection, endSectionSizeStyles[size])}>
|
|
765
784
|
{endContent}
|
|
@@ -168,7 +168,7 @@ describe('Toolbar', () => {
|
|
|
168
168
|
|
|
169
169
|
it('passes variant to Section', () => {
|
|
170
170
|
const {container} = render(<Toolbar label="Actions" variant="muted" />);
|
|
171
|
-
// Section renders with
|
|
171
|
+
// Section renders with astryx-section class containing the variant
|
|
172
172
|
const sectionInner = container.querySelector('.astryx-section');
|
|
173
173
|
expect(sectionInner).toBeInTheDocument();
|
|
174
174
|
expect(sectionInner?.className).toContain('muted');
|
|
@@ -17,7 +17,7 @@ export const docs = {
|
|
|
17
17
|
theming: {
|
|
18
18
|
targets: [
|
|
19
19
|
{className: 'astryx-top-nav', states: ['mode']},
|
|
20
|
-
{className: 'astryx-top-nav-item', states: ['mode']},
|
|
20
|
+
{className: 'astryx-top-nav-item', states: ['mode', 'selected']},
|
|
21
21
|
{className: 'astryx-top-nav-heading'},
|
|
22
22
|
{className: 'astryx-top-nav-mega-menu', states: ['mode']},
|
|
23
23
|
{className: 'astryx-top-nav-mega-menu-item', states: ['mode']},
|
|
@@ -16,6 +16,7 @@ import {TopNav} from './TopNav';
|
|
|
16
16
|
import {TopNavHeading} from './TopNavHeading';
|
|
17
17
|
import {NavIcon} from '../NavIcon';
|
|
18
18
|
import {TopNavItem} from './TopNavItem';
|
|
19
|
+
import {TopNavMegaMenuFeaturedCard} from './TopNavMegaMenuFeaturedCard';
|
|
19
20
|
import {LinkProvider} from '../Link/LinkProvider';
|
|
20
21
|
|
|
21
22
|
function CustomLink({
|
|
@@ -398,4 +399,21 @@ describe('TopNavItem', () => {
|
|
|
398
399
|
expect(link).toHaveAttribute('data-custom-link');
|
|
399
400
|
expect(link).not.toHaveAttribute('data-another-link');
|
|
400
401
|
});
|
|
402
|
+
|
|
403
|
+
describe('TopNavMegaMenuFeaturedCard rest forwarding', () => {
|
|
404
|
+
it('forwards data-testid, id, and aria-* to the root element', () => {
|
|
405
|
+
render(
|
|
406
|
+
<TopNavMegaMenuFeaturedCard
|
|
407
|
+
title="What's new"
|
|
408
|
+
description="Details"
|
|
409
|
+
data-testid="featured-card"
|
|
410
|
+
id="card-1"
|
|
411
|
+
aria-label="Featured"
|
|
412
|
+
/>,
|
|
413
|
+
);
|
|
414
|
+
const card = screen.getByTestId('featured-card');
|
|
415
|
+
expect(card).toHaveAttribute('id', 'card-1');
|
|
416
|
+
expect(card).toHaveAttribute('aria-label', 'Featured');
|
|
417
|
+
});
|
|
418
|
+
});
|
|
401
419
|
});
|
|
@@ -132,6 +132,10 @@ export function TopNavMegaMenuFeaturedCard({
|
|
|
132
132
|
linkLabel,
|
|
133
133
|
linkHref,
|
|
134
134
|
children,
|
|
135
|
+
xstyle,
|
|
136
|
+
className,
|
|
137
|
+
style,
|
|
138
|
+
...rest
|
|
135
139
|
}: TopNavMegaMenuFeaturedCardProps) {
|
|
136
140
|
const LinkComponent = useLinkComponent();
|
|
137
141
|
return (
|
|
@@ -139,8 +143,11 @@ export function TopNavMegaMenuFeaturedCard({
|
|
|
139
143
|
ref={ref}
|
|
140
144
|
{...mergeProps(
|
|
141
145
|
themeProps('top-nav-mega-menu-featured-card'),
|
|
142
|
-
stylex.props(styles.root),
|
|
143
|
-
|
|
146
|
+
stylex.props(styles.root, xstyle),
|
|
147
|
+
className,
|
|
148
|
+
style,
|
|
149
|
+
)}
|
|
150
|
+
{...rest}>
|
|
144
151
|
{image && (
|
|
145
152
|
<img src={image} alt={imageAlt ?? ''} {...stylex.props(styles.image)} />
|
|
146
153
|
)}
|
|
@@ -25,7 +25,7 @@ export const docs = {
|
|
|
25
25
|
theming: {
|
|
26
26
|
targets: [
|
|
27
27
|
{className: 'astryx-tree-list', visualProps: ['density']},
|
|
28
|
-
{className: 'astryx-tree-list-item', states: ['selected', 'disabled']},
|
|
28
|
+
{className: 'astryx-tree-list-item', visualProps: ['density'], states: ['selected', 'disabled']},
|
|
29
29
|
],
|
|
30
30
|
},
|
|
31
31
|
components: [
|
|
@@ -89,7 +89,7 @@ export const docsZh = {
|
|
|
89
89
|
theming: {
|
|
90
90
|
targets: [
|
|
91
91
|
{className: 'astryx-tree-list', visualProps: ['density']},
|
|
92
|
-
{className: 'astryx-tree-list-item', states: ['selected', 'disabled']},
|
|
92
|
+
{className: 'astryx-tree-list-item', visualProps: ['density'], states: ['selected', 'disabled']},
|
|
93
93
|
],
|
|
94
94
|
},
|
|
95
95
|
components: [
|
|
@@ -8,6 +8,16 @@ export const docs = {
|
|
|
8
8
|
displayName: 'Base Typeahead',
|
|
9
9
|
isHiddenFromOverview: true,
|
|
10
10
|
description: 'Unstyled combobox engine providing input, search, keyboard navigation, and dropdown. No wrapper div, no border styling, no token rendering. Used by Typeahead and Tokenizer for custom compositions.',
|
|
11
|
+
usage: {
|
|
12
|
+
description: 'Unstyled combobox engine providing input, search, keyboard navigation, and dropdown. No wrapper div, no border styling, no token rendering. Used by Typeahead and Tokenizer for custom compositions.',
|
|
13
|
+
bestPractices: [
|
|
14
|
+
{ guidance: true, description: 'Use Typeahead or Tokenizer for standard fields; they wrap BaseTypeahead with the wrapper div, border styling, and token rendering it intentionally omits.' },
|
|
15
|
+
{ guidance: true, description: 'Provide your own wrapper div with border and layout when composing directly, since BaseTypeahead renders no visual chrome of its own.' },
|
|
16
|
+
{ guidance: true, description: 'Pass anchorRef pointing to your wrapper so the dropdown positions against your custom input chrome, not just the bare input element.' },
|
|
17
|
+
{ guidance: false, description: 'Expect a wrapper div, border, or token rendering. BaseTypeahead is an engine only; all visual chrome is the caller\'s responsibility.' },
|
|
18
|
+
{ guidance: false, description: 'Use BaseTypeahead when Typeahead or Tokenizer would suffice; the extra wrapper and styling work is only justified for truly custom compositions.' },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
11
21
|
props: [
|
|
12
22
|
{
|
|
13
23
|
name: 'searchSource',
|
|
@@ -226,6 +236,15 @@ export const docsDense = {
|
|
|
226
236
|
isHiddenFromOverview: true,
|
|
227
237
|
displayName: 'Base Typeahead',
|
|
228
238
|
description: 'Unstyled combobox engine; input+search+keyboard nav+dropdown. No wrapper/border/token. Used by Typeahead+Tokenizer.',
|
|
239
|
+
usage: {
|
|
240
|
+
bestPractices: [
|
|
241
|
+
{ guidance: true, description: 'Use Typeahead or Tokenizer for standard fields; they add the wrapper, border, and token rendering BaseTypeahead omits.' },
|
|
242
|
+
{ guidance: true, description: 'Provide your own wrapper div with border and layout when composing directly; BaseTypeahead renders no chrome.' },
|
|
243
|
+
{ guidance: true, description: 'Pass anchorRef to your wrapper so the dropdown positions against your input chrome, not the bare input.' },
|
|
244
|
+
{ guidance: false, description: 'Expect wrapper, border, or token rendering. Engine only; chrome is the caller\'s job.' },
|
|
245
|
+
{ guidance: false, description: 'Use BaseTypeahead when Typeahead or Tokenizer suffice; extra work only pays off for custom compositions.' },
|
|
246
|
+
],
|
|
247
|
+
},
|
|
229
248
|
propDescriptions: {
|
|
230
249
|
searchSource: 'Data source w/ search+bootstrap methods.',
|
|
231
250
|
value: 'Currently selected item.',
|
|
@@ -410,7 +410,10 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
410
410
|
const performSearch = useCallback(
|
|
411
411
|
async (searchQuery: string) => {
|
|
412
412
|
searchSource.cancel?.();
|
|
413
|
-
|
|
413
|
+
// Claim a new generation so overlapping searches can't race: an
|
|
414
|
+
// in-flight response for an older query fails the gen check below
|
|
415
|
+
// instead of overwriting the newer results.
|
|
416
|
+
const gen = ++searchGenRef.current;
|
|
414
417
|
setIsLoading(true);
|
|
415
418
|
setHasSearched(true);
|
|
416
419
|
try {
|
|
@@ -451,7 +454,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
451
454
|
|
|
452
455
|
// Perform bootstrap
|
|
453
456
|
const performBootstrap = useCallback(async () => {
|
|
454
|
-
const gen = searchGenRef.current;
|
|
457
|
+
const gen = ++searchGenRef.current;
|
|
455
458
|
setIsLoading(true);
|
|
456
459
|
try {
|
|
457
460
|
const bootstrapResults = await searchSource.bootstrap();
|
|
@@ -75,7 +75,7 @@ export const docs = {
|
|
|
75
75
|
name: 'disabledMessage',
|
|
76
76
|
type: 'string',
|
|
77
77
|
description:
|
|
78
|
-
'Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the field focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled Typeahead in Tooltip
|
|
78
|
+
'Explains why the input is disabled. With isDisabled, shows a tooltip on hover/keyboard focus and keeps the field focusable via aria-disabled (activation stays blocked). Use this instead of wrapping a disabled Typeahead in Tooltip. Disabled controls swallow the hover events an external Tooltip needs.',
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
81
|
name: 'maxMenuItems',
|
|
@@ -168,7 +168,7 @@ export const docs = {
|
|
|
168
168
|
components: [{name: 'BaseTypeahead'}, {name: 'TypeaheadItem'}],
|
|
169
169
|
theming: {
|
|
170
170
|
targets: [
|
|
171
|
-
{className: 'astryx-typeahead', visualProps: ['status']},
|
|
171
|
+
{className: 'astryx-typeahead', visualProps: ['status', 'size']},
|
|
172
172
|
{className: 'astryx-typeahead-dropdown'},
|
|
173
173
|
{className: 'astryx-typeahead-item'},
|
|
174
174
|
],
|
|
@@ -287,6 +287,11 @@ export const docsDense = {
|
|
|
287
287
|
description:
|
|
288
288
|
'Add a search delay for remote data sources to avoid excessive network requests.',
|
|
289
289
|
},
|
|
290
|
+
{
|
|
291
|
+
guidance: true,
|
|
292
|
+
description:
|
|
293
|
+
'Use inside InputGroup when the typeahead needs a single-line prefix or suffix addon.',
|
|
294
|
+
},
|
|
290
295
|
{
|
|
291
296
|
guidance: false,
|
|
292
297
|
description:
|