@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
|
@@ -16,7 +16,10 @@ import {getButton} from '../__tests__/fastRoleQueries';
|
|
|
16
16
|
import * as stylex from '@stylexjs/stylex';
|
|
17
17
|
import {Calendar} from './Calendar';
|
|
18
18
|
import type {CalendarHandle} from './Calendar';
|
|
19
|
+
import type {ISODateString} from './Calendar';
|
|
19
20
|
import {calendarStyles} from './styles';
|
|
21
|
+
import {defineTheme} from '../theme/defineTheme';
|
|
22
|
+
import {generateThemeCSSFlat} from '../theme/generateThemeRules';
|
|
20
23
|
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
21
24
|
|
|
22
25
|
afterEach(() => {
|
|
@@ -881,4 +884,194 @@ describe('Calendar', () => {
|
|
|
881
884
|
expect(screen.getByText('February 2026')).toBeInTheDocument();
|
|
882
885
|
});
|
|
883
886
|
});
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
// ─── Day-cell marker theming (#4286) ─────────────────────────
|
|
890
|
+
describe('day-cell marker theme state', () => {
|
|
891
|
+
// Tests use the real "today" (as the existing aria-current tests do) since
|
|
892
|
+
// Calendar derives it internally. Helpers pin the exact ISO strings.
|
|
893
|
+
function todayISO(): ISODateString {
|
|
894
|
+
const n = new Date();
|
|
895
|
+
return `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}` as ISODateString;
|
|
896
|
+
}
|
|
897
|
+
function isoOffsetFromToday(deltaDays: number): ISODateString {
|
|
898
|
+
const n = new Date();
|
|
899
|
+
n.setDate(n.getDate() + deltaDays);
|
|
900
|
+
return `${n.getFullYear()}-${String(n.getMonth() + 1).padStart(2, '0')}-${String(n.getDate()).padStart(2, '0')}` as ISODateString;
|
|
901
|
+
}
|
|
902
|
+
function todayCell(): HTMLElement {
|
|
903
|
+
const el = document.querySelector<HTMLElement>(
|
|
904
|
+
`button[data-date="${todayISO()}"]`,
|
|
905
|
+
);
|
|
906
|
+
expect(el).not.toBeNull();
|
|
907
|
+
return el as HTMLElement;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
it('reflects marker="today-only" for a plain today cell (no selection)', () => {
|
|
911
|
+
render(<Calendar />);
|
|
912
|
+
const cell = todayCell();
|
|
913
|
+
expect(cell).toHaveAttribute('data-marker', 'today-only');
|
|
914
|
+
expect(cell).toHaveAttribute('data-today', 'today');
|
|
915
|
+
expect(cell).not.toHaveAttribute('data-selected');
|
|
916
|
+
expect(cell).not.toHaveAttribute('data-in-range');
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
it('reflects marker="today-in-range" when today is strictly inside a range', () => {
|
|
920
|
+
render(
|
|
921
|
+
<Calendar
|
|
922
|
+
mode="range"
|
|
923
|
+
value={{start: isoOffsetFromToday(-2), end: isoOffsetFromToday(2)}}
|
|
924
|
+
/>,
|
|
925
|
+
);
|
|
926
|
+
const cell = todayCell();
|
|
927
|
+
// Today is inside the range but not an endpoint: the today-in-range ring
|
|
928
|
+
// is shown, so `marker` reflects that compound state precisely.
|
|
929
|
+
expect(cell).toHaveAttribute('data-marker', 'today-in-range');
|
|
930
|
+
expect(cell).toHaveAttribute('data-in-range', 'in-range');
|
|
931
|
+
expect(cell).not.toHaveAttribute('data-selected');
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
it('shows no marker state when today is the single-selected date', () => {
|
|
935
|
+
render(<Calendar mode="single" value={todayISO()} />);
|
|
936
|
+
const cell = todayCell();
|
|
937
|
+
// A single-mode selected cell shows no ring by default — `marker` is
|
|
938
|
+
// absent, while `selected` (which owns the selected treatment) is present.
|
|
939
|
+
expect(cell).not.toHaveAttribute('data-marker');
|
|
940
|
+
expect(cell).toHaveAttribute('data-selected', 'selected');
|
|
941
|
+
expect(cell).toHaveAttribute('data-today', 'today');
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
it('preserves the today-in-range ring on a today range endpoint', () => {
|
|
945
|
+
render(
|
|
946
|
+
<Calendar
|
|
947
|
+
mode="range"
|
|
948
|
+
value={{start: todayISO(), end: isoOffsetFromToday(3)}}
|
|
949
|
+
/>,
|
|
950
|
+
);
|
|
951
|
+
const cell = todayCell();
|
|
952
|
+
// A range endpoint is NOT `isSelected` (that flag is single-mode only),
|
|
953
|
+
// so by default the today-in-range ring IS drawn on a today endpoint
|
|
954
|
+
// alongside the endpoint styling. `marker` mirrors that exactly — this
|
|
955
|
+
// asserts the default rendering is preserved, byte-for-byte.
|
|
956
|
+
expect(cell).toHaveAttribute('data-marker', 'today-in-range');
|
|
957
|
+
expect(cell).toHaveAttribute('data-in-range', 'in-range');
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
it('omits the marker state for non-today cells', () => {
|
|
961
|
+
render(<Calendar />);
|
|
962
|
+
const other = document.querySelector(
|
|
963
|
+
`button[data-date="${isoOffsetFromToday(1)}"]`,
|
|
964
|
+
);
|
|
965
|
+
// Guard against the +1 day landing in an adjacent month with outside days
|
|
966
|
+
// hidden; if present it must carry no marker.
|
|
967
|
+
if (other) {
|
|
968
|
+
expect(other).not.toHaveAttribute('data-marker');
|
|
969
|
+
}
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
it('exposes the marker states as themeable defineTheme targets', () => {
|
|
973
|
+
// jsdom can't resolve the @layer cascade, so the DOM-reflection tests
|
|
974
|
+
// above cover that the right state renders; this asserts the state is
|
|
975
|
+
// reachable by a theme via the sanctioned defineTheme channel.
|
|
976
|
+
const theme = defineTheme({
|
|
977
|
+
name: 'calendar-marker-test',
|
|
978
|
+
components: {
|
|
979
|
+
'calendar-day': {
|
|
980
|
+
'marker:today-only': {
|
|
981
|
+
boxShadow: 'inset 0 0 0 2px var(--color-accent)',
|
|
982
|
+
},
|
|
983
|
+
'marker:today-in-range': {
|
|
984
|
+
boxShadow: 'inset 0 0 0 2px var(--color-text-primary)',
|
|
985
|
+
},
|
|
986
|
+
},
|
|
987
|
+
},
|
|
988
|
+
});
|
|
989
|
+
const css = generateThemeCSSFlat(theme);
|
|
990
|
+
expect(css).toContain('.astryx-calendar-day.today-only');
|
|
991
|
+
expect(css).toContain('.astryx-calendar-day.today-in-range');
|
|
992
|
+
expect(css).toContain('box-shadow: inset 0 0 0 2px var(--color-accent)');
|
|
993
|
+
expect(css).toContain(
|
|
994
|
+
'box-shadow: inset 0 0 0 2px var(--color-text-primary)',
|
|
995
|
+
);
|
|
996
|
+
});
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
// ─── Theming targets ─────────────────────────────────────────
|
|
1000
|
+
describe('theming targets', () => {
|
|
1001
|
+
it('renders the astryx-calendar-nav target on both month-nav buttons', () => {
|
|
1002
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
1003
|
+
|
|
1004
|
+
const prev = getButton('Previous month');
|
|
1005
|
+
const next = getButton('Next month');
|
|
1006
|
+
|
|
1007
|
+
// Dedicated, stable theme target — scoped to the nav controls, not the
|
|
1008
|
+
// global astryx-button handle that hits every Button in the app.
|
|
1009
|
+
expect(prev).toHaveClass('astryx-calendar-nav');
|
|
1010
|
+
expect(next).toHaveClass('astryx-calendar-nav');
|
|
1011
|
+
|
|
1012
|
+
// Direction is reflected so a theme can target one arrow alone.
|
|
1013
|
+
expect(prev).toHaveAttribute('data-nav', 'prev');
|
|
1014
|
+
expect(next).toHaveAttribute('data-nav', 'next');
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1017
|
+
it('reflects the disabled nav state as a data attribute at the range edges', () => {
|
|
1018
|
+
// Clamp navigation so "Previous month" is disabled and "Next" is not.
|
|
1019
|
+
render(
|
|
1020
|
+
<Calendar focusDate="2026-01-15" min="2026-01-01" max="2026-03-31" />,
|
|
1021
|
+
);
|
|
1022
|
+
|
|
1023
|
+
const prev = getButton('Previous month');
|
|
1024
|
+
const next = getButton('Next month');
|
|
1025
|
+
|
|
1026
|
+
expect(prev).toHaveAttribute('data-disabled', 'disabled');
|
|
1027
|
+
expect(next).not.toHaveAttribute('data-disabled');
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
it('keeps the default nav rendering unchanged (still a ghost icon button)', () => {
|
|
1031
|
+
render(<Calendar focusDate="2026-01-01" />);
|
|
1032
|
+
|
|
1033
|
+
// The new target is additive — the nav still carries the stock Button
|
|
1034
|
+
// classes, so default appearance is preserved.
|
|
1035
|
+
const prev = getButton('Previous month');
|
|
1036
|
+
expect(prev).toHaveClass('astryx-button');
|
|
1037
|
+
expect(prev).toHaveClass('ghost');
|
|
1038
|
+
expect(prev.tagName).toBe('BUTTON');
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
it('renders the astryx-calendar-day target with its reflected states', () => {
|
|
1042
|
+
render(
|
|
1043
|
+
<Calendar mode="single" value="2026-01-15" focusDate="2026-01-01" />,
|
|
1044
|
+
);
|
|
1045
|
+
|
|
1046
|
+
const selected = getDayButton(15);
|
|
1047
|
+
expect(selected).toHaveClass('astryx-calendar-day');
|
|
1048
|
+
expect(selected).toHaveAttribute('data-selected', 'selected');
|
|
1049
|
+
|
|
1050
|
+
// A non-selected weekday cell still carries the base target and no
|
|
1051
|
+
// selected/today reflection.
|
|
1052
|
+
const plain = getDayButton(20);
|
|
1053
|
+
expect(plain).toHaveClass('astryx-calendar-day');
|
|
1054
|
+
expect(plain).not.toHaveAttribute('data-selected');
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
it('exposes calendar-nav as a themeable defineTheme target', () => {
|
|
1058
|
+
// The generated CSS is what proves the target is reachable by a theme:
|
|
1059
|
+
// jsdom cannot resolve the @layer cascade, so the DOM-class assertions
|
|
1060
|
+
// above and this generation assertion together cover the seam.
|
|
1061
|
+
const theme = defineTheme({
|
|
1062
|
+
name: 'calendar-nav-test',
|
|
1063
|
+
components: {
|
|
1064
|
+
'calendar-nav': {
|
|
1065
|
+
base: {color: 'var(--color-accent)'},
|
|
1066
|
+
'nav:next': {backgroundColor: 'var(--color-accent-muted)'},
|
|
1067
|
+
},
|
|
1068
|
+
},
|
|
1069
|
+
});
|
|
1070
|
+
const css = generateThemeCSSFlat(theme);
|
|
1071
|
+
expect(css).toContain('.astryx-calendar-nav {');
|
|
1072
|
+
expect(css).toContain('color: var(--color-accent)');
|
|
1073
|
+
expect(css).toContain('.astryx-calendar-nav.next');
|
|
1074
|
+
expect(css).toContain('background-color: var(--color-accent-muted)');
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
884
1077
|
});
|
|
@@ -452,6 +452,10 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
452
452
|
{/* Header with navigation */}
|
|
453
453
|
<div {...stylex.props(calendarStyles.header)}>
|
|
454
454
|
<Button
|
|
455
|
+
{...themeProps('calendar-nav', {
|
|
456
|
+
nav: 'prev',
|
|
457
|
+
disabled: !canNavigatePrevious ? 'disabled' : null,
|
|
458
|
+
})}
|
|
455
459
|
label={t('@astryx.calendar.previousMonth')}
|
|
456
460
|
variant="ghost"
|
|
457
461
|
icon={
|
|
@@ -472,6 +476,10 @@ export function Calendar({ref, ...props}: CalendarProps) {
|
|
|
472
476
|
</span>
|
|
473
477
|
|
|
474
478
|
<Button
|
|
479
|
+
{...themeProps('calendar-nav', {
|
|
480
|
+
nav: 'next',
|
|
481
|
+
disabled: !canNavigateNext ? 'disabled' : null,
|
|
482
|
+
})}
|
|
475
483
|
label={t('@astryx.calendar.nextMonth')}
|
|
476
484
|
variant="ghost"
|
|
477
485
|
icon={
|
|
@@ -941,6 +949,21 @@ function DayCell({
|
|
|
941
949
|
});
|
|
942
950
|
|
|
943
951
|
const endpoint = isEndpoint(state);
|
|
952
|
+
|
|
953
|
+
// The day's focus-ring treatment, derived once so the reflected `marker`
|
|
954
|
+
// theme state and the StyleX ring styles below share a single source of
|
|
955
|
+
// truth. `state.isSelected` is single-select only, so a range endpoint that
|
|
956
|
+
// is today still qualifies for the today-in-range ring (unchanged prior
|
|
957
|
+
// behavior).
|
|
958
|
+
const showsTodayRing = state.isToday && !state.isSelected && !state.isInRange;
|
|
959
|
+
const showsTodayInRangeRing =
|
|
960
|
+
state.isToday && !state.isSelected && state.isInRange;
|
|
961
|
+
const markerState: 'today-only' | 'today-in-range' | null = showsTodayRing
|
|
962
|
+
? 'today-only'
|
|
963
|
+
: showsTodayInRangeRing
|
|
964
|
+
? 'today-in-range'
|
|
965
|
+
: null;
|
|
966
|
+
|
|
944
967
|
const rangeRounding = computeRangeRounding(state, {
|
|
945
968
|
prevInRange: neighbors.prevInRange,
|
|
946
969
|
nextInRange: neighbors.nextInRange,
|
|
@@ -1010,28 +1033,27 @@ function DayCell({
|
|
|
1010
1033
|
today: state.isToday ? 'today' : null,
|
|
1011
1034
|
disabled: state.effectivelyDisabled ? 'disabled' : null,
|
|
1012
1035
|
'in-range': state.isInRange ? 'in-range' : null,
|
|
1036
|
+
// `marker` reflects the day's *actual* focus-ring treatment as a
|
|
1037
|
+
// single compound state, so a theme can target exactly the states
|
|
1038
|
+
// the ring is drawn under without needing `:not()` in the theme
|
|
1039
|
+
// key. It is null unless a ring is shown:
|
|
1040
|
+
// 'today-only' → today, not single-selected, not in a range
|
|
1041
|
+
// 'today-in-range' → today, not single-selected, inside a range
|
|
1042
|
+
// `isSelected` here is single-select only (see computeDayCellState),
|
|
1043
|
+
// so a today range endpoint still shows the today-in-range ring —
|
|
1044
|
+
// `marker` mirrors the StyleX conditions below exactly, preserving
|
|
1045
|
+
// the default rendering.
|
|
1046
|
+
marker: markerState,
|
|
1013
1047
|
}),
|
|
1014
1048
|
stylex.props(
|
|
1015
1049
|
dayCellStyles.day,
|
|
1016
1050
|
dayCellTheme.day,
|
|
1017
1051
|
isOutside && dayCellStyles.dayOutside,
|
|
1018
1052
|
isOutside && dayCellTheme.dayOutside,
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
state.isToday &&
|
|
1024
|
-
!state.isSelected &&
|
|
1025
|
-
!state.isInRange &&
|
|
1026
|
-
dayCellTheme.dayToday,
|
|
1027
|
-
state.isToday &&
|
|
1028
|
-
!state.isSelected &&
|
|
1029
|
-
state.isInRange &&
|
|
1030
|
-
dayCellStyles.dayTodayInRange,
|
|
1031
|
-
state.isToday &&
|
|
1032
|
-
!state.isSelected &&
|
|
1033
|
-
state.isInRange &&
|
|
1034
|
-
dayCellTheme.dayTodayInRange,
|
|
1053
|
+
showsTodayRing && dayCellStyles.dayToday,
|
|
1054
|
+
showsTodayRing && dayCellTheme.dayToday,
|
|
1055
|
+
showsTodayInRangeRing && dayCellStyles.dayTodayInRange,
|
|
1056
|
+
showsTodayInRangeRing && dayCellTheme.dayTodayInRange,
|
|
1035
1057
|
endpoint && dayCellStyles.daySelected,
|
|
1036
1058
|
endpoint && dayCellTheme.daySelected,
|
|
1037
1059
|
state.effectivelyDisabled && dayCellStyles.dayDisabled,
|
|
@@ -45,6 +45,11 @@ describe('computeDayCellState', () => {
|
|
|
45
45
|
expect(state.isToday).toBe(false);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
+
it('does not identify an outside day as today', () => {
|
|
49
|
+
const state = computeDayCellState(makeInput({isOutside: true}));
|
|
50
|
+
expect(state.isToday).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
48
53
|
it('identifies selected day in single mode', () => {
|
|
49
54
|
const state = computeDayCellState(
|
|
50
55
|
makeInput({selectedDate: plainDateFromISO('2024-03-15')}),
|
|
@@ -56,7 +56,7 @@ export function computeDayCellState(input: DayCellStateInput): DayCellState {
|
|
|
56
56
|
|
|
57
57
|
return {
|
|
58
58
|
effectivelyDisabled: isDisabled || isOutside,
|
|
59
|
-
isToday: plainDateIsEqual(date, today),
|
|
59
|
+
isToday: !isOutside && plainDateIsEqual(date, today),
|
|
60
60
|
isSelected: !!(
|
|
61
61
|
!isOutside &&
|
|
62
62
|
mode === 'single' &&
|
package/src/Card/Card.doc.mjs
CHANGED
|
@@ -67,6 +67,13 @@ export const docs = {
|
|
|
67
67
|
'Background color variant. `default` uses the standard card background. `transparent` drops the background entirely. `muted` uses the muted background for de-emphasised cards. The non-semantic variants use the corresponding `--color-background-<name>` token.',
|
|
68
68
|
default: "'default'",
|
|
69
69
|
},
|
|
70
|
+
{
|
|
71
|
+
name: 'elevation',
|
|
72
|
+
type: "'none' | 'low' | 'med' | 'high'",
|
|
73
|
+
description:
|
|
74
|
+
'Resting shadow depth. `none` is flat; `low`/`med`/`high` map to the shadow token scale. Raise a card only when it needs to float above surrounding content.',
|
|
75
|
+
default: "'none'",
|
|
76
|
+
},
|
|
70
77
|
],
|
|
71
78
|
playground: {
|
|
72
79
|
defaults: {
|
|
@@ -127,6 +134,7 @@ export const docsZh = {
|
|
|
127
134
|
{name: 'minHeight', type: 'SizeValue', description: '卡片最小高度。'},
|
|
128
135
|
{name: 'children', type: 'ReactNode', description: '在卡片内部渲染的内容。'},
|
|
129
136
|
{name: 'padding', type: '0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10', description: '使用间距比例的内边距。', default: '4'},
|
|
137
|
+
{name: 'elevation', type: "'none' | 'low' | 'med' | 'high'", description: '静止阴影深度。`none` 为扁平;`low`/`med`/`high` 对应阴影令牌比例。', default: "'none'"},
|
|
130
138
|
],
|
|
131
139
|
theming: {
|
|
132
140
|
container: true,
|
|
@@ -170,5 +178,6 @@ export const docsDense = {
|
|
|
170
178
|
children: 'content inside card',
|
|
171
179
|
padding: 'internal padding via spacing scale',
|
|
172
180
|
variant: 'background color variant; `default` = standard card bg, `transparent` = no background at all, `muted` = muted bg for de-emphasised cards; non-semantic variants use the corresponding `--color-background-<name>` token',
|
|
181
|
+
elevation: 'resting shadow depth: none (flat) | low | med | high (shadow token scale). Raise only to float above content.',
|
|
173
182
|
},
|
|
174
183
|
};
|
package/src/Card/Card.test.tsx
CHANGED
|
@@ -17,11 +17,29 @@ describe('Card', () => {
|
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
it('renders transparent variant with variant class', () => {
|
|
20
|
-
const {container} = render(
|
|
21
|
-
<Card variant="transparent">Content</Card>,
|
|
22
|
-
);
|
|
20
|
+
const {container} = render(<Card variant="transparent">Content</Card>);
|
|
23
21
|
const root = container.firstElementChild!;
|
|
24
22
|
expect(root.className).toContain('astryx-card');
|
|
25
23
|
expect(root.className).toContain('transparent');
|
|
26
24
|
});
|
|
25
|
+
|
|
26
|
+
it('applies a distinct class for each elevation level', () => {
|
|
27
|
+
const classFor = (elevation: 'none' | 'low' | 'med' | 'high') => {
|
|
28
|
+
const {container} = render(<Card elevation={elevation}>C</Card>);
|
|
29
|
+
return container.firstElementChild!.className;
|
|
30
|
+
};
|
|
31
|
+
const none = classFor('none');
|
|
32
|
+
const low = classFor('low');
|
|
33
|
+
const med = classFor('med');
|
|
34
|
+
const high = classFor('high');
|
|
35
|
+
expect(new Set([none, low, med, high]).size).toBe(4);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('defaults to flat (elevation none) — same class as explicit none', () => {
|
|
39
|
+
const {container: defaultContainer} = render(<Card>C</Card>);
|
|
40
|
+
const {container: noneContainer} = render(<Card elevation="none">C</Card>);
|
|
41
|
+
expect(defaultContainer.firstElementChild!.className).toBe(
|
|
42
|
+
noneContainer.firstElementChild!.className,
|
|
43
|
+
);
|
|
44
|
+
});
|
|
27
45
|
});
|
package/src/Card/Card.tsx
CHANGED
|
@@ -17,7 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
import type {ReactNode} from 'react';
|
|
19
19
|
import * as stylex from '@stylexjs/stylex';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
borderVars,
|
|
22
|
+
colorVars,
|
|
23
|
+
radiusVars,
|
|
24
|
+
shadowVars,
|
|
25
|
+
} from '../theme/tokens.stylex';
|
|
21
26
|
import {container} from '../Layout/container.stylex';
|
|
22
27
|
import type {SpacingToken} from '../Layout/container.stylex';
|
|
23
28
|
import {
|
|
@@ -27,7 +32,7 @@ import {
|
|
|
27
32
|
containerPaddingBlockEndVarStyles,
|
|
28
33
|
spacingStepToToken,
|
|
29
34
|
} from '../Layout/padding.stylex';
|
|
30
|
-
import type {SizeValue, SpacingStep} from '../utils/types';
|
|
35
|
+
import type {Elevation, SizeValue, SpacingStep} from '../utils/types';
|
|
31
36
|
import {mergeProps} from '../utils';
|
|
32
37
|
import type {BaseProps} from '../BaseProps';
|
|
33
38
|
import {themeProps} from '../utils/themeProps';
|
|
@@ -73,6 +78,13 @@ const styles = stylex.create({
|
|
|
73
78
|
'--_card-radius': radiusVars['--radius-container'],
|
|
74
79
|
borderRadius: 'var(--_card-radius)',
|
|
75
80
|
overflow: 'clip',
|
|
81
|
+
// Resting elevation is set via --_card-elevation (see elevationStyles).
|
|
82
|
+
// The shadow list also reads --_card-ring so composing surfaces — e.g.
|
|
83
|
+
// SelectableCard's inset selection ring — can layer their own shadow
|
|
84
|
+
// alongside elevation instead of clobbering the single box-shadow property.
|
|
85
|
+
// Unset vars fall back to a transparent no-op shadow.
|
|
86
|
+
boxShadow:
|
|
87
|
+
'var(--_card-ring, 0 0 transparent), var(--_card-elevation, 0 0 transparent)',
|
|
76
88
|
},
|
|
77
89
|
// The border is drawn *inside* the padding — its width is subtracted from
|
|
78
90
|
// each side — so total inset (border + padding) equals the padding token
|
|
@@ -135,6 +147,18 @@ const variantStyles = stylex.create({
|
|
|
135
147
|
},
|
|
136
148
|
});
|
|
137
149
|
|
|
150
|
+
// Elevation → shadow-token map. Sets the private --_card-elevation variable
|
|
151
|
+
// (not box-shadow directly) so it composes with --_card-ring in the shadow
|
|
152
|
+
// list above — a selection ring and a resting elevation coexist without one
|
|
153
|
+
// overwriting the other. 'none' is a transparent no-op (not the CSS literal
|
|
154
|
+
// `none`, which would be invalid inside the comma-separated shadow list).
|
|
155
|
+
const elevationStyles = stylex.create({
|
|
156
|
+
none: {'--_card-elevation': '0 0 transparent'},
|
|
157
|
+
low: {'--_card-elevation': shadowVars['--shadow-low']},
|
|
158
|
+
med: {'--_card-elevation': shadowVars['--shadow-med']},
|
|
159
|
+
high: {'--_card-elevation': shadowVars['--shadow-high']},
|
|
160
|
+
});
|
|
161
|
+
|
|
138
162
|
// Dynamic styles for sizing props
|
|
139
163
|
const dynamicStyles = stylex.create({
|
|
140
164
|
sizing: (
|
|
@@ -208,6 +232,13 @@ export interface CardProps extends BaseProps<HTMLDivElement> {
|
|
|
208
232
|
* @default 'default'
|
|
209
233
|
*/
|
|
210
234
|
variant?: CardVariant;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Resting elevation — the shadow depth the card sits at.
|
|
238
|
+
* `none` is flat; `low`/`med`/`high` map to the shadow token scale.
|
|
239
|
+
* @default 'none'
|
|
240
|
+
*/
|
|
241
|
+
elevation?: Elevation;
|
|
211
242
|
}
|
|
212
243
|
|
|
213
244
|
/**
|
|
@@ -252,6 +283,7 @@ export function Card({
|
|
|
252
283
|
children,
|
|
253
284
|
padding,
|
|
254
285
|
variant = 'default',
|
|
286
|
+
elevation = 'none',
|
|
255
287
|
xstyle,
|
|
256
288
|
className,
|
|
257
289
|
style,
|
|
@@ -274,6 +306,7 @@ export function Card({
|
|
|
274
306
|
stylex.props(
|
|
275
307
|
styles.card,
|
|
276
308
|
variantStyles[variant],
|
|
309
|
+
elevationStyles[elevation],
|
|
277
310
|
hasFixedHeight && styles.scrollable,
|
|
278
311
|
dynamicStyles.sizing(
|
|
279
312
|
width ?? null,
|
|
@@ -91,6 +91,7 @@ export const docsDense = {
|
|
|
91
91
|
{guidance: true, description: 'Enable scroll-snap when each item should land precisely at the start edge: gallery, product list.'},
|
|
92
92
|
{guidance: true, description: 'Always provide an aria-label describing what the carousel contains: "Featured products", "Team members".'},
|
|
93
93
|
{guidance: true, description: 'Use consistent gap + item width so the carousel looks intentional, not like content overflowing by accident.'},
|
|
94
|
+
{guidance: true, description: 'Trust built-in navigation: trackpad users swipe horizontally, mouse users hold Shift + wheel to move through items.'},
|
|
94
95
|
{guidance: false, description: 'Use a carousel for content every user must see. Not everyone scrolls horizontally, so put critical content above the fold.'},
|
|
95
96
|
{guidance: false, description: 'Auto-advance items. Let the user scroll at their own pace.'},
|
|
96
97
|
{guidance: false, description: 'Nest carousels. A carousel inside a carousel is confusing and breaks keyboard navigation.'},
|
|
@@ -92,6 +92,59 @@ describe('Carousel', () => {
|
|
|
92
92
|
expect(screen.getByLabelText('Scroll right')).toBeInTheDocument();
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
describe('slide semantics', () => {
|
|
96
|
+
it('exposes each slide as a group with aria-roledescription="slide" and a positional name', () => {
|
|
97
|
+
render(
|
|
98
|
+
<Carousel aria-label="Photos">
|
|
99
|
+
<div>One</div>
|
|
100
|
+
<div>Two</div>
|
|
101
|
+
<div>Three</div>
|
|
102
|
+
</Carousel>,
|
|
103
|
+
);
|
|
104
|
+
// APG carousel pattern: each slide container is role=group with
|
|
105
|
+
// aria-roledescription="slide" and an "N of M" accessible name.
|
|
106
|
+
const slides = screen.getAllByRole('group');
|
|
107
|
+
expect(slides).toHaveLength(3);
|
|
108
|
+
slides.forEach((slide, i) => {
|
|
109
|
+
expect(slide).toHaveAttribute('aria-roledescription', 'slide');
|
|
110
|
+
expect(slide).toHaveAccessibleName(`Slide ${i + 1} of 3`);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('reflects the rendered child count, skipping null and boolean children', () => {
|
|
115
|
+
render(
|
|
116
|
+
<Carousel aria-label="Photos">
|
|
117
|
+
<div>One</div>
|
|
118
|
+
{null}
|
|
119
|
+
{false}
|
|
120
|
+
<div>Two</div>
|
|
121
|
+
</Carousel>,
|
|
122
|
+
);
|
|
123
|
+
const slides = screen.getAllByRole('group');
|
|
124
|
+
expect(slides).toHaveLength(2);
|
|
125
|
+
expect(
|
|
126
|
+
screen.getByRole('group', {name: 'Slide 1 of 2'}),
|
|
127
|
+
).toBeInTheDocument();
|
|
128
|
+
expect(
|
|
129
|
+
screen.getByRole('group', {name: 'Slide 2 of 2'}),
|
|
130
|
+
).toBeInTheDocument();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('keeps the container region semantics unchanged around labelled slides', () => {
|
|
134
|
+
render(
|
|
135
|
+
<Carousel aria-label="Gallery">
|
|
136
|
+
<div>One</div>
|
|
137
|
+
<div>Two</div>
|
|
138
|
+
</Carousel>,
|
|
139
|
+
);
|
|
140
|
+
const region = screen.getByRole('region', {name: 'Gallery'});
|
|
141
|
+
expect(region).toHaveAttribute('aria-roledescription', 'carousel');
|
|
142
|
+
const slides = screen.getAllByRole('group');
|
|
143
|
+
expect(slides).toHaveLength(2);
|
|
144
|
+
slides.forEach(slide => expect(region).toContainElement(slide));
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
95
148
|
it('disables edge scroll buttons instead of removing them from the tab order', () => {
|
|
96
149
|
// In jsdom there is no measurable overflow, so both edges are at rest and
|
|
97
150
|
// the scroll buttons are in their hidden/inert state. They must stay
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* @position Horizontal scroll container with fade-edge overflow indication,
|
|
10
10
|
* optional prev/next buttons on the top layer, scroll-snap, a 1px
|
|
11
11
|
* visual bleed allowance for child selection indicators, and Shift + wheel
|
|
12
|
-
* mapping so mouse users can scroll horizontally.
|
|
12
|
+
* mapping so mouse users can scroll horizontally. Exposes APG
|
|
13
|
+
* carousel semantics: the root is a labelled region with
|
|
14
|
+
* aria-roledescription="carousel" and each item wrapper is a group with
|
|
15
|
+
* aria-roledescription="slide" named "Slide N of M".
|
|
13
16
|
*
|
|
14
17
|
* SYNC: When modified, update:
|
|
15
18
|
* - /packages/core/src/Carousel/index.ts (exports)
|
|
@@ -17,7 +20,14 @@
|
|
|
17
20
|
* - /packages/cli/templates/blocks/components/Carousel/ (showcase blocks)
|
|
18
21
|
*/
|
|
19
22
|
|
|
20
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
type ReactNode,
|
|
25
|
+
useRef,
|
|
26
|
+
useCallback,
|
|
27
|
+
useEffect,
|
|
28
|
+
Children,
|
|
29
|
+
isValidElement,
|
|
30
|
+
} from 'react';
|
|
21
31
|
import * as stylex from '@stylexjs/stylex';
|
|
22
32
|
import {
|
|
23
33
|
spacingVars,
|
|
@@ -270,6 +280,11 @@ export function Carousel({
|
|
|
270
280
|
const scrollElRef = useRef<HTMLElement | null>(null);
|
|
271
281
|
const {scrollRef, overflowStart, overflowEnd} = useScrollOverflow();
|
|
272
282
|
|
|
283
|
+
// Children.toArray drops null/undefined/boolean children and assigns
|
|
284
|
+
// stable keys, so slide numbering ("Slide N of M") matches what actually
|
|
285
|
+
// renders even when some children are conditionally omitted.
|
|
286
|
+
const slides = Children.toArray(children);
|
|
287
|
+
|
|
273
288
|
const layer = useLayer({
|
|
274
289
|
mode: 'context',
|
|
275
290
|
lightDismiss: false,
|
|
@@ -380,8 +395,23 @@ export function Carousel({
|
|
|
380
395
|
hasSnap && styles.snap,
|
|
381
396
|
fadeStyle,
|
|
382
397
|
)}>
|
|
383
|
-
{
|
|
384
|
-
|
|
398
|
+
{slides.map((child, index) => (
|
|
399
|
+
// APG carousel pattern: each slide container is a group with
|
|
400
|
+
// aria-roledescription="slide" and an "N of M" accessible name so
|
|
401
|
+
// ATs announce slide boundaries and position instead of anonymous
|
|
402
|
+
// generics.
|
|
403
|
+
<div
|
|
404
|
+
// eslint-disable-next-line @eslint-react/no-array-index-key -- index fallback only applies to text/number children, which are positional by definition; elements keep their Children.toArray keys
|
|
405
|
+
key={isValidElement(child) ? child.key : index}
|
|
406
|
+
role="group"
|
|
407
|
+
aria-roledescription="slide"
|
|
408
|
+
aria-label={t('@astryx.carousel.slideLabel', {
|
|
409
|
+
current: index + 1,
|
|
410
|
+
total: slides.length,
|
|
411
|
+
})}
|
|
412
|
+
{...stylex.props(styles.item)}>
|
|
413
|
+
{child}
|
|
414
|
+
</div>
|
|
385
415
|
))}
|
|
386
416
|
</div>
|
|
387
417
|
|
|
@@ -56,6 +56,13 @@ export const docs = {
|
|
|
56
56
|
description: 'Visual density.',
|
|
57
57
|
default: "'balanced'",
|
|
58
58
|
},
|
|
59
|
+
{
|
|
60
|
+
name: 'elevation',
|
|
61
|
+
type: "'none' | 'low'",
|
|
62
|
+
description:
|
|
63
|
+
"Resting elevation of the composer body. `low` (the default) keeps today's raised look — low at rest, bumping to med on hover / focus. `none` flattens it and draws a border with the same rest / hover / focus treatment as a text input (emphasized border → accent on focus, matching inset rings).",
|
|
64
|
+
default: "'low'",
|
|
65
|
+
},
|
|
59
66
|
{
|
|
60
67
|
name: 'drawer',
|
|
61
68
|
type: 'ReactNode',
|
|
@@ -102,7 +109,7 @@ export const docs = {
|
|
|
102
109
|
{
|
|
103
110
|
name: 'input',
|
|
104
111
|
type: 'ReactNode',
|
|
105
|
-
description: 'Slot: custom input element. Replaces the default
|
|
112
|
+
description: 'Slot: custom input element. Replaces the default input. Use ChatComposerInput for trigger menus/tokens, or wire any input (plain textarea, rich editor) to the composition contract via useChatComposerContext() — read value/onChange/onSubmit/canSend and register a focus control on inputControlRef so body-click-to-focus works.',
|
|
106
113
|
slotElements: [
|
|
107
114
|
{
|
|
108
115
|
__element: 'TextInput',
|
|
@@ -185,10 +192,11 @@ export const docsZh = {
|
|
|
185
192
|
placeholder: '输入为空时显示的占位文本。',
|
|
186
193
|
isDisabled: '禁用编写器。',
|
|
187
194
|
density: '视觉密度。',
|
|
195
|
+
elevation: "编写器主体的静止高度。low(默认)保持当前的抬起外观——静止时 low,悬停/聚焦时升至 med。none 则扁平化。",
|
|
188
196
|
drawer: '插槽:输入上方的可折叠抽屉——附件、上下文标签等。使用 ChatComposerDrawer。',
|
|
189
197
|
headerActions: '插槽:标题左侧操作按钮(附件、提及按钮)。使用仅图标 size="sm" 按钮。',
|
|
190
198
|
headerContext: '插槽:标题右侧上下文信息(上下文窗口使用情况、ProgressBar、辅助文本)。',
|
|
191
|
-
input: '
|
|
199
|
+
input: '插槽:自定义输入元素。替换默认输入。使用 ChatComposerInput 实现触发菜单/标记,或通过 useChatComposerContext() 将任意输入(纯 textarea、富文本编辑器)接入组合契约——读取 value/onChange/onSubmit/canSend,并在 inputControlRef 上注册聚焦控制,使点击空白处聚焦生效。',
|
|
192
200
|
footerActions: '插槽:左对齐的页脚操作(模型选择器等)。',
|
|
193
201
|
sendActions: '插槽:发送按钮左侧的操作。',
|
|
194
202
|
sendButton: '插槽:自定义发送按钮。替换默认的发送/停止按钮。',
|
|
@@ -210,10 +218,11 @@ export const docsDense = {
|
|
|
210
218
|
placeholder: 'placeholder when empty',
|
|
211
219
|
isDisabled: 'disabled; use during streaming or unmet prereqs',
|
|
212
220
|
density: 'visual density',
|
|
221
|
+
elevation: "resting elevation of composer body: low (default; low→med on hover/focus) | none (flat)",
|
|
213
222
|
drawer: 'slot: collapsible drawer above input: attachments, context chips, etc.; use ChatComposerDrawer',
|
|
214
223
|
headerActions: 'slot: left header actions (attach, mention); icon-only sm buttons',
|
|
215
224
|
headerContext: 'slot: right header context info (window usage, ProgressBar, text)',
|
|
216
|
-
input: 'slot: custom input; replaces default
|
|
225
|
+
input: 'slot: custom input; replaces default. use ChatComposerInput for triggers/tokens, or wire any input via useChatComposerContext() (value/onChange/onSubmit/canSend + register focus on inputControlRef)',
|
|
217
226
|
footerActions: 'slot: left footer actions (model selector etc)',
|
|
218
227
|
sendActions: 'slot: actions left of send btn',
|
|
219
228
|
sendButton: 'slot: custom send btn; replaces default',
|