@astryxdesign/core 0.1.4 → 0.1.5-canary.76e6697
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 +141 -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.d.ts +0 -2
- package/dist/AlertDialog/useImperativeAlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/useImperativeAlertDialog.js +3 -5
- 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.d.ts +48 -10
- package/dist/AspectRatio/AspectRatio.d.ts.map +1 -1
- package/dist/AspectRatio/AspectRatio.js +33 -12
- package/dist/AspectRatio/index.d.ts +1 -1
- package/dist/AspectRatio/index.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +28 -26
- package/dist/Avatar/AvatarStatusDot.js +6 -6
- package/dist/AvatarGroup/AvatarGroup.js +6 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -7
- 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.js +19 -19
- package/dist/ButtonGroup/ButtonGroup.js +7 -7
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +68 -48
- package/dist/Calendar/dayCellUtils.d.ts.map +1 -1
- 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 +24 -21
- 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 +1 -1
- 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.d.ts.map +1 -1
- package/dist/Chat/useTriggerMenu.js +15 -15
- package/dist/CheckboxInput/CheckboxInput.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +25 -23
- 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.js +3 -3
- 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/Collapsible/Collapsible.d.ts +9 -3
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +109 -22
- package/dist/Collapsible/CollapsibleGroup.d.ts +37 -7
- package/dist/Collapsible/CollapsibleGroup.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroup.js +64 -12
- package/dist/Collapsible/CollapsibleGroupContext.d.ts +24 -0
- package/dist/Collapsible/CollapsibleGroupContext.d.ts.map +1 -1
- package/dist/Collapsible/CollapsibleGroupContext.js +26 -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.js +3 -3
- 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 +7 -2
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +76 -43
- package/dist/DateInput/DateInput.js +18 -18
- package/dist/DateRangeInput/DateRangeInput.js +21 -21
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
- 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.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.d.ts +5 -1
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- 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.d.ts +29 -2
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +44 -31
- 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.d.ts +0 -1
- package/dist/Lightbox/useLightbox.d.ts.map +1 -1
- package/dist/Lightbox/useLightbox.js +3 -4
- package/dist/Link/Link.d.ts +0 -2
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +15 -17
- 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/MetadataList/MetadataList.js +10 -10
- package/dist/MetadataList/MetadataListItem.js +15 -15
- package/dist/MobileNav/MobileNav.d.ts +1 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +26 -23
- package/dist/MobileNav/MobileNavToggle.js +5 -5
- package/dist/MoreMenu/MoreMenu.js +3 -3
- package/dist/MultiSelector/MultiSelector.js +56 -56
- 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.d.ts +0 -3
- package/dist/Overlay/useOverlay.d.ts.map +1 -1
- package/dist/Overlay/useOverlay.js +3 -6
- 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.js +7 -7
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +24 -21
- 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.js +46 -46
- 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.js +23 -23
- package/dist/Spinner/Spinner.js +9 -9
- package/dist/StatusDot/StatusDot.js +5 -5
- package/dist/Switch/Switch.d.ts +8 -4
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +34 -29
- 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 +50 -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.js +3 -3
- 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/groupedRows/index.d.ts +3 -0
- package/dist/Table/plugins/groupedRows/index.d.ts.map +1 -0
- package/dist/Table/plugins/groupedRows/index.js +3 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +78 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +250 -0
- 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/useTableRowExpansion.d.ts +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +23 -23
- 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.js +9 -9
- package/dist/Text/Text.js +10 -10
- 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.d.ts.map +1 -1
- package/dist/Toast/useToast.js +44 -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.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +36 -34
- package/dist/Toolbar/Toolbar.js +18 -18
- package/dist/Tooltip/Tooltip.js +11 -11
- package/dist/Tooltip/useTooltip.d.ts +5 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- 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/VisuallyHidden/VisuallyHidden.d.ts +0 -3
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +0 -3
- package/dist/astryx.css +7 -0
- package/dist/astryx.umd.js +63 -63
- package/dist/astryx.umd.js.map +4 -4
- package/dist/docs-types.d.ts +8 -2
- 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/theme/useTheme.d.ts +3 -2
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +73 -6
- 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 +4 -4
- package/src/AlertDialog/AlertDialog.doc.mjs +4 -0
- package/src/AlertDialog/AlertDialog.tsx +2 -0
- package/src/AlertDialog/useImperativeAlertDialog.tsx +0 -2
- package/src/AppShell/AppShell.tsx +2 -0
- package/src/AspectRatio/AspectRatio.doc.mjs +28 -1
- package/src/AspectRatio/AspectRatio.test.tsx +142 -1
- package/src/AspectRatio/AspectRatio.tsx +70 -10
- package/src/AspectRatio/index.ts +5 -1
- package/src/Avatar/Avatar.doc.mjs +11 -0
- package/src/Avatar/Avatar.test.tsx +32 -1
- package/src/Avatar/Avatar.tsx +14 -22
- package/src/Avatar/AvatarStatusDot.tsx +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -0
- package/src/AvatarGroup/AvatarGroup.tsx +2 -2
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +2 -2
- 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/Calendar/Calendar.doc.mjs +1 -1
- package/src/Calendar/Calendar.test.tsx +122 -17
- package/src/Calendar/Calendar.tsx +26 -5
- package/src/Calendar/dayCellUtils.ts +3 -1
- 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 +4 -2
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposerInput.test.tsx +27 -1
- package/src/Chat/ChatComposerInput.tsx +20 -15
- 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/useTriggerMenu.tsx +1 -4
- package/src/CheckboxInput/CheckboxInput.doc.mjs +3 -3
- package/src/CheckboxInput/CheckboxInput.test.tsx +71 -4
- package/src/CheckboxInput/CheckboxInput.tsx +2 -0
- 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/CodeBlock/CodeBlock.doc.mjs +7 -2
- package/src/CodeBlock/CodeBlock.test.tsx +122 -3
- package/src/CodeBlock/CodeBlock.tsx +62 -4
- package/src/Collapsible/Collapsible.doc.mjs +8 -4
- package/src/Collapsible/Collapsible.test.tsx +403 -0
- package/src/Collapsible/Collapsible.tsx +85 -10
- package/src/Collapsible/CollapsibleGroup.doc.mjs +27 -3
- package/src/Collapsible/CollapsibleGroup.test.tsx +314 -0
- package/src/Collapsible/CollapsibleGroup.tsx +97 -9
- package/src/Collapsible/CollapsibleGroupContext.tsx +34 -2
- package/src/Collapsible/index.ts +1 -0
- package/src/Collapsible/useCollapsible.ts +20 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +5 -0
- package/src/CommandPalette/CommandPalette.tsx +5 -3
- package/src/CommandPalette/CommandPaletteEmpty.doc.mjs +5 -0
- 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 +87 -0
- package/src/ContextMenu/ContextMenu.tsx +87 -28
- package/src/ContextMenu/ContextMenuItem.doc.mjs +6 -0
- package/src/DateInput/DateInput.test.tsx +11 -20
- package/src/DateRangeInput/DateRangeInput.doc.mjs +9 -6
- package/src/DateRangeInput/DateRangeInput.test.tsx +31 -44
- package/src/DateTimeInput/DateTimeInput.doc.mjs +3 -2
- package/src/DateTimeInput/DateTimeInput.test.tsx +118 -16
- package/src/DateTimeInput/DateTimeInput.tsx +8 -2
- package/src/DateTimeInput/index.ts +1 -0
- package/src/Dialog/Dialog.doc.mjs +4 -0
- package/src/Dialog/DialogHeader.doc.mjs +45 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -1
- package/src/DropdownMenu/DropdownMenu.test.tsx +22 -2
- package/src/DropdownMenu/DropdownMenuItem.tsx +5 -17
- package/src/EmptyState/EmptyState.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +1 -4
- package/src/Field/FieldLabel.test.tsx +2 -2
- package/src/FieldStatus/FieldStatus.test.tsx +282 -0
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -3
- package/src/Grid/Grid.test.tsx +43 -18
- package/src/Grid/Grid.tsx +26 -9
- package/src/HoverCard/HoverCard.doc.mjs +6 -6
- package/src/HoverCard/useHoverCard.doc.mjs +5 -5
- package/src/HoverCard/useHoverCard.tsx +9 -2
- package/src/Icon/Icon.test.tsx +41 -29
- package/src/Icon/Icon.tsx +6 -2
- package/src/InputGroup/InputGroup.doc.mjs +1 -0
- package/src/InputGroup/InputGroup.tsx +2 -2
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +185 -0
- package/src/Item/Item.tsx +1 -1
- package/src/Layer/useLayer.doc.mjs +2 -2
- package/src/Layer/useLayer.test.tsx +221 -2
- package/src/Layer/useLayer.tsx +69 -30
- 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/Lightbox/Lightbox.doc.mjs +5 -0
- package/src/Lightbox/Lightbox.test.tsx +123 -2
- package/src/Lightbox/Lightbox.tsx +29 -1
- package/src/Lightbox/useLightbox.tsx +0 -1
- package/src/Link/Link.tsx +0 -2
- package/src/Markdown/Markdown.tsx +9 -7
- package/src/Markdown/parser.perf.test.ts +34 -12
- package/src/MobileNav/MobileNav.test.tsx +56 -0
- package/src/MobileNav/MobileNav.tsx +13 -8
- 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/Outline.doc.mjs +2 -0
- 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/Overlay/useOverlay.tsx +0 -3
- package/src/Pagination/Pagination.test.tsx +162 -0
- package/src/Pagination/Pagination.tsx +80 -26
- package/src/Popover/Popover.doc.mjs +6 -6
- package/src/Popover/Popover.test.tsx +65 -0
- package/src/Popover/usePopover.doc.mjs +1 -1
- package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
- package/src/PowerSearch/PowerSearch.test.tsx +109 -1
- package/src/PowerSearch/PowerSearch.tsx +37 -16
- package/src/ProgressBar/ProgressBar.doc.mjs +2 -0
- package/src/ProgressBar/ProgressBar.test.tsx +30 -0
- package/src/ProgressBar/ProgressBar.tsx +12 -5
- package/src/RadioList/RadioList.test.tsx +19 -0
- package/src/RadioList/RadioListItem.tsx +9 -4
- package/src/Resizable/ResizeHandle.test.tsx +218 -0
- package/src/Resizable/ResizeHandle.tsx +22 -4
- package/src/SegmentedControl/SegmentedControl.doc.mjs +1 -1
- 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.test.tsx +27 -1
- 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/Switch/Switch.doc.mjs +7 -7
- package/src/Switch/Switch.test.tsx +102 -3
- package/src/Switch/Switch.tsx +20 -7
- package/src/TabList/TabList.test.tsx +185 -1
- package/src/TabList/TabMenu.tsx +45 -9
- package/src/Table/BaseTable.tsx +13 -2
- package/src/Table/Table.doc.mjs +6 -1
- package/src/Table/Table.test.tsx +87 -0
- package/src/Table/TableBody.tsx +15 -2
- 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/groupedRows/index.ts +7 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +231 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +349 -0
- package/src/Table/plugins/pagination/paginateData.ts +5 -1
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +13 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +1 -1
- 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/useTableGroupedRows.doc.mjs +71 -0
- package/src/TextArea/TextArea.test.tsx +3 -3
- 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.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/Toast/useToast.test.tsx +258 -0
- package/src/Toast/useToast.tsx +41 -0
- package/src/ToggleButton/ToggleButton.doc.mjs +1 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -2
- package/src/Tokenizer/Tokenizer.test.tsx +54 -0
- package/src/Tokenizer/Tokenizer.tsx +5 -4
- package/src/Tooltip/Tooltip.doc.mjs +6 -6
- package/src/Tooltip/useTooltip.doc.mjs +5 -5
- package/src/Tooltip/useTooltip.tsx +12 -2
- package/src/TopNav/TopNav.doc.mjs +1 -1
- package/src/TopNav/TopNav.test.tsx +23 -7
- 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 +1 -1
- package/src/Typeahead/Typeahead.test.tsx +45 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +0 -3
- 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 +9 -1
- 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/useStreamingText.test.ts +54 -19
- package/src/hooks/useStreamingText.ts +16 -5
- package/src/hooks/useTreeFocus.test.tsx +1 -3
- package/src/reset.css +29 -0
- 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/themingTargets.test.ts +353 -0
- package/src/theme/tokens.test.ts +182 -9
- package/src/theme/tokens.ts +239 -4
- package/src/theme/useTheme.test.tsx +126 -2
- package/src/theme/useTheme.ts +87 -6
- 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
- package/dist/Carousel/carousel.markers.stylex.d.ts +0 -7
- package/dist/Carousel/carousel.markers.stylex.d.ts.map +0 -1
- package/dist/Carousel/carousel.markers.stylex.js +0 -12
- package/src/Carousel/carousel.markers.stylex.ts +0 -10
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
import {describe, it, expect, vi} from 'vitest';
|
|
13
13
|
import {act, render, screen, within} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
|
+
import {getButton} from '../__tests__/fastRoleQueries';
|
|
16
|
+
import * as stylex from '@stylexjs/stylex';
|
|
15
17
|
import {Calendar} from './Calendar';
|
|
16
18
|
import type {CalendarHandle} from './Calendar';
|
|
19
|
+
import {calendarStyles} from './styles';
|
|
17
20
|
|
|
18
21
|
/**
|
|
19
22
|
* Helper to find a day button by its day number.
|
|
@@ -24,7 +27,7 @@ import type {CalendarHandle} from './Calendar';
|
|
|
24
27
|
function getDayButton(day: number, month = 'January', year = 2026) {
|
|
25
28
|
// Match the full date pattern with the day number
|
|
26
29
|
const pattern = new RegExp(`${month}\\s+${day},\\s+${year}`);
|
|
27
|
-
return
|
|
30
|
+
return getButton(pattern);
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
describe('Calendar', () => {
|
|
@@ -71,6 +74,24 @@ describe('Calendar', () => {
|
|
|
71
74
|
expect(screen.getByText(expectedLabel)).toBeInTheDocument();
|
|
72
75
|
});
|
|
73
76
|
|
|
77
|
+
it("marks today's cell with aria-current='date'", () => {
|
|
78
|
+
render(<Calendar />);
|
|
79
|
+
|
|
80
|
+
const now = new Date();
|
|
81
|
+
const iso = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
|
82
|
+
|
|
83
|
+
const todayCell = document.querySelector(`button[data-date="${iso}"]`);
|
|
84
|
+
expect(todayCell).not.toBeNull();
|
|
85
|
+
expect(todayCell).toHaveAttribute('aria-current', 'date');
|
|
86
|
+
|
|
87
|
+
// Only today's cell is marked current.
|
|
88
|
+
const others = Array.from(
|
|
89
|
+
document.querySelectorAll('button[data-date]'),
|
|
90
|
+
).filter(el => el.getAttribute('data-date') !== iso);
|
|
91
|
+
expect(others.length).toBeGreaterThan(0);
|
|
92
|
+
others.forEach(el => expect(el).not.toHaveAttribute('aria-current'));
|
|
93
|
+
});
|
|
94
|
+
|
|
74
95
|
it('displays day names', () => {
|
|
75
96
|
render(<Calendar />);
|
|
76
97
|
|
|
@@ -97,7 +118,11 @@ describe('Calendar', () => {
|
|
|
97
118
|
render(<Calendar value="2026-01-15" focusDate="2026-01-01" />);
|
|
98
119
|
|
|
99
120
|
const day15 = getDayButton(15);
|
|
100
|
-
|
|
121
|
+
// In an ARIA grid, selection state lives on the gridcell, not the button
|
|
122
|
+
// (a plain button role does not permit aria-selected).
|
|
123
|
+
const gridcell15 = day15.closest('[role="gridcell"]');
|
|
124
|
+
expect(gridcell15).toHaveAttribute('aria-selected', 'true');
|
|
125
|
+
expect(day15).not.toHaveAttribute('aria-selected');
|
|
101
126
|
});
|
|
102
127
|
|
|
103
128
|
it('calls onChange when date is selected', async () => {
|
|
@@ -123,7 +148,7 @@ describe('Calendar', () => {
|
|
|
123
148
|
// Verify we start on February
|
|
124
149
|
expect(screen.getByText('February 2026')).toBeInTheDocument();
|
|
125
150
|
|
|
126
|
-
const prevButton =
|
|
151
|
+
const prevButton = getButton('Previous month');
|
|
127
152
|
await user.click(prevButton);
|
|
128
153
|
|
|
129
154
|
expect(screen.getByText('January 2026')).toBeInTheDocument();
|
|
@@ -137,7 +162,7 @@ describe('Calendar', () => {
|
|
|
137
162
|
// Verify we start on January
|
|
138
163
|
expect(screen.getByText('January 2026')).toBeInTheDocument();
|
|
139
164
|
|
|
140
|
-
const nextButton =
|
|
165
|
+
const nextButton = getButton('Next month');
|
|
141
166
|
await user.click(nextButton);
|
|
142
167
|
|
|
143
168
|
expect(screen.getByText('February 2026')).toBeInTheDocument();
|
|
@@ -151,7 +176,7 @@ describe('Calendar', () => {
|
|
|
151
176
|
<Calendar focusDate="2026-01-01" onFocusDateChange={handleFocusChange} />,
|
|
152
177
|
);
|
|
153
178
|
|
|
154
|
-
const nextButton =
|
|
179
|
+
const nextButton = getButton('Next month');
|
|
155
180
|
await user.click(nextButton);
|
|
156
181
|
|
|
157
182
|
expect(handleFocusChange).toHaveBeenCalledWith('2026-02-01');
|
|
@@ -209,12 +234,39 @@ describe('Calendar', () => {
|
|
|
209
234
|
|
|
210
235
|
render(<Calendar numberOfMonths={2} focusDate="2026-01-01" />);
|
|
211
236
|
|
|
212
|
-
const nextButton =
|
|
237
|
+
const nextButton = getButton('Next month');
|
|
213
238
|
await user.click(nextButton);
|
|
214
239
|
|
|
215
240
|
expect(screen.getByText(/February 2026.*March 2026/)).toBeInTheDocument();
|
|
216
241
|
});
|
|
217
242
|
|
|
243
|
+
it('clamps out-of-range numberOfMonths to a single month', () => {
|
|
244
|
+
// 1000 would otherwise try to render 1000 month grids and lock the page up.
|
|
245
|
+
render(
|
|
246
|
+
<Calendar
|
|
247
|
+
numberOfMonths={1000 as unknown as 1 | 2}
|
|
248
|
+
focusDate="2026-01-01"
|
|
249
|
+
/>,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
// Only the focused month renders — no second month, no range separator.
|
|
253
|
+
expect(screen.getByText('January 2026')).toBeInTheDocument();
|
|
254
|
+
expect(screen.queryByText(/February 2026/)).not.toBeInTheDocument();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('clamps numberOfMonths={0} to a single month', () => {
|
|
258
|
+
render(
|
|
259
|
+
<Calendar
|
|
260
|
+
numberOfMonths={0 as unknown as 1 | 2}
|
|
261
|
+
focusDate="2026-01-01"
|
|
262
|
+
/>,
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
// 0 previously rendered no months at all; now falls back to one.
|
|
266
|
+
expect(screen.getByText('January 2026')).toBeInTheDocument();
|
|
267
|
+
expect(screen.getAllByRole('gridcell').length).toBeGreaterThan(0);
|
|
268
|
+
});
|
|
269
|
+
|
|
218
270
|
// ─── Display Options ─────────────────────────────────────────
|
|
219
271
|
|
|
220
272
|
it('shows week numbers when hasWeekNumbers is true', () => {
|
|
@@ -310,9 +362,22 @@ describe('Calendar', () => {
|
|
|
310
362
|
const day12 = getDayButton(12);
|
|
311
363
|
const day15 = getDayButton(15);
|
|
312
364
|
|
|
313
|
-
|
|
314
|
-
expect(
|
|
315
|
-
|
|
365
|
+
// Selection state lives on the gridcell wrapper, not the day button.
|
|
366
|
+
expect(day10.closest('[role="gridcell"]')).toHaveAttribute(
|
|
367
|
+
'aria-selected',
|
|
368
|
+
'true',
|
|
369
|
+
);
|
|
370
|
+
expect(day12.closest('[role="gridcell"]')).toHaveAttribute(
|
|
371
|
+
'aria-selected',
|
|
372
|
+
'true',
|
|
373
|
+
);
|
|
374
|
+
expect(day15.closest('[role="gridcell"]')).toHaveAttribute(
|
|
375
|
+
'aria-selected',
|
|
376
|
+
'true',
|
|
377
|
+
);
|
|
378
|
+
expect(day10).not.toHaveAttribute('aria-selected');
|
|
379
|
+
expect(day12).not.toHaveAttribute('aria-selected');
|
|
380
|
+
expect(day15).not.toHaveAttribute('aria-selected');
|
|
316
381
|
});
|
|
317
382
|
|
|
318
383
|
it('caps the range highlight next to a disabled mid-range day (#2715)', () => {
|
|
@@ -476,12 +541,8 @@ describe('Calendar', () => {
|
|
|
476
541
|
it('has navigation buttons with accessible labels', () => {
|
|
477
542
|
render(<Calendar />);
|
|
478
543
|
|
|
479
|
-
expect(
|
|
480
|
-
|
|
481
|
-
).toBeInTheDocument();
|
|
482
|
-
expect(
|
|
483
|
-
screen.getByRole('button', {name: 'Next month'}),
|
|
484
|
-
).toBeInTheDocument();
|
|
544
|
+
expect(getButton('Previous month')).toBeInTheDocument();
|
|
545
|
+
expect(getButton('Next month')).toBeInTheDocument();
|
|
485
546
|
});
|
|
486
547
|
|
|
487
548
|
// ─── Bug Regression Tests ───────────────────────────────────
|
|
@@ -589,14 +650,14 @@ describe('Calendar', () => {
|
|
|
589
650
|
it('prev button is disabled when focusDate month contains min', () => {
|
|
590
651
|
render(<Calendar focusDate="2026-01-01" min="2026-01-15" />);
|
|
591
652
|
|
|
592
|
-
const prevButton =
|
|
653
|
+
const prevButton = getButton('Previous month');
|
|
593
654
|
expect(prevButton).toBeDisabled();
|
|
594
655
|
});
|
|
595
656
|
|
|
596
657
|
it('next button is disabled when focusDate month contains max', () => {
|
|
597
658
|
render(<Calendar focusDate="2026-01-01" max="2026-01-15" />);
|
|
598
659
|
|
|
599
|
-
const nextButton =
|
|
660
|
+
const nextButton = getButton('Next month');
|
|
600
661
|
expect(nextButton).toBeDisabled();
|
|
601
662
|
});
|
|
602
663
|
|
|
@@ -675,4 +736,48 @@ describe('Calendar', () => {
|
|
|
675
736
|
}
|
|
676
737
|
}
|
|
677
738
|
});
|
|
739
|
+
|
|
740
|
+
// ─── RTL (#3388) ─────────────────────────────────────────────
|
|
741
|
+
|
|
742
|
+
describe('RTL month navigation', () => {
|
|
743
|
+
// jsdom does not apply compiled StyleX CSS, so the scaleX(-1) mirror
|
|
744
|
+
// itself is only observable in a browser (see the dir="rtl" Storybook
|
|
745
|
+
// story). These tests pin the structure the fix depends on: both nav
|
|
746
|
+
// chevrons render inside the navIcon wrapper that carries the
|
|
747
|
+
// ':is([dir="rtl"] *)' conditional transform.
|
|
748
|
+
it('wraps both nav chevrons in the RTL-mirroring navIcon wrapper', () => {
|
|
749
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
750
|
+
|
|
751
|
+
const {className: navIconClass} = stylex.props(calendarStyles.navIcon);
|
|
752
|
+
expect(navIconClass).toBeTruthy();
|
|
753
|
+
|
|
754
|
+
for (const name of ['Previous month', 'Next month']) {
|
|
755
|
+
const button = getButton(name);
|
|
756
|
+
const wrappers = Array.from(button.querySelectorAll('span')).filter(
|
|
757
|
+
span => span.className === navIconClass,
|
|
758
|
+
);
|
|
759
|
+
expect(wrappers.length).toBe(1);
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it('keeps navigation semantics unchanged under dir="rtl"', async () => {
|
|
764
|
+
const user = userEvent.setup();
|
|
765
|
+
|
|
766
|
+
render(
|
|
767
|
+
<div dir="rtl">
|
|
768
|
+
<Calendar focusDate="2026-02-01" />
|
|
769
|
+
</div>,
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
expect(screen.getByText('February 2026')).toBeInTheDocument();
|
|
773
|
+
|
|
774
|
+
// DOM order and handlers must not change in RTL: flexbox already
|
|
775
|
+
// places "Previous month" at the visual right; only the glyph mirrors.
|
|
776
|
+
await user.click(getButton('Previous month'));
|
|
777
|
+
expect(screen.getByText('January 2026')).toBeInTheDocument();
|
|
778
|
+
|
|
779
|
+
await user.click(getButton('Next month'));
|
|
780
|
+
expect(screen.getByText('February 2026')).toBeInTheDocument();
|
|
781
|
+
});
|
|
782
|
+
});
|
|
678
783
|
});
|
|
@@ -203,7 +203,7 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
203
203
|
value,
|
|
204
204
|
defaultValue,
|
|
205
205
|
onChange,
|
|
206
|
-
numberOfMonths = 1,
|
|
206
|
+
numberOfMonths: numberOfMonthsProp = 1,
|
|
207
207
|
min,
|
|
208
208
|
max,
|
|
209
209
|
dateConstraints,
|
|
@@ -223,6 +223,11 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
223
223
|
// DayOfWeek so all downstream date math keeps working with an index.
|
|
224
224
|
const weekStartsOn = normalizeDayOfWeek(weekStartsOnProp);
|
|
225
225
|
|
|
226
|
+
// `numberOfMonths` is typed `1 | 2`; defensively clamp anything else that
|
|
227
|
+
// slips through at runtime to 1 so `Array.from({length})` can't render an
|
|
228
|
+
// absurd number of month grids (e.g. `numberOfMonths={1000}`).
|
|
229
|
+
const numberOfMonths = numberOfMonthsProp === 2 ? 2 : 1;
|
|
230
|
+
|
|
226
231
|
// Today's date (memoized)
|
|
227
232
|
const today = useMemo(() => plainDateToday(), []);
|
|
228
233
|
|
|
@@ -426,7 +431,14 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
426
431
|
<Button
|
|
427
432
|
label="Previous month"
|
|
428
433
|
variant="ghost"
|
|
429
|
-
icon={
|
|
434
|
+
icon={
|
|
435
|
+
// Wrapper span (not Icon props): Icon's string mode clobbers
|
|
436
|
+
// caller classNames, so the RTL mirror must live on its own
|
|
437
|
+
// element.
|
|
438
|
+
<span {...stylex.props(calendarStyles.navIcon)}>
|
|
439
|
+
<Icon icon="chevronLeft" size="sm" color="inherit" />
|
|
440
|
+
</span>
|
|
441
|
+
}
|
|
430
442
|
onClick={() => navigateMonth(-1)}
|
|
431
443
|
isDisabled={!canNavigatePrevious}
|
|
432
444
|
isIconOnly
|
|
@@ -439,7 +451,11 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
439
451
|
<Button
|
|
440
452
|
label="Next month"
|
|
441
453
|
variant="ghost"
|
|
442
|
-
icon={
|
|
454
|
+
icon={
|
|
455
|
+
<span {...stylex.props(calendarStyles.navIcon)}>
|
|
456
|
+
<Icon icon="chevronRight" size="sm" color="inherit" />
|
|
457
|
+
</span>
|
|
458
|
+
}
|
|
443
459
|
onClick={() => navigateMonth(1)}
|
|
444
460
|
isDisabled={!canNavigateNext}
|
|
445
461
|
isIconOnly
|
|
@@ -912,7 +928,10 @@ function DayCell({
|
|
|
912
928
|
});
|
|
913
929
|
|
|
914
930
|
return (
|
|
915
|
-
<div
|
|
931
|
+
<div
|
|
932
|
+
role="gridcell"
|
|
933
|
+
aria-selected={state.isSelected || state.isInRange || undefined}
|
|
934
|
+
{...stylex.props(dayCellStyles.cell)}>
|
|
916
935
|
{/* Range background */}
|
|
917
936
|
{state.isInRange && (
|
|
918
937
|
<div
|
|
@@ -952,8 +971,10 @@ function DayCell({
|
|
|
952
971
|
type="button"
|
|
953
972
|
data-date={day.iso}
|
|
954
973
|
aria-label={plainDateFormat(date, DATE_FORMAT_WITH_WEEKDAY)}
|
|
955
|
-
aria-selected={state.isSelected || state.isInRange || undefined}
|
|
956
974
|
aria-disabled={state.effectivelyDisabled || undefined}
|
|
975
|
+
// Mark today's cell programmatically (APG date-picker pattern), not just
|
|
976
|
+
// visually, so screen-reader users can identify the current date.
|
|
977
|
+
aria-current={state.isToday ? 'date' : undefined}
|
|
957
978
|
disabled={isDisabled}
|
|
958
979
|
// Initial roving tab-stop seed; useGridFocus owns it after mount.
|
|
959
980
|
tabIndex={isTabbableDay ? 0 : -1}
|
|
@@ -193,7 +193,9 @@ export function isRangeHighlighted(input: {
|
|
|
193
193
|
isDisabled: boolean;
|
|
194
194
|
isOutside: boolean;
|
|
195
195
|
}): boolean {
|
|
196
|
-
if (input.mode !== 'range') {
|
|
196
|
+
if (input.mode !== 'range') {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
197
199
|
return isSpanHighlighted({
|
|
198
200
|
date: input.date,
|
|
199
201
|
spanStart: input.rangeStart,
|
package/src/Calendar/styles.ts
CHANGED
|
@@ -64,9 +64,19 @@ export const calendarStyles = stylex.create({
|
|
|
64
64
|
whiteSpace: 'nowrap',
|
|
65
65
|
borderWidth: 0,
|
|
66
66
|
},
|
|
67
|
+
/**
|
|
68
|
+
* Wrapper for the month nav chevrons. In RTL the flex header already
|
|
69
|
+
* swaps the buttons' visual sides; the glyphs must mirror with them so
|
|
70
|
+
* "Previous month" points outward (visually right) instead of inward.
|
|
71
|
+
* Keyed on the dir attribute (dir="rtl"), same as MobileNav's drawer
|
|
72
|
+
* transform — bare CSS `direction: rtl` alone won't trigger it.
|
|
73
|
+
*/
|
|
67
74
|
navIcon: {
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
display: 'inline-flex',
|
|
76
|
+
transform: {
|
|
77
|
+
default: null,
|
|
78
|
+
':is([dir="rtl"] *)': 'scaleX(-1)',
|
|
79
|
+
},
|
|
70
80
|
},
|
|
71
81
|
});
|
|
72
82
|
|
package/src/Card/Card.doc.mjs
CHANGED
|
@@ -131,7 +131,7 @@ export const docsZh = {
|
|
|
131
131
|
theming: {
|
|
132
132
|
container: true,
|
|
133
133
|
targets: [
|
|
134
|
-
{className: 'astryx-card'},
|
|
134
|
+
{className: 'astryx-card', visualProps: ['variant']},
|
|
135
135
|
],
|
|
136
136
|
vars: [
|
|
137
137
|
{name: '--_card-radius', description: 'Border radius of the card', default: 'var(--radius-container)', private: true},
|
package/src/Card/Card.tsx
CHANGED
|
@@ -44,8 +44,10 @@ import {themeProps} from '../utils/themeProps';
|
|
|
44
44
|
* - Non-semantic palette: `blue | cyan | gray | green | orange | pink | purple | red | teal | yellow`
|
|
45
45
|
* Each uses the corresponding `--color-background-<name>` token (20% opacity tint).
|
|
46
46
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
47
|
+
* Only `default` draws a visible border. Its border width is subtracted from
|
|
48
|
+
* the padding so the total inset (border + padding) equals the padding token —
|
|
49
|
+
* keeping content geometry faithful to the spacing scale and identical to the
|
|
50
|
+
* borderless variants. Themes can override borderWidth/borderColor.
|
|
49
51
|
*/
|
|
50
52
|
export type CardVariant =
|
|
51
53
|
| 'default'
|
|
@@ -71,12 +73,18 @@ const styles = stylex.create({
|
|
|
71
73
|
'--_card-radius': radiusVars['--radius-container'],
|
|
72
74
|
borderRadius: 'var(--_card-radius)',
|
|
73
75
|
overflow: 'clip',
|
|
74
|
-
borderWidth: borderVars['--border-width'],
|
|
75
|
-
borderStyle: 'solid',
|
|
76
|
-
borderColor: 'transparent',
|
|
77
76
|
},
|
|
77
|
+
// The border is drawn *inside* the padding — its width is subtracted from
|
|
78
|
+
// each side — so total inset (border + padding) equals the padding token
|
|
79
|
+
// rather than exceeding it by the border width.
|
|
78
80
|
withBorder: {
|
|
81
|
+
borderWidth: borderVars['--border-width'],
|
|
82
|
+
borderStyle: 'solid',
|
|
79
83
|
borderColor: colorVars['--color-border-emphasized'],
|
|
84
|
+
paddingInlineStart: `calc(var(--container-padding-inline-start) - ${borderVars['--border-width']})`,
|
|
85
|
+
paddingInlineEnd: `calc(var(--container-padding-inline-end) - ${borderVars['--border-width']})`,
|
|
86
|
+
paddingBlockStart: `calc(var(--container-padding-block-start) - ${borderVars['--border-width']})`,
|
|
87
|
+
paddingBlockEnd: `calc(var(--container-padding-block-end) - ${borderVars['--border-width']})`,
|
|
80
88
|
},
|
|
81
89
|
// Fixed-height cards scroll content; overflow: auto also clips to border-radius
|
|
82
90
|
scrollable: {
|
|
@@ -266,7 +274,6 @@ export function Card({
|
|
|
266
274
|
stylex.props(
|
|
267
275
|
styles.card,
|
|
268
276
|
variantStyles[variant],
|
|
269
|
-
variant === 'default' && styles.withBorder,
|
|
270
277
|
hasFixedHeight && styles.scrollable,
|
|
271
278
|
dynamicStyles.sizing(
|
|
272
279
|
width ?? null,
|
|
@@ -296,6 +303,9 @@ export function Card({
|
|
|
296
303
|
!useThemeDefault &&
|
|
297
304
|
effectivePadding !== 4 &&
|
|
298
305
|
containerPaddingBlockEndVarStyles[effectivePadding],
|
|
306
|
+
// Applied after the container padding so the border-inset calc wins;
|
|
307
|
+
// it reads the --container-padding-* vars set above.
|
|
308
|
+
variant === 'default' && styles.withBorder,
|
|
299
309
|
xstyle,
|
|
300
310
|
),
|
|
301
311
|
className,
|
|
@@ -20,15 +20,15 @@ export const docs = {
|
|
|
20
20
|
],
|
|
21
21
|
anatomy: [
|
|
22
22
|
{name: 'Scroll container', required: true, description: 'The horizontal overflow area that holds all items.'},
|
|
23
|
-
{name: 'Items', required: true, description: 'The children rendered in a row.
|
|
23
|
+
{name: 'Items', required: true, description: 'The children rendered in a row inside the scroll container. With hasSnap, each item snaps to the start edge.'},
|
|
24
24
|
{name: 'Fade edges', required: false, description: 'Gradient fades on the left and right edges that indicate more content is available. Enabled by default, disable with hasEdgeFade={false}.'},
|
|
25
|
-
{name: 'Navigation buttons', required: false, description: 'Prev/next buttons that appear
|
|
25
|
+
{name: 'Navigation buttons', required: false, description: 'Prev/next buttons that appear when the content can scroll in that direction. Enabled by default, disable with hasButtons={false}.'},
|
|
26
26
|
],
|
|
27
27
|
},
|
|
28
28
|
props: [
|
|
29
29
|
{name: 'children', type: 'ReactNode', description: 'Carousel items rendered in a horizontal scroll container.', required: true},
|
|
30
30
|
{name: 'gap', type: "0 | 0.5 | 1 | 1.5 | 2 | 3 | 4", description: 'Gap between items using the spacing token scale.', default: '1'},
|
|
31
|
-
{name: 'hasButtons', type: 'boolean', description: 'Show prev/next navigation buttons
|
|
31
|
+
{name: 'hasButtons', type: 'boolean', description: 'Show prev/next navigation buttons when content is scrollable.', default: 'true'},
|
|
32
32
|
{name: 'hasEdgeFade', type: 'boolean', description: 'Show a gradient edge-fade mask when content overflows, signalling that more items exist off-screen.', default: 'true'},
|
|
33
33
|
{name: 'hasSnap', type: 'boolean', description: 'Enable scroll-snap so each child snaps to the start edge.', default: 'false'},
|
|
34
34
|
{name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: 'Inline padding inside the scroll container, with matching scroll-padding so snap points align to the content edge.'},
|
|
@@ -59,20 +59,20 @@ export const docs = {
|
|
|
59
59
|
export const docsZh = {
|
|
60
60
|
usage: {
|
|
61
61
|
description:
|
|
62
|
-
'Carousel
|
|
62
|
+
'Carousel 在项目超出可用宽度时将一行项目水平滚动。适用于卡片网格、图片画廊、产品列表,或任何希望无需占据整页即可浏览的项目集合。',
|
|
63
63
|
bestPractices: [
|
|
64
|
-
{guidance: true, description: '
|
|
65
|
-
{guidance: true, description: '
|
|
66
|
-
{guidance: true, description: '
|
|
67
|
-
{guidance: false, description: '
|
|
68
|
-
{guidance: false, description: '
|
|
69
|
-
{guidance: false, description: '
|
|
64
|
+
{guidance: true, description: '当每个项目应精确对齐到起始边缘时启用滚动吸附,例如画廊或产品列表。'},
|
|
65
|
+
{guidance: true, description: '始终提供描述轮播内容的 aria-label,例如"精选产品"或"团队成员"。'},
|
|
66
|
+
{guidance: true, description: '使用一致的间距和项目宽度,让轮播看起来是有意为之,而不是内容意外溢出。'},
|
|
67
|
+
{guidance: false, description: '将每位用户都必须看到的内容放入轮播。并非所有人都会水平滚动,关键内容应放在首屏。'},
|
|
68
|
+
{guidance: false, description: '自动轮播项目。让用户按自己的节奏滚动。'},
|
|
69
|
+
{guidance: false, description: '嵌套轮播。轮播中嵌套轮播会造成困惑并破坏键盘导航。'},
|
|
70
70
|
],
|
|
71
71
|
},
|
|
72
72
|
propDescriptions: {
|
|
73
73
|
children: '在水平滚动容器中渲染的轮播项目。',
|
|
74
74
|
gap: '使用间距令牌比例的项目间距。',
|
|
75
|
-
hasButtons: '
|
|
75
|
+
hasButtons: '内容可滚动时显示上一个/下一个导航按钮。',
|
|
76
76
|
hasEdgeFade: '内容溢出时显示渐变边缘遮罩,提示屏幕外还有更多项目。',
|
|
77
77
|
hasSnap: '启用滚动吸附,使每个子元素吸附到起始边缘。',
|
|
78
78
|
padding: '滚动容器内的内联内边距,并设置匹配的 scroll-padding,使吸附点与内容边缘对齐。',
|
|
@@ -98,7 +98,7 @@ export const docsDense = {
|
|
|
98
98
|
propDescriptions: {
|
|
99
99
|
children: 'carousel items in horizontal scroll',
|
|
100
100
|
gap: 'item spacing via spacing token scale',
|
|
101
|
-
hasButtons: 'prev/next buttons
|
|
101
|
+
hasButtons: 'prev/next buttons when content is scrollable',
|
|
102
102
|
hasEdgeFade: 'gradient edge-fade mask on overflow',
|
|
103
103
|
hasSnap: 'scroll-snap; children snap to start edge',
|
|
104
104
|
padding: 'inline padding; scroll-padding keeps snap points on content edge',
|
|
@@ -38,6 +38,19 @@ describe('Carousel', () => {
|
|
|
38
38
|
expect(region).toHaveAttribute('aria-roledescription', 'carousel');
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
it('makes the scroll container keyboard-focusable', () => {
|
|
42
|
+
render(
|
|
43
|
+
<Carousel aria-label="Photos">
|
|
44
|
+
<div>Item</div>
|
|
45
|
+
</Carousel>,
|
|
46
|
+
);
|
|
47
|
+
// The inner scroll container overflows, so it must be reachable by
|
|
48
|
+
// keyboard (axe: scrollable-region-focusable).
|
|
49
|
+
const region = screen.getByRole('region', {name: 'Photos'});
|
|
50
|
+
const scroller = region.firstElementChild;
|
|
51
|
+
expect(scroller).toHaveAttribute('tabindex', '0');
|
|
52
|
+
});
|
|
53
|
+
|
|
41
54
|
it('applies data-testid', () => {
|
|
42
55
|
render(
|
|
43
56
|
<Carousel data-testid="my-carousel">
|
|
@@ -318,6 +318,8 @@ export function Carousel({
|
|
|
318
318
|
: null
|
|
319
319
|
: null;
|
|
320
320
|
|
|
321
|
+
// Self-authored position styles (positioning: 'custom' below): a cover
|
|
322
|
+
// centered on the anchor, sized to it — direction-neutral by construction.
|
|
321
323
|
const coverStyle: React.CSSProperties = {
|
|
322
324
|
positionArea: 'center',
|
|
323
325
|
width: 'anchor-size(width)',
|
|
@@ -340,6 +342,7 @@ export function Carousel({
|
|
|
340
342
|
{...htmlProps}>
|
|
341
343
|
<div
|
|
342
344
|
ref={composedRef}
|
|
345
|
+
tabIndex={0}
|
|
343
346
|
{...stylex.props(
|
|
344
347
|
styles.scroller,
|
|
345
348
|
gapStyles[gap],
|
|
@@ -397,8 +400,7 @@ export function Carousel({
|
|
|
397
400
|
</div>
|
|
398
401
|
</>,
|
|
399
402
|
{
|
|
400
|
-
|
|
401
|
-
alignment: 'center',
|
|
403
|
+
positioning: 'custom',
|
|
402
404
|
style: coverStyle,
|
|
403
405
|
xstyle: styles.buttonOverlay,
|
|
404
406
|
},
|
package/src/Chat/Chat.doc.mjs
CHANGED
|
@@ -17,7 +17,7 @@ export const docs = {
|
|
|
17
17
|
{className: 'astryx-chat-composer', visualProps: ['density']},
|
|
18
18
|
{className: 'astryx-chat-composer-input'},
|
|
19
19
|
{className: 'astryx-chat-composer-drawer', visualProps: ['collapsed']},
|
|
20
|
-
{className: 'astryx-chat-message', visualProps: ['sender']},
|
|
20
|
+
{className: 'astryx-chat-message', visualProps: ['sender', 'density']},
|
|
21
21
|
{
|
|
22
22
|
className: 'astryx-chat-message-bubble',
|
|
23
23
|
visualProps: ['sender', 'variant', 'density'],
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {describe, it, expect, vi, afterEach} from 'vitest';
|
|
4
4
|
import {render, screen, fireEvent} from '@testing-library/react';
|
|
5
|
+
import {ChatComposer} from './ChatComposer';
|
|
5
6
|
import {ChatComposerInput} from './ChatComposerInput';
|
|
6
7
|
import type {
|
|
7
8
|
ChatComposerTrigger,
|
|
@@ -129,6 +130,29 @@ describe('ChatComposerInput', () => {
|
|
|
129
130
|
fireEvent.keyDown(textbox, {key: 'Enter'});
|
|
130
131
|
expect(onSubmit).not.toHaveBeenCalled();
|
|
131
132
|
});
|
|
133
|
+
|
|
134
|
+
it('keeps parent submit flow when child onChange observes input changes', () => {
|
|
135
|
+
const onSubmit = vi.fn();
|
|
136
|
+
const onInputChange = vi.fn();
|
|
137
|
+
render(
|
|
138
|
+
<ChatComposer
|
|
139
|
+
onSubmit={onSubmit}
|
|
140
|
+
input={<ChatComposerInput onChange={onInputChange} />}
|
|
141
|
+
/>,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const textbox = screen.getByRole('textbox');
|
|
145
|
+
textbox.textContent = 'hello world';
|
|
146
|
+
fireEvent.input(textbox);
|
|
147
|
+
|
|
148
|
+
expect(onInputChange).toHaveBeenLastCalledWith('hello world');
|
|
149
|
+
|
|
150
|
+
fireEvent.keyDown(textbox, {key: 'Enter'});
|
|
151
|
+
|
|
152
|
+
expect(onSubmit).toHaveBeenCalledWith('hello world');
|
|
153
|
+
expect(onInputChange).toHaveBeenLastCalledWith('');
|
|
154
|
+
expect(textbox.textContent).toBe('');
|
|
155
|
+
});
|
|
132
156
|
});
|
|
133
157
|
|
|
134
158
|
// Controlled-value sync used to overwrite `textContent` on every
|
|
@@ -345,7 +369,9 @@ describe('ChatComposerInput', () => {
|
|
|
345
369
|
},
|
|
346
370
|
});
|
|
347
371
|
|
|
348
|
-
expect(
|
|
372
|
+
expect(
|
|
373
|
+
textbox.querySelector('[data-astryx-token]'),
|
|
374
|
+
).not.toBeInTheDocument();
|
|
349
375
|
expect(textbox.textContent).toBe(long);
|
|
350
376
|
});
|
|
351
377
|
});
|
|
@@ -43,10 +43,7 @@ import {
|
|
|
43
43
|
} from '../theme/tokens.stylex';
|
|
44
44
|
import {mergeProps} from '../utils';
|
|
45
45
|
import {useTriggerMenu} from './useTriggerMenu';
|
|
46
|
-
import {
|
|
47
|
-
useChatComposerTokens,
|
|
48
|
-
isCustomToken,
|
|
49
|
-
} from './useChatComposerTokens';
|
|
46
|
+
import {useChatComposerTokens, isCustomToken} from './useChatComposerTokens';
|
|
50
47
|
import {ensureCaretInside, insertTextAtCursor} from './chatComposerSelection';
|
|
51
48
|
import {ChatPastedTextToken} from './ChatPastedTextToken';
|
|
52
49
|
import {
|
|
@@ -283,12 +280,13 @@ function serialize(node: Node): string {
|
|
|
283
280
|
|
|
284
281
|
export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
285
282
|
const composerCtx = useChatComposerContext();
|
|
283
|
+
const hasControlledValueProp = props.value !== undefined;
|
|
286
284
|
|
|
287
285
|
const {
|
|
288
286
|
ref,
|
|
289
287
|
handleRef,
|
|
290
288
|
value: controlledValue = composerCtx?.value,
|
|
291
|
-
onChange
|
|
289
|
+
onChange: onChangeProp,
|
|
292
290
|
placeholder = composerCtx?.placeholder ?? 'Type a message\u2026',
|
|
293
291
|
maxRows = 8,
|
|
294
292
|
triggers,
|
|
@@ -306,6 +304,21 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
|
306
304
|
...rest
|
|
307
305
|
} = props;
|
|
308
306
|
|
|
307
|
+
const composerOnChange = composerCtx?.onChange;
|
|
308
|
+
const onChange = useCallback(
|
|
309
|
+
(nextValue: string) => {
|
|
310
|
+
if (hasControlledValueProp) {
|
|
311
|
+
onChangeProp?.(nextValue);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
composerOnChange?.(nextValue);
|
|
315
|
+
if (onChangeProp !== composerOnChange) {
|
|
316
|
+
onChangeProp?.(nextValue);
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
[composerOnChange, hasControlledValueProp, onChangeProp],
|
|
320
|
+
);
|
|
321
|
+
|
|
309
322
|
const editableRef = useRef<HTMLDivElement>(null);
|
|
310
323
|
const selfRef = useRef<ChatComposerInputHandle>(null);
|
|
311
324
|
const [isEmpty, setIsEmpty] = useState(true);
|
|
@@ -679,11 +692,7 @@ ChatComposerInput.displayName = 'ChatComposerInput';
|
|
|
679
692
|
// Token element helper (for custom rendering in stories/consumers)
|
|
680
693
|
// =============================================================================
|
|
681
694
|
|
|
682
|
-
export function ChatComposerTokenElement({
|
|
683
|
-
token,
|
|
684
|
-
}: {
|
|
685
|
-
token: ChatComposerToken;
|
|
686
|
-
}) {
|
|
695
|
+
export function ChatComposerTokenElement({token}: {token: ChatComposerToken}) {
|
|
687
696
|
return (
|
|
688
697
|
<span
|
|
689
698
|
data-astryx-token=""
|
|
@@ -693,11 +702,7 @@ export function ChatComposerTokenElement({
|
|
|
693
702
|
{isCustomToken(token) ? (
|
|
694
703
|
token.render()
|
|
695
704
|
) : (
|
|
696
|
-
<Badge
|
|
697
|
-
label={token.label}
|
|
698
|
-
variant={token.variant}
|
|
699
|
-
icon={token.icon}
|
|
700
|
-
/>
|
|
705
|
+
<Badge label={token.label} variant={token.variant} icon={token.icon} />
|
|
701
706
|
)}
|
|
702
707
|
</span>
|
|
703
708
|
);
|