@astryxdesign/core 0.1.7 → 0.1.8-canary.0c4d8d7
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 +65 -0
- package/README.md +30 -19
- 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 +10 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -8
- package/dist/Avatar/AvatarSizeContext.d.ts +1 -1
- package/dist/Avatar/AvatarSizeContext.js +1 -1
- package/dist/Avatar/AvatarStatusDot.d.ts +2 -2
- package/dist/Avatar/AvatarStatusDot.js +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts +2 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +2 -2
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +16 -14
- 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/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/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 +6 -2
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +55 -5
- package/dist/Chat/ChatComposer.d.ts +8 -0
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +31 -6
- 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 +19 -3
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.d.ts +1 -1
- package/dist/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/Chat/ChatMessage.js +1 -1
- package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
- package/dist/Chat/ChatSendButton.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.d.ts +5 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -3
- package/dist/Chat/useTriggerMenu.d.ts.map +1 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +10 -4
- package/dist/ClickableCard/ClickableCard.d.ts +9 -2
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +3 -0
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +8 -1
- package/dist/Collapsible/Collapsible.d.ts +11 -1
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +36 -4
- 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/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -3
- package/dist/ContextMenu/index.d.ts +3 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +7 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +10 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +8 -4
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +88 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +169 -0
- package/dist/DropdownMenu/DropdownMenuContext.d.ts +17 -1
- package/dist/DropdownMenu/DropdownMenuContext.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuContext.js +18 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +68 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +69 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +178 -0
- package/dist/DropdownMenu/index.d.ts +5 -1
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +10 -1
- package/dist/DropdownMenu/menuItemRoles.d.ts +13 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemRoles.js +15 -0
- 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 +43 -13
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +62 -27
- 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 +68 -3
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +128 -26
- package/dist/Outline/useScrollSpy.d.ts +27 -7
- package/dist/Outline/useScrollSpy.d.ts.map +1 -1
- package/dist/Outline/useScrollSpy.js +202 -70
- 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/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 +14 -11
- 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 +15 -1
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -0
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/Table.d.ts +1 -1
- package/dist/Table/Table.js +1 -1
- package/dist/Table/index.d.ts +4 -0
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +2 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +24 -2
- 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 +12 -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/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +18 -7
- package/dist/Table/plugins/tree/index.d.ts +5 -0
- package/dist/Table/plugins/tree/index.d.ts.map +1 -0
- package/dist/Table/plugins/tree/index.js +4 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts +38 -0
- package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeData.js +358 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts +51 -0
- package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -0
- package/dist/Table/plugins/tree/useTableTreeState.js +175 -0
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +6 -3
- package/dist/Thumbnail/Thumbnail.d.ts +8 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +46 -8
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +15 -4
- 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/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +8 -1
- 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/TopNavMenu.d.ts +2 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +68 -6
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +5 -14
- package/dist/astryx.css +51 -16
- package/dist/astryx.umd.js +56 -56
- package/dist/astryx.umd.js.map +4 -4
- package/dist/authoring/doc.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/useOverflow.d.ts +19 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +37 -25
- package/dist/theme/Theme.js +1 -1
- package/dist/theme/defineTheme.d.ts +1 -1
- package/dist/theme/defineTheme.js +1 -1
- 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 +0 -3
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/docs.mjs +32 -461
- package/locales/en.json +212 -172
- package/locales/fr-FR.json +10 -0
- package/locales/pseudo.json +30 -0
- package/package.json +3 -1
- package/scripts/postinstall.mjs +93 -0
- 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 +6 -6
- package/src/Avatar/Avatar.tsx +16 -11
- package/src/Avatar/AvatarSizeContext.ts +1 -1
- package/src/Avatar/AvatarStatusDot.tsx +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
- package/src/AvatarGroup/AvatarGroup.test.tsx +17 -3
- package/src/AvatarGroup/AvatarGroup.tsx +3 -3
- package/src/AvatarGroup/AvatarGroupOverflow.doc.mjs +4 -4
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +21 -5
- 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/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/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 +149 -1
- package/src/Carousel/Carousel.tsx +62 -5
- package/src/Chat/Chat.doc.mjs +1 -1
- package/src/Chat/ChatComposer.doc.mjs +9 -0
- package/src/Chat/ChatComposer.test.tsx +35 -0
- package/src/Chat/ChatComposer.tsx +58 -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 +87 -0
- package/src/Chat/ChatComposerInput.tsx +35 -3
- package/src/Chat/ChatLayout.tsx +3 -1
- package/src/Chat/ChatLayoutScrollButton.tsx +3 -1
- package/src/Chat/ChatMessage.tsx +4 -2
- package/src/Chat/ChatMessageMetadata.tsx +1 -2
- package/src/Chat/ChatSendButton.tsx +5 -1
- package/src/Chat/ChatToolCalls.test.tsx +64 -0
- package/src/Chat/ChatToolCalls.tsx +13 -1
- package/src/Chat/useTriggerMenu.tsx +3 -1
- package/src/CheckboxInput/CheckboxInput.doc.mjs +1 -1
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxList/CheckboxList.test.tsx +9 -1
- package/src/Citation/Citation.test.tsx +51 -0
- package/src/Citation/Citation.tsx +8 -2
- package/src/ClickableCard/ClickableCard.doc.mjs +2 -0
- package/src/ClickableCard/ClickableCard.test.tsx +34 -0
- package/src/ClickableCard/ClickableCard.tsx +11 -1
- package/src/CodeBlock/CodeBlock.test.tsx +56 -0
- package/src/CodeBlock/CodeBlock.tsx +9 -1
- package/src/Collapsible/Collapsible.doc.mjs +7 -0
- package/src/Collapsible/Collapsible.test.tsx +80 -0
- package/src/Collapsible/Collapsible.tsx +58 -5
- 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 +75 -1
- package/src/ContextMenu/ContextMenu.tsx +10 -5
- package/src/ContextMenu/index.ts +15 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +35 -0
- package/src/DateTimeInput/DateTimeInput.tsx +14 -2
- package/src/Dialog/Dialog.tsx +12 -2
- package/src/DropdownMenu/DropdownMenu.doc.mjs +23 -0
- package/src/DropdownMenu/DropdownMenu.tsx +11 -6
- package/src/DropdownMenu/DropdownMenuCheckboxItem.doc.mjs +95 -0
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +236 -0
- package/src/DropdownMenu/DropdownMenuContext.tsx +29 -1
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +7 -1
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +118 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.doc.mjs +80 -0
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +232 -0
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +163 -0
- package/src/DropdownMenu/index.ts +23 -3
- package/src/DropdownMenu/menuItemRoles.ts +22 -0
- package/src/Field/Field.doc.mjs +1 -1
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/FieldLabel.doc.mjs +1 -1
- 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 +12 -0
- package/src/Icon/Icon.test.tsx +142 -0
- package/src/Icon/Icon.tsx +98 -30
- package/src/IconButton/IconButton.doc.mjs +8 -0
- package/src/IconButton/IconButton.test.tsx +15 -18
- package/src/Item/Item.doc.mjs +1 -1
- package/src/Layer/useLayer.tsx +8 -0
- 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 +162 -1
- package/src/MultiSelector/MultiSelector.tsx +55 -12
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NumberInput/NumberInput.doc.mjs +2 -2
- package/src/NumberInput/NumberInput.test.tsx +11 -7
- package/src/NumberInput/NumberInput.tsx +1 -2
- package/src/Outline/Outline.doc.mjs +123 -3
- package/src/Outline/Outline.test.tsx +735 -0
- package/src/Outline/Outline.tsx +183 -33
- package/src/Outline/useScrollSpy.ts +248 -72
- 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/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 +27 -14
- package/src/Selector/Selector.test.tsx +69 -0
- package/src/Selector/Selector.tsx +5 -1
- package/src/Selector/SelectorOption.doc.mjs +1 -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.doc.mjs +2 -2
- package/src/SideNav/SideNavItem.tsx +5 -1
- package/src/Slider/Slider.test.tsx +62 -2
- package/src/Slider/Slider.tsx +15 -1
- package/src/Switch/Switch.doc.mjs +1 -1
- package/src/Switch/Switch.test.tsx +32 -1
- package/src/TabList/Tab.tsx +5 -1
- package/src/TabList/TabList.doc.mjs +3 -3
- package/src/TabList/TabList.test.tsx +66 -0
- package/src/TabList/TabList.tsx +8 -0
- package/src/TabList/TabMenu.tsx +4 -1
- package/src/Table/Table.doc.mjs +2 -0
- package/src/Table/Table.tsx +1 -1
- package/src/Table/index.ts +12 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +6 -2
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +90 -1
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +37 -5
- 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 +18 -1
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +95 -9
- package/src/Table/plugins/sortable/useTableSortable.tsx +23 -7
- package/src/Table/plugins/tree/index.ts +12 -0
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +163 -0
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +594 -0
- package/src/Table/plugins/tree/useTableTreeData.tsx +495 -0
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +636 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +253 -0
- package/src/Table/useBaseTablePlugins.ts +6 -2
- package/src/Table/useTableRowStatus.doc.mjs +30 -0
- package/src/Table/useTableSelection.doc.mjs +65 -14
- package/src/Table/useTableTreeData.doc.mjs +75 -0
- package/src/Table/useTableTreeState.doc.mjs +98 -0
- package/src/TextArea/TextArea.doc.mjs +1 -1
- package/src/TextArea/TextArea.test.tsx +9 -1
- package/src/TextInput/TextInput.doc.mjs +1 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +9 -0
- package/src/Thumbnail/Thumbnail.test.tsx +38 -8
- package/src/Thumbnail/Thumbnail.tsx +28 -1
- package/src/TimeInput/TimeInput.test.tsx +76 -1
- package/src/TimeInput/TimeInput.tsx +19 -6
- package/src/Tokenizer/Tokenizer.doc.mjs +1 -1
- package/src/Tokenizer/Tokenizer.test.tsx +137 -2
- package/src/Tokenizer/Tokenizer.tsx +16 -4
- package/src/Toolbar/Toolbar.tsx +10 -3
- package/src/TopNav/TopNav.test.tsx +80 -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/TopNavMenu.test.tsx +118 -4
- package/src/TopNav/TopNavMenu.tsx +83 -5
- package/src/TreeList/TreeList.test.tsx +32 -1
- package/src/TreeList/TreeListItem.tsx +19 -10
- package/src/authoring/doc.ts +1 -3
- package/src/docs-script.test.mjs +18 -13
- package/src/hooks/computeOverflow.test.ts +422 -0
- package/src/hooks/computeOverflow.ts +290 -0
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +77 -33
- package/src/postinstall.test.mjs +71 -0
- package/src/theme/Theme.doc.mjs +4 -4
- package/src/theme/Theme.tsx +1 -1
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/generateThemeRules.test.ts +65 -0
- package/src/theme/generateThemeRules.ts +56 -0
- package/src/theme/hct.ts +0 -4
- package/src/utils/types.ts +14 -0
- package/dist/TreeList/treeListItem.markers.stylex.d.ts +0 -16
- package/dist/TreeList/treeListItem.markers.stylex.d.ts.map +0 -1
- package/dist/TreeList/treeListItem.markers.stylex.js +0 -22
- package/src/TreeList/treeListItem.markers.stylex.ts +0 -20
|
@@ -155,6 +155,93 @@ describe('ChatComposerInput', () => {
|
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
+
describe('Enter submit behavior', () => {
|
|
159
|
+
it('does not submit on Enter while IME composition is in progress', () => {
|
|
160
|
+
const onSubmit = vi.fn();
|
|
161
|
+
render(<ChatComposerInput onSubmit={onSubmit} />);
|
|
162
|
+
const textbox = screen.getByRole('textbox');
|
|
163
|
+
textbox.textContent = 'こんにちは';
|
|
164
|
+
fireEvent.input(textbox);
|
|
165
|
+
// isComposing is surfaced on the native event during IME composition.
|
|
166
|
+
fireEvent.keyDown(textbox, {key: 'Enter', isComposing: true});
|
|
167
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('does not submit on Enter for the legacy keyCode 229 composing signal', () => {
|
|
171
|
+
const onSubmit = vi.fn();
|
|
172
|
+
render(<ChatComposerInput onSubmit={onSubmit} />);
|
|
173
|
+
const textbox = screen.getByRole('textbox');
|
|
174
|
+
textbox.textContent = 'ㅎ';
|
|
175
|
+
fireEvent.input(textbox);
|
|
176
|
+
fireEvent.keyDown(textbox, {key: 'Enter', keyCode: 229});
|
|
177
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('lets onKeyDown suppress the default submit via preventDefault (touch-newline recipe)', () => {
|
|
181
|
+
// The documented "insert a newline instead of sending" pattern: a
|
|
182
|
+
// consumer preventDefaults Enter (e.g. on a coarse pointer).
|
|
183
|
+
const onSubmit = vi.fn();
|
|
184
|
+
const onKeyDown = vi.fn(e => {
|
|
185
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
render(<ChatComposerInput onSubmit={onSubmit} onKeyDown={onKeyDown} />);
|
|
190
|
+
const textbox = screen.getByRole('textbox');
|
|
191
|
+
textbox.textContent = 'hello';
|
|
192
|
+
fireEvent.input(textbox);
|
|
193
|
+
fireEvent.keyDown(textbox, {key: 'Enter'});
|
|
194
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
195
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('lets onKeyDown add behavior (Cmd/Ctrl+Enter submit) without preventDefault', () => {
|
|
199
|
+
// Adding a submit shortcut is just handling the event yourself; the
|
|
200
|
+
// built-in Enter handling still runs for the plain-Enter case.
|
|
201
|
+
const onSubmit = vi.fn();
|
|
202
|
+
const handle = vi.fn();
|
|
203
|
+
const onKeyDown = vi.fn(e => {
|
|
204
|
+
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
|
|
205
|
+
handle();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
render(<ChatComposerInput onSubmit={onSubmit} onKeyDown={onKeyDown} />);
|
|
209
|
+
const textbox = screen.getByRole('textbox');
|
|
210
|
+
textbox.textContent = 'hello';
|
|
211
|
+
fireEvent.input(textbox);
|
|
212
|
+
fireEvent.keyDown(textbox, {key: 'Enter', metaKey: true});
|
|
213
|
+
expect(handle).toHaveBeenCalled();
|
|
214
|
+
// Consumer did not preventDefault, so the built-in submit also fires.
|
|
215
|
+
expect(onSubmit).toHaveBeenCalledWith('hello');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('calls onKeyDown before submit and lets preventDefault take over', () => {
|
|
219
|
+
const onSubmit = vi.fn();
|
|
220
|
+
const onKeyDown = vi.fn(e => {
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
});
|
|
223
|
+
render(<ChatComposerInput onSubmit={onSubmit} onKeyDown={onKeyDown} />);
|
|
224
|
+
const textbox = screen.getByRole('textbox');
|
|
225
|
+
textbox.textContent = 'hello';
|
|
226
|
+
fireEvent.input(textbox);
|
|
227
|
+
fireEvent.keyDown(textbox, {key: 'Enter'});
|
|
228
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
229
|
+
expect(onSubmit).not.toHaveBeenCalled();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('calls onKeyDown but still submits when the consumer does not preventDefault', () => {
|
|
233
|
+
const onSubmit = vi.fn();
|
|
234
|
+
const onKeyDown = vi.fn();
|
|
235
|
+
render(<ChatComposerInput onSubmit={onSubmit} onKeyDown={onKeyDown} />);
|
|
236
|
+
const textbox = screen.getByRole('textbox');
|
|
237
|
+
textbox.textContent = 'hello';
|
|
238
|
+
fireEvent.input(textbox);
|
|
239
|
+
fireEvent.keyDown(textbox, {key: 'Enter'});
|
|
240
|
+
expect(onKeyDown).toHaveBeenCalled();
|
|
241
|
+
expect(onSubmit).toHaveBeenCalledWith('hello');
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
158
245
|
// Controlled-value sync used to overwrite `textContent` on every
|
|
159
246
|
// distinct render, which (a) collapsed the caret to offset 0
|
|
160
247
|
// (visible after a slash-command pick like
|
|
@@ -11,8 +11,10 @@
|
|
|
11
11
|
*
|
|
12
12
|
* ContentEditable-based rich input for the chat composer.
|
|
13
13
|
* Supports trigger menus (@ mentions, / commands) via SearchSource,
|
|
14
|
-
* inline token rendering, serialization, Enter
|
|
15
|
-
*
|
|
14
|
+
* inline token rendering, serialization, Enter-to-submit with
|
|
15
|
+
* IME-composition guarding and an onKeyDown seam for platform-specific
|
|
16
|
+
* key handling, message history, paste/drop file handling, and
|
|
17
|
+
* mobile-safe touch typography.
|
|
16
18
|
*
|
|
17
19
|
*
|
|
18
20
|
* SYNC: When modified, update:
|
|
@@ -188,6 +190,21 @@ export interface ChatComposerInputProps extends Omit<
|
|
|
188
190
|
onFiles?: (files: File[]) => void;
|
|
189
191
|
/** Submit handler (Enter without Shift) */
|
|
190
192
|
onSubmit?: (value: string) => void;
|
|
193
|
+
/**
|
|
194
|
+
* Key-down handler invoked before the built-in Enter/history behavior
|
|
195
|
+
* (but after an open trigger menu consumes the event).
|
|
196
|
+
*
|
|
197
|
+
* This is the seam for platform- or app-specific key handling:
|
|
198
|
+
* - Call `event.preventDefault()` to suppress the default submit (e.g.
|
|
199
|
+
* let Enter insert a newline on a touch keyboard).
|
|
200
|
+
* - Add behavior by acting on the event yourself (e.g. submit on
|
|
201
|
+
* Cmd/Ctrl+Enter) without calling `preventDefault()`, so the default
|
|
202
|
+
* handling still runs for other keys.
|
|
203
|
+
*
|
|
204
|
+
* IME composition is always respected regardless of this handler: Enter
|
|
205
|
+
* never submits while a composition is in progress.
|
|
206
|
+
*/
|
|
207
|
+
onKeyDown?: (event: KeyboardEvent<HTMLDivElement>) => void;
|
|
191
208
|
}
|
|
192
209
|
|
|
193
210
|
// =============================================================================
|
|
@@ -299,6 +316,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
|
299
316
|
pasteAsToken: pasteAsTokenProp,
|
|
300
317
|
onFiles,
|
|
301
318
|
onSubmit = composerCtx?.onSubmit,
|
|
319
|
+
onKeyDown: onKeyDownProp,
|
|
302
320
|
xstyle,
|
|
303
321
|
className,
|
|
304
322
|
style,
|
|
@@ -477,6 +495,13 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
|
477
495
|
return;
|
|
478
496
|
}
|
|
479
497
|
|
|
498
|
+
// Consumer passthrough — runs before built-in Enter/history handling.
|
|
499
|
+
// A consumer can preventDefault() to fully own the keystroke.
|
|
500
|
+
onKeyDownProp?.(e);
|
|
501
|
+
if (e.defaultPrevented) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
480
505
|
// Handle Backspace near tokens — prevent browser from creating
|
|
481
506
|
// stray <br> elements or moving the cursor unexpectedly.
|
|
482
507
|
if (e.key === 'Backspace') {
|
|
@@ -519,6 +544,13 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
|
519
544
|
}
|
|
520
545
|
|
|
521
546
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
547
|
+
// Never submit mid-composition — an IME uses Enter to commit a
|
|
548
|
+
// candidate (e.g. Japanese/Chinese/Korean input), and browsers may
|
|
549
|
+
// also surface the legacy keyCode 229 for composing keystrokes.
|
|
550
|
+
if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
522
554
|
e.preventDefault();
|
|
523
555
|
if (!editableRef.current) {
|
|
524
556
|
return;
|
|
@@ -583,7 +615,7 @@ export function ChatComposerInput(props: ChatComposerInputProps) {
|
|
|
583
615
|
}
|
|
584
616
|
}
|
|
585
617
|
},
|
|
586
|
-
[hasHistory, onSubmit, onChange, emitChange, triggerMenu],
|
|
618
|
+
[hasHistory, onSubmit, onChange, emitChange, triggerMenu, onKeyDownProp],
|
|
587
619
|
);
|
|
588
620
|
|
|
589
621
|
const handlePaste = useCallback(
|
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();
|
|
@@ -135,7 +135,9 @@ export function ChatLayoutScrollButton({
|
|
|
135
135
|
)}>
|
|
136
136
|
<Button
|
|
137
137
|
label={label ?? t('@astryx.chatLayoutScrollButton.scrollToBottom')}
|
|
138
|
-
aria-label={
|
|
138
|
+
aria-label={
|
|
139
|
+
label ?? t('@astryx.chatLayoutScrollButton.scrollToBottom')
|
|
140
|
+
}
|
|
139
141
|
icon={<Icon icon="chevronDown" size="md" />}
|
|
140
142
|
variant="ghost"
|
|
141
143
|
size="md"
|
package/src/Chat/ChatMessage.tsx
CHANGED
|
@@ -150,7 +150,7 @@ const styles = stylex.create({
|
|
|
150
150
|
*
|
|
151
151
|
* @example
|
|
152
152
|
* ```
|
|
153
|
-
* <ChatMessage sender="assistant" name="Navi" avatar={<Avatar name="Navi" size="
|
|
153
|
+
* <ChatMessage sender="assistant" name="Navi" avatar={<Avatar name="Navi" size="md" />}>
|
|
154
154
|
* <ChatMessageBubble>Hello!</ChatMessageBubble>
|
|
155
155
|
* <ChatMessageMetadata timestamp="2:30 PM" />
|
|
156
156
|
* </ChatMessage>
|
|
@@ -222,7 +222,9 @@ export function ChatMessage({
|
|
|
222
222
|
{...rest}
|
|
223
223
|
ref={ref}
|
|
224
224
|
data-testid={testId}
|
|
225
|
-
aria-label={
|
|
225
|
+
aria-label={
|
|
226
|
+
!hasName ? t('@astryx.chatMessage.messageFrom', {sender}) : undefined
|
|
227
|
+
}
|
|
226
228
|
aria-labelledby={hasName ? nameId : undefined}
|
|
227
229
|
{...mergeProps(
|
|
228
230
|
themeProps('chat-message', {sender, density}),
|
|
@@ -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;
|
|
@@ -96,7 +96,11 @@ export function ChatSendButton(props: ChatSendButtonProps): ReactNode {
|
|
|
96
96
|
return (
|
|
97
97
|
<Button
|
|
98
98
|
ref={ref}
|
|
99
|
-
label={
|
|
99
|
+
label={
|
|
100
|
+
isStopShown
|
|
101
|
+
? t('@astryx.chatSendButton.stop')
|
|
102
|
+
: t('@astryx.chatSendButton.send')
|
|
103
|
+
}
|
|
100
104
|
variant={isStopShown ? 'secondary' : 'primary'}
|
|
101
105
|
size={size}
|
|
102
106
|
icon={
|
|
@@ -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;
|
|
@@ -395,6 +400,13 @@ function CallRow({call}: {call: ChatToolCallItem}) {
|
|
|
395
400
|
</span>
|
|
396
401
|
</>
|
|
397
402
|
)}
|
|
403
|
+
{status === 'error' && call.errorMessage != null && (
|
|
404
|
+
// The title attribute above is hover-only; expose the error detail
|
|
405
|
+
// as real text so it reaches screen readers, keyboard, and touch
|
|
406
|
+
// users. Rendering it inside the row also folds it into the
|
|
407
|
+
// accessible name of expandable (role="button") rows.
|
|
408
|
+
<VisuallyHidden>{`Error: ${call.errorMessage}`}</VisuallyHidden>
|
|
409
|
+
)}
|
|
398
410
|
</span>
|
|
399
411
|
<span {...stylex.props(styles.callName)}>{call.name}</span>
|
|
400
412
|
{call.node != null && (
|
|
@@ -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),
|
|
@@ -113,7 +113,7 @@ export const docs = {
|
|
|
113
113
|
{
|
|
114
114
|
name: 'labelIcon',
|
|
115
115
|
type: 'IconType',
|
|
116
|
-
description: 'Icon to display before the label text. See `
|
|
116
|
+
description: 'Icon to display before the label text. See `astryx docs icons` for valid semantic names.',
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
name: 'status',
|
|
@@ -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
|
|
|
@@ -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(() => {
|
|
@@ -20,6 +20,7 @@ const probe = stylex.create({
|
|
|
20
20
|
secondaryText: {color: colorVars['--color-text-secondary']},
|
|
21
21
|
accentText: {color: colorVars['--color-text-accent']},
|
|
22
22
|
badgeBackground: {backgroundColor: colorVars['--color-accent-muted']},
|
|
23
|
+
pointerCursor: {cursor: 'pointer'},
|
|
23
24
|
});
|
|
24
25
|
|
|
25
26
|
function atomicClasses(style: (typeof probe)[keyof typeof probe]): string[] {
|
|
@@ -118,4 +119,54 @@ describe('Citation', () => {
|
|
|
118
119
|
expect(el.classList.contains(cls)).toBe(true);
|
|
119
120
|
}
|
|
120
121
|
});
|
|
122
|
+
|
|
123
|
+
// The interactive (pointer) treatment is keyed on `source.url`: a citation
|
|
124
|
+
// with no url is non-interactive and must keep the default cursor.
|
|
125
|
+
const noUrlSource = {title: 'No link'};
|
|
126
|
+
|
|
127
|
+
it('does not use the pointer cursor without a url in the label variant', () => {
|
|
128
|
+
render(<Citation source={noUrlSource} number={1} data-testid="citation" />);
|
|
129
|
+
const el = screen.getByTestId('citation');
|
|
130
|
+
for (const cls of atomicClasses(probe.pointerCursor)) {
|
|
131
|
+
expect(el.classList.contains(cls)).toBe(false);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('uses the pointer cursor with a url in the label variant', () => {
|
|
136
|
+
render(<Citation source={source} number={1} data-testid="citation" />);
|
|
137
|
+
const el = screen.getByTestId('citation');
|
|
138
|
+
for (const cls of atomicClasses(probe.pointerCursor)) {
|
|
139
|
+
expect(el.classList.contains(cls)).toBe(true);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('does not use the pointer cursor without a url in the number variant', () => {
|
|
144
|
+
render(
|
|
145
|
+
<Citation
|
|
146
|
+
source={noUrlSource}
|
|
147
|
+
number={1}
|
|
148
|
+
variant="number"
|
|
149
|
+
data-testid="citation"
|
|
150
|
+
/>,
|
|
151
|
+
);
|
|
152
|
+
const el = screen.getByTestId('citation');
|
|
153
|
+
for (const cls of atomicClasses(probe.pointerCursor)) {
|
|
154
|
+
expect(el.classList.contains(cls)).toBe(false);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('uses the pointer cursor with a url in the number variant', () => {
|
|
159
|
+
render(
|
|
160
|
+
<Citation
|
|
161
|
+
source={source}
|
|
162
|
+
number={1}
|
|
163
|
+
variant="number"
|
|
164
|
+
data-testid="citation"
|
|
165
|
+
/>,
|
|
166
|
+
);
|
|
167
|
+
const el = screen.getByTestId('citation');
|
|
168
|
+
for (const cls of atomicClasses(probe.pointerCursor)) {
|
|
169
|
+
expect(el.classList.contains(cls)).toBe(true);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
121
172
|
});
|
|
@@ -61,7 +61,6 @@ const styles = stylex.create({
|
|
|
61
61
|
paddingInline: spacingVars['--spacing-2'],
|
|
62
62
|
marginInlineStart: spacingVars['--spacing-0-5'],
|
|
63
63
|
textDecoration: 'none',
|
|
64
|
-
cursor: 'pointer',
|
|
65
64
|
transitionProperty: 'background-color, border-color, color',
|
|
66
65
|
transitionDuration: durationVars['--duration-fast-max'],
|
|
67
66
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
@@ -77,6 +76,9 @@ const styles = stylex.create({
|
|
|
77
76
|
whiteSpace: 'nowrap',
|
|
78
77
|
minWidth: 0,
|
|
79
78
|
},
|
|
79
|
+
labelInteractive: {
|
|
80
|
+
cursor: 'pointer',
|
|
81
|
+
},
|
|
80
82
|
labelHover: {
|
|
81
83
|
backgroundColor: {
|
|
82
84
|
':hover': {
|
|
@@ -108,11 +110,13 @@ const styles = stylex.create({
|
|
|
108
110
|
height: spacingVars['--spacing-5'],
|
|
109
111
|
paddingInline: spacingVars['--spacing-1'],
|
|
110
112
|
textDecoration: 'none',
|
|
111
|
-
cursor: 'pointer',
|
|
112
113
|
transitionProperty: 'background-color',
|
|
113
114
|
transitionDuration: durationVars['--duration-fast-max'],
|
|
114
115
|
transitionTimingFunction: easeVars['--ease-standard'],
|
|
115
116
|
},
|
|
117
|
+
numberInteractive: {
|
|
118
|
+
cursor: 'pointer',
|
|
119
|
+
},
|
|
116
120
|
numberHover: {
|
|
117
121
|
backgroundColor: {
|
|
118
122
|
// Explicit default for the same reason as labelHover's color: a
|
|
@@ -191,6 +195,7 @@ export function Citation({
|
|
|
191
195
|
stylex.props(
|
|
192
196
|
styles.number,
|
|
193
197
|
href != null && styles.numberHover,
|
|
198
|
+
href != null && styles.numberInteractive,
|
|
194
199
|
xstyle,
|
|
195
200
|
),
|
|
196
201
|
className,
|
|
@@ -215,6 +220,7 @@ export function Citation({
|
|
|
215
220
|
styles.label,
|
|
216
221
|
icon != null && styles.labelWithIcon,
|
|
217
222
|
href != null && styles.labelHover,
|
|
223
|
+
href != null && styles.labelInteractive,
|
|
218
224
|
xstyle,
|
|
219
225
|
),
|
|
220
226
|
className,
|
|
@@ -28,6 +28,7 @@ export const docs = {
|
|
|
28
28
|
{name: 'children', type: 'ReactNode', description: 'Card content.'},
|
|
29
29
|
{name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: 'Inner padding.', default: '4'},
|
|
30
30
|
{name: 'variant', type: "'default' | 'transparent' | 'muted' | 'blue' | 'cyan' | 'gray' | 'green' | 'orange' | 'pink' | 'purple' | 'red' | 'teal' | 'yellow'", description: 'Background color variant.', default: "'default'"},
|
|
31
|
+
{name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: 'Resting shadow depth. Often raised to signal the whole card is clickable.', default: "'none'"},
|
|
31
32
|
{name: 'width', type: 'SizeValue', description: 'Card width.'},
|
|
32
33
|
{name: 'height', type: 'SizeValue', description: 'Card height.'},
|
|
33
34
|
{name: 'maxWidth', type: 'SizeValue', description: 'Maximum card width.'},
|
|
@@ -73,6 +74,7 @@ export const docsDense = {
|
|
|
73
74
|
isDisabled: 'disables card',
|
|
74
75
|
padding: 'inner padding',
|
|
75
76
|
variant: 'background color variant',
|
|
77
|
+
elevation: 'resting shadow depth: none|low|med|high; often raised to signal clickability',
|
|
76
78
|
width: 'card width',
|
|
77
79
|
height: 'card height',
|
|
78
80
|
maxWidth: 'max card width',
|
|
@@ -106,4 +106,38 @@ describe('ClickableCard', () => {
|
|
|
106
106
|
const link = screen.getByRole('link', {name: 'Disabled link'});
|
|
107
107
|
expect(link).toHaveAttribute('aria-disabled', 'true');
|
|
108
108
|
});
|
|
109
|
+
|
|
110
|
+
describe('elevation', () => {
|
|
111
|
+
it('forwards a distinct elevation class to the card for each level', () => {
|
|
112
|
+
const classFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
|
|
113
|
+
const {container} = render(
|
|
114
|
+
<ClickableCard label="Card" elevation={elevation}>
|
|
115
|
+
Content
|
|
116
|
+
</ClickableCard>,
|
|
117
|
+
);
|
|
118
|
+
return container.firstElementChild!.className;
|
|
119
|
+
};
|
|
120
|
+
const classes = new Set([
|
|
121
|
+
classFor('none'),
|
|
122
|
+
classFor('low'),
|
|
123
|
+
classFor('med'),
|
|
124
|
+
classFor('high'),
|
|
125
|
+
]);
|
|
126
|
+
expect(classes.size).toBe(4);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('defaults to flat (elevation none)', () => {
|
|
130
|
+
const {container: def} = render(
|
|
131
|
+
<ClickableCard label="Card">Content</ClickableCard>,
|
|
132
|
+
);
|
|
133
|
+
const {container: none} = render(
|
|
134
|
+
<ClickableCard label="Card" elevation="none">
|
|
135
|
+
Content
|
|
136
|
+
</ClickableCard>,
|
|
137
|
+
);
|
|
138
|
+
expect(def.firstElementChild!.className).toBe(
|
|
139
|
+
none.firstElementChild!.className,
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
109
143
|
});
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - /apps/storybook/stories/ClickableCard.stories.tsx (storybook stories)
|
|
15
15
|
* - /packages/cli/templates/blocks/components/Card/ClickableCardShowcase.tsx (showcase block)
|
|
16
16
|
* - /packages/cli/templates/blocks/components/Card/ClickableCardWithNestedButton.tsx (block)
|
|
17
|
+
* - /packages/cli/templates/blocks/components/Card/ClickableCardElevated.tsx (block)
|
|
17
18
|
*
|
|
18
19
|
* Composes Card for all visual styling (radius, padding, variants,
|
|
19
20
|
* container tokens, theming). Adds an interactive wrapper with
|
|
@@ -37,7 +38,7 @@ import {
|
|
|
37
38
|
durationVars,
|
|
38
39
|
easeVars,
|
|
39
40
|
} from '../theme/tokens.stylex';
|
|
40
|
-
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
41
|
+
import type {SizeValue, SpacingStep, Elevation} from '../utils/types';
|
|
41
42
|
import {mergeProps, mergeRefs} from '../utils';
|
|
42
43
|
import {Card} from '../Card/Card';
|
|
43
44
|
import type {CardVariant} from '../Card/Card';
|
|
@@ -197,6 +198,13 @@ export interface ClickableCardProps extends BaseProps {
|
|
|
197
198
|
*/
|
|
198
199
|
variant?: CardVariant;
|
|
199
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Resting elevation — the shadow depth the card sits at. Often raised to
|
|
203
|
+
* signal that the whole card is clickable.
|
|
204
|
+
* @default 'none'
|
|
205
|
+
*/
|
|
206
|
+
elevation?: Elevation;
|
|
207
|
+
|
|
200
208
|
/** Width of the card. */
|
|
201
209
|
width?: SizeValue;
|
|
202
210
|
|
|
@@ -253,6 +261,7 @@ export function ClickableCard({
|
|
|
253
261
|
children,
|
|
254
262
|
padding,
|
|
255
263
|
variant = 'default',
|
|
264
|
+
elevation = 'none',
|
|
256
265
|
width,
|
|
257
266
|
height,
|
|
258
267
|
maxWidth,
|
|
@@ -297,6 +306,7 @@ export function ClickableCard({
|
|
|
297
306
|
maxWidth={maxWidth}
|
|
298
307
|
padding={padding}
|
|
299
308
|
variant={variant}
|
|
309
|
+
elevation={elevation}
|
|
300
310
|
{...mergeProps(themeProps('clickable-card', {variant}), {
|
|
301
311
|
className: classNameProp,
|
|
302
312
|
style,
|