@astryxdesign/core 0.1.8 → 0.1.9
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 +100 -0
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +6 -2
- package/dist/AppShell/AppShellMobileContext.d.ts +8 -0
- package/dist/AppShell/AppShellMobileContext.d.ts.map +1 -1
- package/dist/Avatar/Avatar.d.ts +18 -2
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +63 -7
- package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +208 -6
- package/dist/Breadcrumbs/index.d.ts +5 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +9 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +31 -2
- package/dist/ButtonGroup/ButtonGroup.d.ts +9 -1
- package/dist/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/ButtonGroup/ButtonGroup.js +30 -1
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +30 -2
- package/dist/Calendar/dayCellUtils.js +1 -1
- package/dist/Card/Card.d.ts +8 -2
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +28 -2
- package/dist/Carousel/Carousel.d.ts +4 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +24 -4
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +46 -7
- package/dist/Chat/ChatComposerDrawer.d.ts +2 -0
- package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
- package/dist/Chat/ChatComposerDrawer.js +11 -1
- package/dist/Chat/ChatComposerInput.d.ts +20 -3
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +35 -3
- package/dist/Chat/ChatContext.d.ts +33 -0
- package/dist/Chat/ChatContext.d.ts.map +1 -1
- package/dist/Chat/ChatContext.js +16 -2
- package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
- package/dist/Chat/ChatDictationButton.js +1 -1
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.js +4 -4
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.js +7 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +18 -9
- package/dist/Chat/index.d.ts +2 -1
- package/dist/Chat/index.d.ts.map +1 -1
- package/dist/Chat/index.js +1 -1
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +11 -1
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +8 -1
- package/dist/CommandPalette/CommandPalette.d.ts +1 -1
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +3 -1
- package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
- package/dist/CommandPalette/CommandPaletteInput.d.ts +7 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +6 -1
- package/dist/DateInput/DateInput.d.ts +47 -1
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +26 -2
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +10 -1
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +57 -6
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Divider/Divider.js +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +1 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +2 -3
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +42 -15
- package/dist/FieldStatus/FieldStatus.d.ts +8 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +22 -4
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +10 -2
- package/dist/HoverCard/HoverCard.d.ts +9 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +2 -0
- package/dist/HoverCard/useHoverCard.d.ts +8 -0
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -2
- package/dist/Icon/Icon.d.ts +7 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Layer/useLayer.d.ts +6 -0
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +2 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +6 -1
- package/dist/MobileNav/MobileNavToggle.d.ts.map +1 -1
- package/dist/MobileNav/MobileNavToggle.js +4 -0
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +39 -12
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/Outline/Outline.d.ts +0 -1
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +0 -1
- package/dist/OverflowList/OverflowList.d.ts +20 -3
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +29 -4
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +3 -2
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +3 -9
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.d.ts +9 -2
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +16 -13
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +4 -2
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +19 -2
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +3 -2
- 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/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/index.d.ts +3 -0
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/index.js +3 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +60 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -0
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +145 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts +13 -0
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +4 -1
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeData.js +87 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
- package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/Thumbnail/Thumbnail.d.ts +26 -5
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +97 -54
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
- package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -4
- package/dist/Timestamp/Timestamp.d.ts +3 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +8 -6
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +2 -5
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +16 -4
- package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
- package/dist/TopNav/TopNavHeading.js +18 -8
- package/dist/TopNav/TopNavMegaMenu.js +10 -4
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TopNav/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeList.d.ts +12 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +2 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +10 -4
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +27 -7
- package/dist/TreeList/TreeListTypes.d.ts +25 -1
- package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
- package/dist/TreeList/index.d.ts +2 -2
- package/dist/TreeList/index.d.ts.map +1 -1
- package/dist/astryx.css +28 -18
- package/dist/astryx.umd.js +51 -51
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.d.ts.map +1 -1
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.d.ts +47 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -0
- package/dist/hooks/computeOverflow.js +213 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +2 -1
- package/dist/hooks/useDevWarning.d.ts +18 -0
- package/dist/hooks/useDevWarning.d.ts.map +1 -0
- package/dist/hooks/useDevWarning.js +49 -0
- package/dist/hooks/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +36 -25
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +51 -0
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
- package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
- package/dist/utils/devWarning.d.ts +42 -0
- package/dist/utils/devWarning.d.ts.map +1 -0
- package/dist/utils/devWarning.js +88 -0
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +3 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +53 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +24 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +18 -0
- package/package.json +1 -1
- package/src/AppShell/AppShell.tsx +6 -0
- package/src/AppShell/AppShellMobileContext.tsx +8 -0
- package/src/AppShell/useAppShellMobile.doc.mjs +8 -0
- package/src/Avatar/Avatar.doc.mjs +15 -3
- package/src/Avatar/Avatar.test.tsx +156 -1
- package/src/Avatar/Avatar.tsx +96 -4
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +178 -21
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +47 -3
- package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +284 -2
- package/src/Breadcrumbs/index.ts +27 -0
- package/src/Button/Button.doc.mjs +9 -0
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +25 -1
- package/src/ButtonGroup/ButtonGroup.doc.mjs +3 -0
- package/src/ButtonGroup/ButtonGroup.test.tsx +37 -0
- package/src/ButtonGroup/ButtonGroup.tsx +32 -0
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +193 -0
- package/src/Calendar/Calendar.tsx +38 -16
- package/src/Calendar/dayCellUtils.test.ts +5 -0
- package/src/Calendar/dayCellUtils.ts +1 -1
- package/src/Card/Card.doc.mjs +9 -0
- package/src/Card/Card.test.tsx +21 -3
- package/src/Card/Card.tsx +35 -2
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Carousel/Carousel.test.tsx +53 -0
- package/src/Carousel/Carousel.tsx +34 -4
- package/src/Chat/ChatComposer.doc.mjs +12 -3
- package/src/Chat/ChatComposer.test.tsx +115 -0
- package/src/Chat/ChatComposer.tsx +73 -9
- package/src/Chat/ChatComposerDrawer.test.tsx +61 -0
- package/src/Chat/ChatComposerDrawer.tsx +11 -1
- package/src/Chat/ChatComposerInput.doc.mjs +7 -0
- package/src/Chat/ChatComposerInput.test.tsx +103 -0
- package/src/Chat/ChatComposerInput.tsx +49 -3
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +4 -1
- package/src/Chat/ChatLayout.tsx +3 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +7 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +11 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +25 -4
- package/src/Chat/index.ts +5 -1
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/Chat/useTriggerMenu.tsx +3 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +81 -3
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +41 -5
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +13 -3
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +9 -1
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.tsx +3 -1
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
- package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
- package/src/CommandPalette/CommandPaletteInput.doc.mjs +26 -9
- package/src/CommandPalette/CommandPaletteInput.test.tsx +34 -0
- package/src/CommandPalette/CommandPaletteInput.tsx +11 -0
- package/src/ContextMenu/ContextMenu.test.tsx +193 -0
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.test.tsx +108 -0
- package/src/DateInput/DateInput.tsx +68 -3
- package/src/DateInput/index.ts +1 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
- package/src/DateTimeInput/DateTimeInput.tsx +14 -2
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +89 -5
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/Divider/Divider.tsx +2 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +6 -5
- package/src/Field/FieldLabel.tsx +8 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +78 -40
- package/src/FieldStatus/FieldStatus.tsx +22 -4
- package/src/FileInput/FileInput.test.tsx +52 -3
- package/src/FileInput/FileInput.tsx +13 -2
- package/src/HoverCard/HoverCard.doc.mjs +13 -0
- package/src/HoverCard/HoverCard.test.tsx +21 -2
- package/src/HoverCard/HoverCard.tsx +11 -0
- package/src/HoverCard/useHoverCard.doc.mjs +2 -0
- package/src/HoverCard/useHoverCard.tsx +24 -2
- package/src/Icon/Icon.doc.mjs +3 -2
- package/src/Icon/Icon.tsx +7 -2
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/Layer/useLayer.tsx +8 -0
- package/src/List/List.test.tsx +9 -8
- package/src/MobileNav/MobileNav.tsx +12 -1
- package/src/MobileNav/MobileNavToggle.test.tsx +116 -0
- package/src/MobileNav/MobileNavToggle.tsx +9 -1
- package/src/MultiSelector/MultiSelector.doc.mjs +4 -2
- package/src/MultiSelector/MultiSelector.test.tsx +172 -3
- package/src/MultiSelector/MultiSelector.tsx +55 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NumberInput/NumberInput.test.tsx +11 -7
- package/src/NumberInput/NumberInput.tsx +1 -2
- package/src/Outline/Outline.tsx +0 -1
- package/src/OverflowList/OverflowList.doc.mjs +39 -6
- package/src/OverflowList/OverflowList.test.tsx +111 -0
- package/src/OverflowList/OverflowList.tsx +48 -8
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
- package/src/PowerSearch/PowerSearch.test.tsx +20 -0
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/SelectableCard/SelectableCard.doc.mjs +2 -0
- package/src/SelectableCard/SelectableCard.test.tsx +46 -4
- package/src/SelectableCard/SelectableCard.tsx +29 -16
- package/src/Selector/Selector.test.tsx +69 -0
- package/src/Selector/Selector.tsx +5 -1
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNavCollapseButton.tsx +6 -1
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +5 -1
- package/src/Slider/Slider.test.tsx +75 -2
- package/src/Slider/Slider.tsx +21 -5
- package/src/Switch/Switch.test.tsx +32 -1
- package/src/Table/BaseTable.tsx +3 -5
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- package/src/Table/plugins/rowStatus/index.ts +7 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +138 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +189 -0
- package/src/Table/plugins/selection/useTableSelection.test.tsx +16 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +19 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +128 -1
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/useBaseTablePlugins.ts +10 -6
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +29 -0
- package/src/Table/useTableTreeState.doc.mjs +2 -2
- package/src/TextArea/TextArea.test.tsx +9 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +141 -41
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.test.tsx +76 -1
- package/src/TimeInput/TimeInput.tsx +19 -6
- package/src/Timestamp/Timestamp.doc.mjs +4 -4
- package/src/Timestamp/Timestamp.test.tsx +32 -0
- package/src/Timestamp/Timestamp.tsx +28 -8
- package/src/Toast/useToast.tsx +7 -8
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +15 -1
- package/src/Tokenizer/Tokenizer.test.tsx +183 -2
- package/src/Tokenizer/Tokenizer.tsx +16 -4
- package/src/TopNav/TopNav.test.tsx +125 -1
- package/src/TopNav/TopNavHeading.tsx +24 -8
- package/src/TopNav/TopNavMegaMenu.test.tsx +149 -1
- package/src/TopNav/TopNavMegaMenu.tsx +10 -4
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TopNav/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.doc.mjs +22 -0
- package/src/TreeList/TreeList.test.tsx +232 -0
- package/src/TreeList/TreeList.tsx +18 -2
- package/src/TreeList/TreeListBranches.tsx +16 -2
- package/src/TreeList/TreeListItem.tsx +51 -11
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/authoring/doc.ts +1 -3
- package/src/docs-types.ts +5 -0
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/resolve.ts +9 -21
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/generateThemeRules.test.ts +65 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +1 -1
- package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
- package/src/utils/devWarning.test.ts +56 -0
- package/src/utils/devWarning.ts +102 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/plainDate.test.ts +22 -0
- package/src/utils/plainDate.ts +61 -0
- package/src/utils/types.ts +14 -0
package/src/Chat/ChatContext.tsx
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @file ChatContext.tsx
|
|
7
7
|
* @input Uses React createContext
|
|
8
|
-
* @output Exports
|
|
9
|
-
*
|
|
8
|
+
* @output Exports Chat message/list/composer/layout contexts. The composer
|
|
9
|
+
* context (value + input-control registration) is public composition API,
|
|
10
|
+
* re-exported from Chat/index.ts for custom inputs.
|
|
11
|
+
* @position Shared contexts; consumed by ChatMessage, ChatComposer,
|
|
12
|
+
* ChatComposerInput, ChatSendButton, and custom inputs.
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
|
-
import {createContext, use} from 'react';
|
|
15
|
+
import {createContext, use, type RefObject} from 'react';
|
|
13
16
|
|
|
14
17
|
export type ChatMessageSender = 'user' | 'assistant' | 'system';
|
|
15
18
|
export type ChatDensity = 'compact' | 'balanced' | 'spacious';
|
|
@@ -19,8 +22,9 @@ export interface ChatMessageContextValue {
|
|
|
19
22
|
density: ChatDensity;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
export const ChatMessageContext =
|
|
23
|
-
|
|
25
|
+
export const ChatMessageContext = createContext<ChatMessageContextValue | null>(
|
|
26
|
+
null,
|
|
27
|
+
);
|
|
24
28
|
ChatMessageContext.displayName = 'ChatMessageContext';
|
|
25
29
|
|
|
26
30
|
export function useChatMessageContext(): ChatMessageContextValue | null {
|
|
@@ -31,9 +35,7 @@ export interface ChatListContextValue {
|
|
|
31
35
|
density: ChatDensity;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
export const ChatListContext = createContext<ChatListContextValue | null>(
|
|
35
|
-
null,
|
|
36
|
-
);
|
|
38
|
+
export const ChatListContext = createContext<ChatListContextValue | null>(null);
|
|
37
39
|
ChatListContext.displayName = 'ChatListContext';
|
|
38
40
|
|
|
39
41
|
export function useChatListContext(): ChatListContextValue | null {
|
|
@@ -44,6 +46,21 @@ export function useChatListContext(): ChatListContextValue | null {
|
|
|
44
46
|
// Composer context — shared state between ChatComposer and ChatComposerInput
|
|
45
47
|
// =============================================================================
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Imperative surface the composer shell can invoke on its input slot.
|
|
51
|
+
*
|
|
52
|
+
* The input is one slot inside the composer body — it does not span the whole
|
|
53
|
+
* body — so shell-level interactions like "click empty space to focus the
|
|
54
|
+
* input" must flow shell → input. A custom input registers this control (via
|
|
55
|
+
* `ChatComposerContextValue.inputControlRef`) so the shell can drive it
|
|
56
|
+
* without knowing its DOM shape. Optional methods can be added over time;
|
|
57
|
+
* inputs implement only what they support.
|
|
58
|
+
*/
|
|
59
|
+
export interface ChatComposerInputControl {
|
|
60
|
+
/** Move keyboard focus into the input. */
|
|
61
|
+
focus: () => void;
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
export interface ChatComposerContextValue {
|
|
48
65
|
value: string;
|
|
49
66
|
onChange: (value: string) => void;
|
|
@@ -53,6 +70,15 @@ export interface ChatComposerContextValue {
|
|
|
53
70
|
isStopShown: boolean;
|
|
54
71
|
canSend: boolean;
|
|
55
72
|
onStop?: () => void;
|
|
73
|
+
/**
|
|
74
|
+
* Mutable handle the input slot populates with its {@link
|
|
75
|
+
* ChatComposerInputControl}. The shell reads `.current` to drive the input
|
|
76
|
+
* (e.g. focus on body click). A custom input assigns
|
|
77
|
+
* `inputControlRef.current = { focus }` on mount and clears it on unmount.
|
|
78
|
+
* When unset, the shell falls back to focusing a `contenteditable`/`textarea`
|
|
79
|
+
* it finds in the body.
|
|
80
|
+
*/
|
|
81
|
+
inputControlRef?: RefObject<ChatComposerInputControl | null>;
|
|
56
82
|
}
|
|
57
83
|
|
|
58
84
|
export const ChatComposerContext =
|
|
@@ -74,8 +100,9 @@ export interface ChatLayoutContextValue {
|
|
|
74
100
|
contentRef: (el: HTMLElement | null) => void;
|
|
75
101
|
}
|
|
76
102
|
|
|
77
|
-
export const ChatLayoutContext =
|
|
78
|
-
|
|
103
|
+
export const ChatLayoutContext = createContext<ChatLayoutContextValue | null>(
|
|
104
|
+
null,
|
|
105
|
+
);
|
|
79
106
|
ChatLayoutContext.displayName = 'ChatLayoutContext';
|
|
80
107
|
|
|
81
108
|
export function useChatLayoutContext(): ChatLayoutContextValue | null {
|
|
@@ -66,7 +66,10 @@ const styles = stylex.create({
|
|
|
66
66
|
borderRadius: radiusVars['--radius-full'],
|
|
67
67
|
transformOrigin: 'center',
|
|
68
68
|
transitionProperty: 'transform, background-color',
|
|
69
|
-
transitionDuration:
|
|
69
|
+
transitionDuration: {
|
|
70
|
+
default: '0.06s',
|
|
71
|
+
'@media (prefers-reduced-motion: reduce)': '0s',
|
|
72
|
+
},
|
|
70
73
|
transitionTimingFunction: 'ease-out',
|
|
71
74
|
},
|
|
72
75
|
});
|
package/src/Chat/ChatLayout.tsx
CHANGED
|
@@ -276,7 +276,9 @@ export function ChatLayout({
|
|
|
276
276
|
const defaultScrollButton = (
|
|
277
277
|
<ChatLayoutScrollButton
|
|
278
278
|
isVisible={scroll.isScrolledUp || newMsgs.hasNewMessages}
|
|
279
|
-
label={
|
|
279
|
+
label={
|
|
280
|
+
newMsgs.hasNewMessages ? t('@astryx.chatLayout.newMessages') : undefined
|
|
281
|
+
}
|
|
280
282
|
onClick={() => {
|
|
281
283
|
newMsgs.dismiss();
|
|
282
284
|
scroll.scrollToBottom();
|
|
@@ -69,7 +69,10 @@ const styles = stylex.create({
|
|
|
69
69
|
height: '32px',
|
|
70
70
|
transitionProperty: 'opacity, transform, max-width',
|
|
71
71
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
72
|
-
transitionDuration:
|
|
72
|
+
transitionDuration: {
|
|
73
|
+
default: durationVars['--duration-fast-max'],
|
|
74
|
+
'@media (prefers-reduced-motion: reduce)': '0s',
|
|
75
|
+
},
|
|
73
76
|
},
|
|
74
77
|
hidden: {
|
|
75
78
|
opacity: 0,
|
|
@@ -135,7 +138,9 @@ export function ChatLayoutScrollButton({
|
|
|
135
138
|
)}>
|
|
136
139
|
<Button
|
|
137
140
|
label={label ?? t('@astryx.chatLayoutScrollButton.scrollToBottom')}
|
|
138
|
-
aria-label={
|
|
141
|
+
aria-label={
|
|
142
|
+
label ?? t('@astryx.chatLayoutScrollButton.scrollToBottom')
|
|
143
|
+
}
|
|
139
144
|
icon={<Icon icon="chevronDown" size="md" />}
|
|
140
145
|
variant="ghost"
|
|
141
146
|
size="md"
|
|
@@ -122,8 +122,7 @@ export function ChatMessageMetadata({
|
|
|
122
122
|
const sender = msgContext?.sender ?? 'assistant';
|
|
123
123
|
|
|
124
124
|
const statusConfig = status != null ? STATUS_CONFIG[status] : null;
|
|
125
|
-
const statusLabel =
|
|
126
|
-
statusConfig != null ? t(statusConfig.i18nKey) : '';
|
|
125
|
+
const statusLabel = statusConfig != null ? t(statusConfig.i18nKey) : '';
|
|
127
126
|
|
|
128
127
|
const hasContent =
|
|
129
128
|
timestamp != null || footer != null || statusConfig != null;
|
|
@@ -88,7 +88,10 @@ export function ChatSendButton(props: ChatSendButtonProps): ReactNode {
|
|
|
88
88
|
stopIcon,
|
|
89
89
|
size = 'md',
|
|
90
90
|
xstyle,
|
|
91
|
+
className,
|
|
92
|
+
style,
|
|
91
93
|
ref,
|
|
94
|
+
...rest
|
|
92
95
|
} = props;
|
|
93
96
|
|
|
94
97
|
const handleSend = onSend ?? (() => context?.onSubmit(''));
|
|
@@ -96,7 +99,11 @@ export function ChatSendButton(props: ChatSendButtonProps): ReactNode {
|
|
|
96
99
|
return (
|
|
97
100
|
<Button
|
|
98
101
|
ref={ref}
|
|
99
|
-
label={
|
|
102
|
+
label={
|
|
103
|
+
isStopShown
|
|
104
|
+
? t('@astryx.chatSendButton.stop')
|
|
105
|
+
: t('@astryx.chatSendButton.send')
|
|
106
|
+
}
|
|
100
107
|
variant={isStopShown ? 'secondary' : 'primary'}
|
|
101
108
|
size={size}
|
|
102
109
|
icon={
|
|
@@ -107,7 +114,10 @@ export function ChatSendButton(props: ChatSendButtonProps): ReactNode {
|
|
|
107
114
|
isIconOnly
|
|
108
115
|
isDisabled={!isStopShown && isDisabled}
|
|
109
116
|
onClick={isStopShown ? onStop : handleSend}
|
|
117
|
+
{...rest}
|
|
110
118
|
{...themeProps('chat-send-button')}
|
|
119
|
+
className={className}
|
|
120
|
+
style={style}
|
|
111
121
|
xstyle={[styles.root, xstyle]}
|
|
112
122
|
/>
|
|
113
123
|
);
|
|
@@ -133,6 +133,70 @@ describe('ChatToolCalls', () => {
|
|
|
133
133
|
expect(panel).toHaveTextContent('file contents here');
|
|
134
134
|
});
|
|
135
135
|
|
|
136
|
+
it('exposes the error message as text without requiring hover', () => {
|
|
137
|
+
render(
|
|
138
|
+
<ChatToolCalls
|
|
139
|
+
calls={[
|
|
140
|
+
{
|
|
141
|
+
name: 'bash',
|
|
142
|
+
status: 'error',
|
|
143
|
+
errorMessage: 'Command exited with code 1',
|
|
144
|
+
},
|
|
145
|
+
]}
|
|
146
|
+
/>,
|
|
147
|
+
);
|
|
148
|
+
// The message must exist as real (screen-reader-visible) text content,
|
|
149
|
+
// not only inside a hover-only title attribute.
|
|
150
|
+
expect(screen.getByText(/Command exited with code 1/)).toBeInTheDocument();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('includes the error message in the accessible name of an expandable error row', () => {
|
|
154
|
+
render(
|
|
155
|
+
<ChatToolCalls
|
|
156
|
+
calls={[
|
|
157
|
+
{
|
|
158
|
+
name: 'bash',
|
|
159
|
+
status: 'error',
|
|
160
|
+
errorMessage: 'Command exited with code 1',
|
|
161
|
+
resultDetail: <div>stderr output</div>,
|
|
162
|
+
},
|
|
163
|
+
]}
|
|
164
|
+
/>,
|
|
165
|
+
);
|
|
166
|
+
expect(
|
|
167
|
+
screen.getByRole('button', {name: /Command exited with code 1/}),
|
|
168
|
+
).toBeInTheDocument();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('keeps the hover tooltip on the error status icon', () => {
|
|
172
|
+
const {container} = render(
|
|
173
|
+
<ChatToolCalls
|
|
174
|
+
calls={[
|
|
175
|
+
{
|
|
176
|
+
name: 'bash',
|
|
177
|
+
status: 'error',
|
|
178
|
+
errorMessage: 'Command exited with code 1',
|
|
179
|
+
},
|
|
180
|
+
]}
|
|
181
|
+
/>,
|
|
182
|
+
);
|
|
183
|
+
expect(
|
|
184
|
+
container.querySelector('[title="Command exited with code 1"]'),
|
|
185
|
+
).not.toBeNull();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('renders no error text for non-error calls', () => {
|
|
189
|
+
render(
|
|
190
|
+
<ChatToolCalls
|
|
191
|
+
calls={[
|
|
192
|
+
{name: 'bash', status: 'complete', errorMessage: 'stale message'},
|
|
193
|
+
]}
|
|
194
|
+
/>,
|
|
195
|
+
);
|
|
196
|
+
expect(screen.queryByText(/stale message/)).not.toBeInTheDocument();
|
|
197
|
+
expect(screen.queryByText(/Error:/)).not.toBeInTheDocument();
|
|
198
|
+
});
|
|
199
|
+
|
|
136
200
|
it('points the group header aria-controls at the content region', () => {
|
|
137
201
|
render(
|
|
138
202
|
<ChatToolCalls
|
|
@@ -35,6 +35,7 @@ import {getKey, mergeProps} from '../utils';
|
|
|
35
35
|
import {Badge} from '../Badge';
|
|
36
36
|
import {Icon, type IconName} from '../Icon';
|
|
37
37
|
import {Spinner} from '../Spinner';
|
|
38
|
+
import {VisuallyHidden} from '../VisuallyHidden';
|
|
38
39
|
import {themeProps} from '../utils/themeProps';
|
|
39
40
|
|
|
40
41
|
// =============================================================================
|
|
@@ -60,7 +61,11 @@ export interface ChatToolCallItem {
|
|
|
60
61
|
deletions?: number;
|
|
61
62
|
/** Additional info rendered after the label. Free-form ReactNode. */
|
|
62
63
|
stats?: ReactNode;
|
|
63
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Error message when status is 'error'. Rendered as visually hidden text in
|
|
66
|
+
* the row (so screen readers and keyboard users perceive it) and echoed in a
|
|
67
|
+
* hover tooltip on the status icon.
|
|
68
|
+
*/
|
|
64
69
|
errorMessage?: string;
|
|
65
70
|
/** Unique key for React list rendering. Derived from stable metadata if omitted. */
|
|
66
71
|
key?: string;
|
|
@@ -128,7 +133,10 @@ const styles = stylex.create({
|
|
|
128
133
|
width: '14px',
|
|
129
134
|
height: '14px',
|
|
130
135
|
color: colorVars['--color-text-disabled'],
|
|
131
|
-
transition:
|
|
136
|
+
transition: {
|
|
137
|
+
default: `transform ${durationVars['--duration-fast']} ${easeVars['--ease-standard']}`,
|
|
138
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
139
|
+
},
|
|
132
140
|
},
|
|
133
141
|
chevronExpanded: {
|
|
134
142
|
transform: 'rotate(180deg)',
|
|
@@ -136,7 +144,10 @@ const styles = stylex.create({
|
|
|
136
144
|
groupContent: {
|
|
137
145
|
display: 'grid',
|
|
138
146
|
gridTemplateRows: '0fr',
|
|
139
|
-
transition:
|
|
147
|
+
transition: {
|
|
148
|
+
default: `grid-template-rows ${durationVars['--duration-medium']} ${easeVars['--ease-standard']}`,
|
|
149
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
150
|
+
},
|
|
140
151
|
},
|
|
141
152
|
groupContentExpanded: {
|
|
142
153
|
gridTemplateRows: '1fr',
|
|
@@ -261,7 +272,10 @@ const styles = stylex.create({
|
|
|
261
272
|
width: '14px',
|
|
262
273
|
height: '14px',
|
|
263
274
|
color: colorVars['--color-text-disabled'],
|
|
264
|
-
transition:
|
|
275
|
+
transition: {
|
|
276
|
+
default: `transform ${durationVars['--duration-fast']} ${easeVars['--ease-standard']}`,
|
|
277
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
278
|
+
},
|
|
265
279
|
marginInlineStart: 'auto',
|
|
266
280
|
},
|
|
267
281
|
callDetailContent: {
|
|
@@ -395,6 +409,13 @@ function CallRow({call}: {call: ChatToolCallItem}) {
|
|
|
395
409
|
</span>
|
|
396
410
|
</>
|
|
397
411
|
)}
|
|
412
|
+
{status === 'error' && call.errorMessage != null && (
|
|
413
|
+
// The title attribute above is hover-only; expose the error detail
|
|
414
|
+
// as real text so it reaches screen readers, keyboard, and touch
|
|
415
|
+
// users. Rendering it inside the row also folds it into the
|
|
416
|
+
// accessible name of expandable (role="button") rows.
|
|
417
|
+
<VisuallyHidden>{`Error: ${call.errorMessage}`}</VisuallyHidden>
|
|
418
|
+
)}
|
|
398
419
|
</span>
|
|
399
420
|
<span {...stylex.props(styles.callName)}>{call.name}</span>
|
|
400
421
|
{call.node != null && (
|
package/src/Chat/index.ts
CHANGED
|
@@ -81,7 +81,11 @@ export type {
|
|
|
81
81
|
TokenPortal,
|
|
82
82
|
} from './useChatComposerTokens';
|
|
83
83
|
export type {ChatMessageSender, ChatDensity} from './ChatContext';
|
|
84
|
-
export {useChatLayoutContext} from './ChatContext';
|
|
84
|
+
export {useChatLayoutContext, useChatComposerContext} from './ChatContext';
|
|
85
|
+
export type {
|
|
86
|
+
ChatComposerContextValue,
|
|
87
|
+
ChatComposerInputControl,
|
|
88
|
+
} from './ChatContext';
|
|
85
89
|
|
|
86
90
|
export {ChatToolCalls} from './ChatToolCalls';
|
|
87
91
|
export type {
|
|
@@ -45,6 +45,23 @@ afterEach(() => {
|
|
|
45
45
|
vi.unstubAllGlobals();
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
// The global test setup polyfills matchMedia with a never-matching stub;
|
|
49
|
+
// this override makes only the reduced-motion query match, mirroring the
|
|
50
|
+
// pattern in useStreamingText.test.ts. Undone by afterEach's
|
|
51
|
+
// unstubAllGlobals.
|
|
52
|
+
function stubReducedMotion() {
|
|
53
|
+
vi.stubGlobal('matchMedia', (query: string) => ({
|
|
54
|
+
matches: query.includes('prefers-reduced-motion'),
|
|
55
|
+
media: query,
|
|
56
|
+
onchange: null,
|
|
57
|
+
addListener: () => {},
|
|
58
|
+
removeListener: () => {},
|
|
59
|
+
addEventListener: () => {},
|
|
60
|
+
removeEventListener: () => {},
|
|
61
|
+
dispatchEvent: () => false,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
|
|
48
65
|
function setGeometry(
|
|
49
66
|
el: HTMLElement,
|
|
50
67
|
{scrollHeight, clientHeight}: {scrollHeight: number; clientHeight: number},
|
|
@@ -166,3 +183,35 @@ describe("useChatStreamScroll — scrollToBottom({behavior: 'instant'})", () =>
|
|
|
166
183
|
expect(rafQueue.length).toBeGreaterThan(0);
|
|
167
184
|
});
|
|
168
185
|
});
|
|
186
|
+
|
|
187
|
+
describe('useChatStreamScroll — prefers-reduced-motion', () => {
|
|
188
|
+
it('streaming growth jumps synchronously instead of springing', () => {
|
|
189
|
+
stubReducedMotion();
|
|
190
|
+
const {api, el} = renderHook();
|
|
191
|
+
setGeometry(el, {scrollHeight: 1000, clientHeight: 400});
|
|
192
|
+
flushRaf(); // consume the mount jump
|
|
193
|
+
expect(el.scrollTop).toBe(600);
|
|
194
|
+
|
|
195
|
+
// Post-first-fill growth would normally take the spring path; under
|
|
196
|
+
// reduced motion it must land in the same synchronous step.
|
|
197
|
+
setGeometry(el, {scrollHeight: 1400, clientHeight: 400});
|
|
198
|
+
rafQueue = [];
|
|
199
|
+
act(() => api.current!.scrollIfLocked());
|
|
200
|
+
expect(el.scrollTop).toBe(1000);
|
|
201
|
+
expect(rafQueue).toHaveLength(0);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('default scrollToBottom falls back to an instant jump', () => {
|
|
205
|
+
stubReducedMotion();
|
|
206
|
+
const {api, el} = renderHook();
|
|
207
|
+
setGeometry(el, {scrollHeight: 1000, clientHeight: 400});
|
|
208
|
+
flushRaf();
|
|
209
|
+
el.scrollTop = 100; // user scrolled up
|
|
210
|
+
|
|
211
|
+
rafQueue = [];
|
|
212
|
+
act(() => api.current!.scrollToBottom());
|
|
213
|
+
expect(el.scrollTop).toBe(600);
|
|
214
|
+
expect(rafQueue).toHaveLength(0);
|
|
215
|
+
expect(api.current!.isLocked).toBe(true);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file useChatStreamScroll.ts
|
|
7
|
-
* @input Uses React refs, state, callbacks
|
|
7
|
+
* @input Uses React refs, state, callbacks, useMediaQuery
|
|
8
8
|
* @output Exports useChatStreamScroll hook for AI chat scroll behavior
|
|
9
9
|
* @position Utility hook — used by ChatLayout, also usable standalone
|
|
10
10
|
*
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* - The first fill positions instantly (whether content is present at
|
|
16
16
|
* mount or arrives async); only subsequent growth springs
|
|
17
17
|
* - `scrollToBottom({behavior: 'instant'})` jumps in one frame, no animation
|
|
18
|
+
* - Under `prefers-reduced-motion`, every spring path falls back to the
|
|
19
|
+
* same instant jump — following still works, it just doesn't animate
|
|
18
20
|
*
|
|
19
21
|
* Uses scroll direction (lastScrollTop comparison) to detect user
|
|
20
22
|
* intent — works for wheel, touch, scrollbar drag, keyboard, everything.
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
*/
|
|
27
29
|
|
|
28
30
|
import {useCallback, useEffect, useRef, useState} from 'react';
|
|
31
|
+
import {useMediaQuery} from '../hooks/useMediaQuery';
|
|
29
32
|
|
|
30
33
|
// =============================================================================
|
|
31
34
|
// Types
|
|
@@ -37,7 +40,8 @@ export interface ChatScrollToBottomOptions {
|
|
|
37
40
|
* the spring animation. Use for programmatic positioning (opening a
|
|
38
41
|
* conversation, restoring a session) — keep the default `'spring'` for
|
|
39
42
|
* user-initiated scrolls like the scroll-to-bottom button. Mirrors the
|
|
40
|
-
* DOM's `scrollTo({behavior})`.
|
|
43
|
+
* DOM's `scrollTo({behavior})`. When the user prefers reduced motion,
|
|
44
|
+
* `'spring'` also jumps instantly.
|
|
41
45
|
* @default 'spring'
|
|
42
46
|
*/
|
|
43
47
|
behavior?: 'instant' | 'spring';
|
|
@@ -189,14 +193,6 @@ export function useChatStreamScroll({
|
|
|
189
193
|
requestAnimationFrame(animate);
|
|
190
194
|
}, [scrollRef, damping, stiffness, mass]);
|
|
191
195
|
|
|
192
|
-
const startAnimation = useCallback(() => {
|
|
193
|
-
if (!animatingRef.current && lockedRef.current) {
|
|
194
|
-
animatingRef.current = true;
|
|
195
|
-
lastTickRef.current = undefined;
|
|
196
|
-
requestAnimationFrame(animate);
|
|
197
|
-
}
|
|
198
|
-
}, [animate]);
|
|
199
|
-
|
|
200
196
|
// Jump to the bottom in a single frame — cancels any in-flight spring so
|
|
201
197
|
// a later animation tick can't fight the assignment.
|
|
202
198
|
const jumpToBottom = useCallback(() => {
|
|
@@ -211,6 +207,27 @@ export function useChatStreamScroll({
|
|
|
211
207
|
lastScrollTopRef.current = el.scrollTop;
|
|
212
208
|
}, [scrollRef]);
|
|
213
209
|
|
|
210
|
+
const prefersReducedMotion = useMediaQuery(
|
|
211
|
+
'(prefers-reduced-motion: reduce)',
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Every spring entry point (scrollToBottom, lock, scrollIfLocked growth
|
|
215
|
+
// follow) funnels through here, so this one branch covers them all.
|
|
216
|
+
const startAnimation = useCallback(() => {
|
|
217
|
+
if (!lockedRef.current) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (prefersReducedMotion) {
|
|
221
|
+
jumpToBottom();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (!animatingRef.current) {
|
|
225
|
+
animatingRef.current = true;
|
|
226
|
+
lastTickRef.current = undefined;
|
|
227
|
+
requestAnimationFrame(animate);
|
|
228
|
+
}
|
|
229
|
+
}, [animate, jumpToBottom, prefersReducedMotion]);
|
|
230
|
+
|
|
214
231
|
// --- Public API ---
|
|
215
232
|
|
|
216
233
|
const scrollToBottom = useCallback(
|
|
@@ -242,7 +242,7 @@ async function createVolumeAnalyser(
|
|
|
242
242
|
|
|
243
243
|
let _sharedAudioCtx: AudioContext | null = null;
|
|
244
244
|
|
|
245
|
-
|
|
245
|
+
function getDefaultAudioContext(): AudioContext {
|
|
246
246
|
if (!_sharedAudioCtx || _sharedAudioCtx.state === 'closed') {
|
|
247
247
|
_sharedAudioCtx = new AudioContext();
|
|
248
248
|
}
|
|
@@ -699,7 +699,9 @@ export function useTriggerMenu(
|
|
|
699
699
|
<div
|
|
700
700
|
id={listboxId}
|
|
701
701
|
role="listbox"
|
|
702
|
-
aria-label={
|
|
702
|
+
aria-label={
|
|
703
|
+
trigger?.menuLabel ?? t('@astryx.chatTriggerMenu.suggestions')
|
|
704
|
+
}
|
|
703
705
|
{...mergeProps(
|
|
704
706
|
themeProps('trigger-menu'),
|
|
705
707
|
stylex.props(styles.dropdown),
|
|
@@ -9,10 +9,15 @@
|
|
|
9
9
|
* SYNC: When CheckboxInput.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
13
|
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
14
14
|
import userEvent from '@testing-library/user-event';
|
|
15
15
|
import {CheckboxInput} from './CheckboxInput';
|
|
16
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
__resetLiveRegionsForTest();
|
|
20
|
+
});
|
|
16
21
|
|
|
17
22
|
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
18
23
|
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
@@ -333,6 +338,32 @@ describe('CheckboxInput', () => {
|
|
|
333
338
|
);
|
|
334
339
|
});
|
|
335
340
|
|
|
341
|
+
// Regression: the status is conditionally mounted, so it must be announced
|
|
342
|
+
// through the persistent useAnnounce live region — a live region born
|
|
343
|
+
// together with its content is not reliably announced.
|
|
344
|
+
it('announces a status message that appears after mount', async () => {
|
|
345
|
+
const {rerender} = render(
|
|
346
|
+
<CheckboxInput label="Accept terms" value={false} onChange={() => {}} />,
|
|
347
|
+
);
|
|
348
|
+
expect(
|
|
349
|
+
document.querySelector('[data-astryx-live-region="assertive"]'),
|
|
350
|
+
).toBeNull();
|
|
351
|
+
|
|
352
|
+
rerender(
|
|
353
|
+
<CheckboxInput
|
|
354
|
+
label="Accept terms"
|
|
355
|
+
value={false}
|
|
356
|
+
onChange={() => {}}
|
|
357
|
+
status={{type: 'error', message: 'Required field'}}
|
|
358
|
+
/>,
|
|
359
|
+
);
|
|
360
|
+
await waitFor(() => {
|
|
361
|
+
expect(
|
|
362
|
+
document.querySelector('[data-astryx-live-region="assertive"]'),
|
|
363
|
+
).toHaveTextContent('Required field');
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
336
367
|
describe('disabledMessage', () => {
|
|
337
368
|
const h = {hidden: true} as const;
|
|
338
369
|
|
|
@@ -166,7 +166,7 @@ const styles = stylex.create({
|
|
|
166
166
|
indeterminateMark: {
|
|
167
167
|
display: 'none',
|
|
168
168
|
backgroundColor: colorVars['--color-on-accent'],
|
|
169
|
-
borderRadius:
|
|
169
|
+
borderRadius: radiusVars['--radius-full'],
|
|
170
170
|
},
|
|
171
171
|
indeterminateMarkVisible: {
|
|
172
172
|
display: 'block',
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* SYNC: When CheckboxList.tsx or CheckboxListItem.tsx changes, update tests to match new behavior
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
12
|
+
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
13
|
import {
|
|
14
14
|
render,
|
|
15
15
|
screen,
|
|
@@ -20,8 +20,16 @@ import {
|
|
|
20
20
|
import userEvent from '@testing-library/user-event';
|
|
21
21
|
import {CheckboxList} from './CheckboxList';
|
|
22
22
|
import {CheckboxListItem} from './CheckboxListItem';
|
|
23
|
+
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
23
24
|
import {List} from '../List/List';
|
|
24
25
|
|
|
26
|
+
// FieldStatus announces status messages through the persistent useAnnounce
|
|
27
|
+
// singletons; remove them between tests so role/aria-live queries in this
|
|
28
|
+
// file never match a leftover region.
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
__resetLiveRegionsForTest();
|
|
31
|
+
});
|
|
32
|
+
|
|
25
33
|
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
26
34
|
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
27
35
|
beforeEach(() => {
|
|
@@ -437,6 +445,71 @@ describe('CheckboxListItem standalone mode', () => {
|
|
|
437
445
|
});
|
|
438
446
|
});
|
|
439
447
|
|
|
448
|
+
describe('CheckboxListItem accessible name', () => {
|
|
449
|
+
it('names the checkbox from a string label', () => {
|
|
450
|
+
render(
|
|
451
|
+
<CheckboxList label="Preferences" value={[]} onChange={() => {}}>
|
|
452
|
+
<CheckboxListItem label="Option A" value="a" />
|
|
453
|
+
</CheckboxList>,
|
|
454
|
+
);
|
|
455
|
+
expect(
|
|
456
|
+
screen.getByRole('checkbox', {name: 'Option A'}),
|
|
457
|
+
).toBeInTheDocument();
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
it('names the checkbox from aria-label when the label is a ReactNode', () => {
|
|
461
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
462
|
+
render(
|
|
463
|
+
<CheckboxList label="Plans" value={[]} onChange={() => {}}>
|
|
464
|
+
<CheckboxListItem
|
|
465
|
+
label={
|
|
466
|
+
<span>
|
|
467
|
+
Pro plan <em>(recommended)</em>
|
|
468
|
+
</span>
|
|
469
|
+
}
|
|
470
|
+
aria-label="Pro plan"
|
|
471
|
+
value="pro"
|
|
472
|
+
/>
|
|
473
|
+
</CheckboxList>,
|
|
474
|
+
);
|
|
475
|
+
expect(
|
|
476
|
+
screen.getByRole('checkbox', {name: 'Pro plan'}),
|
|
477
|
+
).toBeInTheDocument();
|
|
478
|
+
// A named checkbox needs no dev guidance.
|
|
479
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
480
|
+
warnSpy.mockRestore();
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('warns once when a ReactNode label has no aria-label', () => {
|
|
484
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
485
|
+
const richLabel = (
|
|
486
|
+
<span>
|
|
487
|
+
Pro plan <em>(recommended)</em>
|
|
488
|
+
</span>
|
|
489
|
+
);
|
|
490
|
+
const {rerender} = render(
|
|
491
|
+
<CheckboxList label="Plans" value={[]} onChange={() => {}}>
|
|
492
|
+
<CheckboxListItem label={richLabel} value="pro" />
|
|
493
|
+
</CheckboxList>,
|
|
494
|
+
);
|
|
495
|
+
// Falls back to the generic name, and tells the developer how to fix it.
|
|
496
|
+
expect(
|
|
497
|
+
screen.getByRole('checkbox', {name: 'Checkbox'}),
|
|
498
|
+
).toBeInTheDocument();
|
|
499
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
500
|
+
expect(String(warnSpy.mock.calls[0]?.[0])).toContain('aria-label');
|
|
501
|
+
|
|
502
|
+
// Warn once per item instance — re-renders don't repeat it.
|
|
503
|
+
rerender(
|
|
504
|
+
<CheckboxList label="Plans" value={['pro']} onChange={() => {}}>
|
|
505
|
+
<CheckboxListItem label={richLabel} value="pro" />
|
|
506
|
+
</CheckboxList>,
|
|
507
|
+
);
|
|
508
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
509
|
+
warnSpy.mockRestore();
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
|
|
440
513
|
describe('CheckboxListItem ARIA props', () => {
|
|
441
514
|
it('conveys checked state via the inner checkbox, not aria-checked on the listitem', () => {
|
|
442
515
|
render(
|
|
@@ -567,7 +640,7 @@ describe('CheckboxListItem ARIA props', () => {
|
|
|
567
640
|
expect(changeAction).toHaveBeenCalledWith(['a']);
|
|
568
641
|
});
|
|
569
642
|
|
|
570
|
-
it('forwards arbitrary aria attributes to the list item
|
|
643
|
+
it('forwards arbitrary aria attributes to the list item, but aria-label names the checkbox', () => {
|
|
571
644
|
render(
|
|
572
645
|
<List>
|
|
573
646
|
<CheckboxListItem
|
|
@@ -578,8 +651,13 @@ describe('CheckboxListItem ARIA props', () => {
|
|
|
578
651
|
</List>,
|
|
579
652
|
);
|
|
580
653
|
const item = screen.getByRole('listitem');
|
|
654
|
+
// Arbitrary aria-* still forward to the row...
|
|
581
655
|
expect(item).toHaveAttribute('aria-describedby', 'help-text');
|
|
582
|
-
|
|
656
|
+
// ...but aria-label names the checkbox control, not the row.
|
|
657
|
+
expect(item).not.toHaveAttribute('aria-label');
|
|
658
|
+
expect(
|
|
659
|
+
screen.getByRole('checkbox', {name: 'custom label'}),
|
|
660
|
+
).toBeInTheDocument();
|
|
583
661
|
});
|
|
584
662
|
|
|
585
663
|
describe('disabledMessage', () => {
|