@astryxdesign/core 0.1.8 → 0.1.9-canary.02ef052
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 +58 -3
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +240 -53
- package/dist/Avatar/AvatarStatusDot.d.ts +35 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +58 -6
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
- package/dist/Banner/Banner.d.ts +9 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +33 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +215 -6
- package/dist/Breadcrumbs/index.d.ts +6 -0
- package/dist/Breadcrumbs/index.d.ts.map +1 -1
- package/dist/Breadcrumbs/index.js +10 -1
- package/dist/Button/Button.d.ts +8 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +33 -4
- 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 +80 -11
- package/dist/Calendar/dayCellUtils.d.ts +4 -4
- package/dist/Calendar/dayCellUtils.js +3 -3
- package/dist/Calendar/styles.d.ts +30 -31
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +30 -31
- 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 +46 -16
- 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 +36 -4
- 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 +4 -2
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +4 -4
- 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 +27 -11
- 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/Chat/useTriggerMenu.js +2 -2
- package/dist/CheckboxInput/CheckboxInput.js +5 -5
- 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/Citation/Citation.d.ts +22 -1
- package/dist/Citation/Citation.d.ts.map +1 -1
- package/dist/Citation/Citation.js +20 -6
- 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 +22 -9
- package/dist/Collapsible/Collapsible.d.ts.map +1 -1
- package/dist/Collapsible/Collapsible.js +3 -1
- package/dist/CommandPalette/CommandPalette.d.ts +2 -2
- package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPalette.js +45 -4
- 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/CommandPalette/CommandPaletteItem.js +1 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +14 -5
- package/dist/ContextMenu/index.d.ts +1 -0
- package/dist/ContextMenu/index.d.ts.map +1 -1
- package/dist/ContextMenu/index.js +3 -1
- package/dist/DateInput/DateInput.d.ts +56 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +59 -21
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +23 -20
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +33 -19
- 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/DropdownMenu.d.ts +6 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +22 -5
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts +1 -2
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +5 -3
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +5 -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/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
- package/dist/DropdownMenu/index.d.ts +10 -0
- package/dist/DropdownMenu/index.d.ts.map +1 -1
- package/dist/DropdownMenu/index.js +13 -0
- package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
- package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
- package/dist/DropdownMenu/menuItemHover.js +33 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
- package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
- package/dist/DropdownMenu/menuItemRoles.js +10 -1
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -6
- package/dist/Field/Field.d.ts +3 -1
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +6 -4
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +43 -16
- package/dist/Field/inputStyles.stylex.d.ts +1 -0
- package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
- package/dist/Field/inputStyles.stylex.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +18 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +60 -6
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +54 -35
- 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 +17 -6
- package/dist/Icon/Icon.d.ts +22 -3
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +19 -3
- 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/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +19 -13
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +7 -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 +9 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +104 -50
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +16 -0
- package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
- package/dist/NumberInput/NumberInput.d.ts +10 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +22 -17
- 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/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +11 -3
- 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/PowerSearch.d.ts +9 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +2 -0
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/PowerSearch/usePowerSearchSource.d.ts.map +1 -1
- package/dist/RadioList/RadioList.d.ts +2 -2
- package/dist/RadioList/RadioListItem.js +4 -4
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +2 -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 +8 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +65 -19
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +16 -0
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +5 -5
- package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
- package/dist/SideNav/SideNavCollapseButton.js +13 -10
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +21 -8
- package/dist/SideNav/SideNavItem.d.ts +1 -1
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +12 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +106 -36
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Switch/Switch.d.ts +8 -1
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +160 -91
- package/dist/TabList/Tab.js +2 -2
- package/dist/TabList/TabMenu.js +1 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +33 -6
- package/dist/Table/TableCell.js +3 -3
- package/dist/Table/TableHeaderCell.js +3 -3
- 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/groupedRows/useTableGroupedRows.js +15 -11
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
- 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 +7 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -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 +105 -12
- 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/types.d.ts +32 -0
- package/dist/Table/types.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
- package/dist/Table/useBaseTablePlugins.js +5 -3
- package/dist/TextArea/TextArea.d.ts +10 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +18 -19
- package/dist/TextInput/TextInput.d.ts +10 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +20 -17
- 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 +10 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +32 -21
- 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/Token/Token.d.ts +30 -3
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +17 -2
- package/dist/Token/index.d.ts +1 -1
- package/dist/Token/index.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.d.ts +10 -3
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +20 -6
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +17 -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/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 +3 -0
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +18 -10
- package/dist/TreeList/TreeListItem.d.ts +8 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +59 -21
- 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/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +20 -11
- package/dist/Typeahead/Typeahead.d.ts +9 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +3 -1
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +20 -10
- package/dist/astryx.css +61 -39
- package/dist/astryx.umd.js +53 -53
- 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 +3 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -1
- package/dist/hooks/isRtlElement.d.ts +18 -0
- package/dist/hooks/isRtlElement.d.ts.map +1 -0
- package/dist/hooks/isRtlElement.js +27 -0
- 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/useGridFocus.d.ts +6 -1
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +12 -9
- package/dist/hooks/useInputStatusIcon.d.ts +38 -0
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
- package/dist/hooks/useInputStatusIcon.js +158 -0
- package/dist/hooks/useListFocus.d.ts +39 -1
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +54 -9
- 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/InternationalizationContext.d.ts +1 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationContext.js +3 -0
- package/dist/i18n/InternationalizationProvider.d.ts +8 -1
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +5 -1
- package/dist/i18n/getLocaleDirection.d.ts +18 -0
- package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
- package/dist/i18n/getLocaleDirection.js +29 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +7 -1
- package/dist/i18n/resolve.d.ts.map +1 -1
- package/dist/i18n/resolve.js +7 -18
- package/dist/i18n/useDirection.d.ts +2 -0
- package/dist/i18n/useDirection.d.ts.map +1 -0
- package/dist/i18n/useDirection.js +27 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +2 -7
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +13 -0
- 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 +4 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -2
- package/dist/utils/plainDate.d.ts +30 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +65 -3
- package/dist/utils/rtlStyles.d.ts +24 -0
- package/dist/utils/rtlStyles.d.ts.map +1 -0
- package/dist/utils/rtlStyles.js +27 -0
- package/dist/utils/types.d.ts +13 -0
- package/dist/utils/types.d.ts.map +1 -1
- package/locales/en.json +104 -0
- package/locales/fr-FR.json +14 -0
- package/locales/pseudo.json +78 -0
- package/package.json +6 -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 +64 -5
- package/src/Avatar/Avatar.test.tsx +374 -1
- package/src/Avatar/Avatar.tsx +367 -69
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +180 -21
- package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
- package/src/AvatarGroup/AvatarGroup.test.tsx +141 -1
- package/src/AvatarGroup/AvatarGroup.tsx +58 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +30 -0
- package/src/Banner/Banner.tsx +53 -9
- 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 +335 -2
- package/src/Breadcrumbs/index.ts +31 -0
- package/src/Button/Button.doc.mjs +9 -4
- package/src/Button/Button.test.tsx +49 -0
- package/src/Button/Button.tsx +27 -3
- 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 +362 -19
- package/src/Calendar/Calendar.tsx +111 -32
- package/src/Calendar/dayCellUtils.test.ts +23 -18
- package/src/Calendar/dayCellUtils.ts +3 -3
- package/src/Calendar/styles.ts +33 -39
- 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 +59 -10
- 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 +51 -5
- package/src/Chat/ChatContext.tsx +37 -10
- package/src/Chat/ChatDictationButton.tsx +11 -2
- package/src/Chat/ChatLayout.tsx +7 -5
- 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 +33 -5
- 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 +4 -2
- package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +32 -1
- package/src/CheckboxInput/CheckboxInput.tsx +5 -5
- package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
- 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/Citation/Citation.doc.mjs +4 -3
- package/src/Citation/Citation.test.tsx +97 -0
- package/src/Citation/Citation.tsx +43 -11
- 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 +45 -10
- package/src/Collapsible/Collapsible.doc.mjs +1 -0
- package/src/Collapsible/Collapsible.test.tsx +7 -0
- package/src/Collapsible/Collapsible.tsx +16 -6
- package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
- package/src/CommandPalette/CommandPalette.test.tsx +95 -1
- package/src/CommandPalette/CommandPalette.tsx +44 -3
- 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/CommandPalette/CommandPaletteItem.tsx +1 -1
- package/src/ContextMenu/ContextMenu.test.tsx +235 -0
- package/src/ContextMenu/ContextMenu.tsx +13 -11
- package/src/ContextMenu/index.ts +5 -0
- package/src/DateInput/DateInput.doc.mjs +41 -0
- package/src/DateInput/DateInput.test.tsx +338 -0
- package/src/DateInput/DateInput.tsx +119 -32
- package/src/DateInput/index.ts +1 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
- package/src/DateRangeInput/DateRangeInput.tsx +42 -30
- package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
- package/src/DateTimeInput/DateTimeInput.test.tsx +147 -0
- package/src/DateTimeInput/DateTimeInput.tsx +58 -41
- 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 +229 -0
- package/src/DropdownMenu/DropdownMenu.tsx +31 -12
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +9 -4
- package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +1 -2
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
- package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
- package/src/DropdownMenu/index.ts +16 -0
- package/src/DropdownMenu/menuItemHover.ts +39 -0
- package/src/DropdownMenu/menuItemRoles.ts +9 -0
- package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
- package/src/Field/Field.test.tsx +57 -12
- package/src/Field/Field.tsx +20 -14
- package/src/Field/FieldLabel.tsx +9 -1
- package/src/Field/inputStyles.stylex.ts +2 -0
- package/src/FieldStatus/FieldStatus.doc.mjs +17 -5
- package/src/FieldStatus/FieldStatus.test.tsx +150 -40
- package/src/FieldStatus/FieldStatus.tsx +69 -5
- package/src/FileInput/FileInput.doc.mjs +23 -2
- package/src/FileInput/FileInput.test.tsx +135 -12
- package/src/FileInput/FileInput.tsx +65 -51
- 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 +39 -5
- package/src/Icon/Icon.doc.mjs +16 -2
- package/src/Icon/Icon.test.tsx +89 -0
- package/src/Icon/Icon.tsx +58 -5
- 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/Lightbox/Lightbox.tsx +15 -7
- package/src/List/List.test.tsx +9 -8
- package/src/Markdown/Markdown.test.tsx +21 -0
- package/src/Markdown/Markdown.tsx +4 -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 +24 -2
- package/src/MultiSelector/MultiSelector.test.tsx +498 -3
- package/src/MultiSelector/MultiSelector.tsx +149 -65
- package/src/MultiSelector/hooks.ts +17 -0
- package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
- package/src/NumberInput/NumberInput.doc.mjs +21 -0
- package/src/NumberInput/NumberInput.test.tsx +82 -7
- package/src/NumberInput/NumberInput.tsx +36 -28
- 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/Pagination/Pagination.tsx +11 -3
- package/src/Popover/Popover.tsx +7 -4
- package/src/Popover/usePopover.tsx +9 -13
- package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
- package/src/PowerSearch/PowerSearch.test.tsx +43 -0
- package/src/PowerSearch/PowerSearch.tsx +10 -1
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/PowerSearch/usePowerSearchSource.ts +1 -2
- package/src/RadioList/RadioList.doc.mjs +6 -0
- package/src/RadioList/RadioList.tsx +2 -2
- package/src/RadioList/RadioListItem.tsx +4 -4
- package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
- 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.doc.mjs +15 -0
- package/src/Selector/Selector.test.tsx +417 -0
- package/src/Selector/Selector.tsx +86 -21
- package/src/Selector/hooks.ts +17 -0
- package/src/SideNav/SideNav.test.tsx +119 -3
- package/src/SideNav/SideNav.tsx +1 -8
- package/src/SideNav/SideNavCollapseButton.tsx +15 -8
- package/src/SideNav/SideNavHeading.tsx +24 -8
- package/src/SideNav/SideNavItem.tsx +10 -4
- package/src/Slider/Slider.doc.mjs +6 -0
- package/src/Slider/Slider.test.tsx +314 -13
- package/src/Slider/Slider.tsx +117 -28
- package/src/Switch/Switch.doc.mjs +142 -42
- package/src/Switch/Switch.test.tsx +54 -1
- package/src/Switch/Switch.tsx +90 -33
- package/src/TabList/Tab.tsx +2 -2
- package/src/TabList/TabMenu.tsx +2 -2
- package/src/Table/BaseTable.tsx +37 -7
- package/src/Table/Table.doc.mjs +11 -0
- package/src/Table/Table.test.tsx +85 -0
- package/src/Table/TableCell.tsx +3 -3
- package/src/Table/TableHeaderCell.tsx +3 -3
- package/src/Table/index.ts +5 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +15 -8
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
- 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 +77 -3
- package/src/Table/plugins/selection/useTableSelection.tsx +22 -1
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
- package/src/Table/plugins/tree/useTableTreeData.tsx +139 -8
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
- package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
- package/src/Table/types.ts +33 -0
- 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.doc.mjs +21 -0
- package/src/TextArea/TextArea.test.tsx +32 -1
- package/src/TextArea/TextArea.tsx +27 -26
- package/src/TextInput/TextInput.doc.mjs +21 -0
- package/src/TextInput/TextInput.test.tsx +150 -0
- package/src/TextInput/TextInput.tsx +28 -25
- package/src/Thumbnail/Thumbnail.doc.mjs +19 -10
- package/src/Thumbnail/Thumbnail.test.tsx +98 -7
- package/src/Thumbnail/Thumbnail.tsx +142 -42
- package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
- package/src/TimeInput/TimeInput.doc.mjs +21 -0
- package/src/TimeInput/TimeInput.test.tsx +99 -1
- package/src/TimeInput/TimeInput.tsx +43 -31
- 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/Token/Token.test.tsx +21 -15
- package/src/Token/Token.tsx +31 -14
- package/src/Token/index.ts +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +38 -2
- package/src/Tokenizer/Tokenizer.test.tsx +206 -2
- package/src/Tokenizer/Tokenizer.tsx +30 -6
- package/src/Tooltip/Tooltip.test.tsx +46 -0
- package/src/Tooltip/useTooltip.tsx +20 -0
- 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 +28 -0
- package/src/TreeList/TreeList.test.tsx +272 -0
- package/src/TreeList/TreeList.tsx +23 -2
- package/src/TreeList/TreeListBranches.tsx +24 -8
- package/src/TreeList/TreeListItem.tsx +84 -22
- package/src/TreeList/TreeListTypes.ts +27 -1
- package/src/TreeList/index.ts +2 -2
- package/src/Typeahead/BaseTypeahead.tsx +30 -15
- package/src/Typeahead/Typeahead.doc.mjs +13 -0
- package/src/Typeahead/Typeahead.test.tsx +50 -0
- package/src/Typeahead/Typeahead.tsx +11 -1
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/__tests__/inputWidthContract.test.tsx +62 -0
- package/src/authoring/doc.ts +1 -3
- package/src/doc-mjs.d.ts +19 -0
- 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 +8 -0
- package/src/hooks/isRtlElement.ts +27 -0
- package/src/hooks/useDevWarning.test.tsx +45 -0
- package/src/hooks/useDevWarning.ts +54 -0
- package/src/hooks/useGridFocus.doc.mjs +3 -3
- package/src/hooks/useGridFocus.test.tsx +41 -0
- package/src/hooks/useGridFocus.ts +21 -10
- package/src/hooks/useInputStatusIcon.test.tsx +162 -0
- package/src/hooks/useInputStatusIcon.tsx +224 -0
- package/src/hooks/useListFocus.doc.mjs +25 -3
- package/src/hooks/useListFocus.test.tsx +153 -1
- package/src/hooks/useListFocus.ts +102 -9
- package/src/hooks/useOverflow.test.ts +96 -4
- package/src/hooks/useOverflow.ts +74 -33
- package/src/i18n/InternationalizationContext.ts +4 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
- package/src/i18n/InternationalizationProvider.tsx +12 -2
- package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
- package/src/i18n/__tests__/useDirection.test.tsx +66 -0
- package/src/i18n/getLocaleDirection.ts +29 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/resolve.ts +9 -21
- package/src/i18n/useDirection.ts +29 -0
- package/src/reset.css +0 -26
- package/src/reset.test.ts +60 -0
- package/src/theme/Theme.tsx +11 -14
- package/src/theme/derivedVarRegistry.test.ts +1 -0
- package/src/theme/derivedVarRegistry.ts +6 -0
- package/src/theme/generateThemeRules.test.ts +107 -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 +8 -0
- package/src/utils/plainDate.test.ts +46 -6
- package/src/utils/plainDate.ts +69 -3
- package/src/utils/rtlStyles.ts +27 -0
- package/src/utils/types.ts +14 -0
|
@@ -15,6 +15,8 @@ import userEvent from '@testing-library/user-event';
|
|
|
15
15
|
import {getButton, queryButton} from '../__tests__/fastRoleQueries';
|
|
16
16
|
import {DateTimeInput} from './DateTimeInput';
|
|
17
17
|
import type {ISODateTimeString} from './DateTimeInput';
|
|
18
|
+
import {defineTheme} from '../theme/defineTheme';
|
|
19
|
+
import {generateThemeCSSFlat} from '../theme/generateThemeRules';
|
|
18
20
|
|
|
19
21
|
describe('DateTimeInput', () => {
|
|
20
22
|
it('renders with label', () => {
|
|
@@ -185,6 +187,41 @@ describe('DateTimeInput', () => {
|
|
|
185
187
|
);
|
|
186
188
|
});
|
|
187
189
|
|
|
190
|
+
it('opens the calendar popover on ArrowDown (keyboard, forms-13)', () => {
|
|
191
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
192
|
+
const input = screen.getByRole('combobox');
|
|
193
|
+
input.focus();
|
|
194
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
195
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
196
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
197
|
+
// skipAutoFocus keeps focus in the input, per the APG date-picker pattern
|
|
198
|
+
expect(input).toHaveFocus();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('opens the calendar popover on Alt+ArrowDown (keyboard, forms-13)', () => {
|
|
202
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
203
|
+
const input = screen.getByRole('combobox');
|
|
204
|
+
fireEvent.keyDown(input, {key: 'ArrowDown', altKey: true});
|
|
205
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('does not open on ArrowDown when disabled', () => {
|
|
209
|
+
render(<DateTimeInput label="Meeting" isDisabled onChange={() => {}} />);
|
|
210
|
+
const input = screen.getByRole('combobox');
|
|
211
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
212
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('does not re-trigger on ArrowDown when the calendar is already open', () => {
|
|
216
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
217
|
+
const input = screen.getByRole('combobox');
|
|
218
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
219
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
220
|
+
// A second ArrowDown is a no-op: the calendar stays open
|
|
221
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
222
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
223
|
+
});
|
|
224
|
+
|
|
188
225
|
it('calendar button is focusable and clickable', () => {
|
|
189
226
|
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
190
227
|
const button = getButton('Open calendar');
|
|
@@ -779,4 +816,114 @@ describe('DateTimeInput', () => {
|
|
|
779
816
|
expect(onChange.mock.calls[0][0]).toContain('14:31');
|
|
780
817
|
});
|
|
781
818
|
});
|
|
819
|
+
// ===========================================================================
|
|
820
|
+
// Segment theme targets (#4075)
|
|
821
|
+
// ===========================================================================
|
|
822
|
+
|
|
823
|
+
describe('segment theme targets', () => {
|
|
824
|
+
// The root only publishes `astryx-date-time-input`; the date and time
|
|
825
|
+
// wrappers were anonymous nodes carrying hashed atomic classes only, so a
|
|
826
|
+
// theme that restyles input geometry through the text-input/date-input/
|
|
827
|
+
// time-input targets could not reach them and DateTimeInput rendered
|
|
828
|
+
// shorter than every other input under that theme.
|
|
829
|
+
|
|
830
|
+
it('renders the date segment target on the date wrapper', () => {
|
|
831
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
832
|
+
const wrapper = screen
|
|
833
|
+
.getByLabelText('Meeting')
|
|
834
|
+
.closest('.astryx-date-time-input-date-segment');
|
|
835
|
+
|
|
836
|
+
expect(wrapper).not.toBeNull();
|
|
837
|
+
// The wrapper is the input's own container, not an ancestor further up.
|
|
838
|
+
expect(wrapper).toBe(screen.getByLabelText('Meeting').parentElement);
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
it('renders the time segment target on the time wrapper', () => {
|
|
842
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
843
|
+
const wrapper = screen
|
|
844
|
+
.getByLabelText('Meeting time')
|
|
845
|
+
.closest('.astryx-date-time-input-time-segment');
|
|
846
|
+
|
|
847
|
+
expect(wrapper).not.toBeNull();
|
|
848
|
+
expect(wrapper).toBe(screen.getByLabelText('Meeting time').parentElement);
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
it('reflects size on both segments so themes can restyle geometry', () => {
|
|
852
|
+
render(<DateTimeInput label="Meeting" size="lg" onChange={() => {}} />);
|
|
853
|
+
|
|
854
|
+
const date = screen
|
|
855
|
+
.getByLabelText('Meeting')
|
|
856
|
+
.closest('.astryx-date-time-input-date-segment');
|
|
857
|
+
const time = screen
|
|
858
|
+
.getByLabelText('Meeting time')
|
|
859
|
+
.closest('.astryx-date-time-input-time-segment');
|
|
860
|
+
|
|
861
|
+
expect(date).toHaveAttribute('data-size', 'lg');
|
|
862
|
+
expect(date).toHaveClass('lg');
|
|
863
|
+
expect(time).toHaveAttribute('data-size', 'lg');
|
|
864
|
+
expect(time).toHaveClass('lg');
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
it('reflects status on both segments, mirroring the root', () => {
|
|
868
|
+
render(
|
|
869
|
+
<DateTimeInput
|
|
870
|
+
label="Meeting"
|
|
871
|
+
status={{type: 'error', message: 'Required'}}
|
|
872
|
+
onChange={() => {}}
|
|
873
|
+
/>,
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
const date = screen
|
|
877
|
+
.getByLabelText('Meeting')
|
|
878
|
+
.closest('.astryx-date-time-input-date-segment');
|
|
879
|
+
const time = screen
|
|
880
|
+
.getByLabelText('Meeting time')
|
|
881
|
+
.closest('.astryx-date-time-input-time-segment');
|
|
882
|
+
|
|
883
|
+
expect(date).toHaveAttribute('data-status', 'error');
|
|
884
|
+
expect(time).toHaveAttribute('data-status', 'error');
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
it('omits data-status when there is no status, like the root does', () => {
|
|
888
|
+
render(<DateTimeInput label="Meeting" onChange={() => {}} />);
|
|
889
|
+
|
|
890
|
+
const date = screen
|
|
891
|
+
.getByLabelText('Meeting')
|
|
892
|
+
.closest('.astryx-date-time-input-date-segment');
|
|
893
|
+
|
|
894
|
+
expect(date).not.toHaveAttribute('data-status');
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
it('keeps the root target intact', () => {
|
|
898
|
+
const {container} = render(
|
|
899
|
+
<DateTimeInput label="Meeting" onChange={() => {}} />,
|
|
900
|
+
);
|
|
901
|
+
// Additive change — the existing root target still renders.
|
|
902
|
+
expect(container.querySelector('.astryx-date-time-input')).not.toBeNull();
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
it('exposes both segments as themeable defineTheme targets', () => {
|
|
906
|
+
// jsdom cannot resolve the @layer cascade, so the generated CSS is what
|
|
907
|
+
// proves a theme can actually reach these nodes.
|
|
908
|
+
const theme = defineTheme({
|
|
909
|
+
name: 'date-time-input-segments-test',
|
|
910
|
+
components: {
|
|
911
|
+
'date-time-input-date-segment': {
|
|
912
|
+
base: {blockSize: 'var(--size-element-lg)'},
|
|
913
|
+
lg: {paddingInline: 'var(--spacing-4)'},
|
|
914
|
+
},
|
|
915
|
+
'date-time-input-time-segment': {
|
|
916
|
+
base: {blockSize: 'var(--size-element-lg)'},
|
|
917
|
+
},
|
|
918
|
+
},
|
|
919
|
+
});
|
|
920
|
+
const css = generateThemeCSSFlat(theme);
|
|
921
|
+
|
|
922
|
+
expect(css).toContain('.astryx-date-time-input-date-segment {');
|
|
923
|
+
expect(css).toContain('.astryx-date-time-input-date-segment.lg');
|
|
924
|
+
expect(css).toContain('.astryx-date-time-input-time-segment {');
|
|
925
|
+
expect(css).toContain('block-size: var(--size-element-lg)');
|
|
926
|
+
expect(css).toContain('padding-inline: var(--spacing-4)');
|
|
927
|
+
});
|
|
928
|
+
});
|
|
782
929
|
});
|
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
type KeyboardEvent,
|
|
28
28
|
} from 'react';
|
|
29
29
|
import * as stylex from '@stylexjs/stylex';
|
|
30
|
-
import type {IconName} from '../Icon';
|
|
31
30
|
import {
|
|
32
31
|
colorVars,
|
|
33
32
|
sizeVars,
|
|
@@ -40,7 +39,6 @@ import {
|
|
|
40
39
|
import {
|
|
41
40
|
Field,
|
|
42
41
|
type InputStatus,
|
|
43
|
-
type InputStatusType,
|
|
44
42
|
inputWrapperStyles,
|
|
45
43
|
inputStatusBorderStyles,
|
|
46
44
|
inputStatusHoverShadowStyles,
|
|
@@ -54,6 +52,7 @@ import {useCalendarConstraints} from '../Calendar/hooks';
|
|
|
54
52
|
import {usePopover} from '../Popover';
|
|
55
53
|
import {useTooltip} from '../Tooltip';
|
|
56
54
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
55
|
+
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
|
57
56
|
import {
|
|
58
57
|
type ISOTimeString,
|
|
59
58
|
parseDateInput,
|
|
@@ -470,25 +469,21 @@ export function DateTimeInput({
|
|
|
470
469
|
isEnabled: showsDisabledMessage,
|
|
471
470
|
});
|
|
472
471
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
> = {
|
|
483
|
-
warning: 'warning',
|
|
484
|
-
error: 'error',
|
|
485
|
-
success: 'success',
|
|
486
|
-
};
|
|
472
|
+
// DateTimeInput fixes its status presentation to the detached message box,
|
|
473
|
+
// so the shared helper suppresses the on-field icon (the message box carries
|
|
474
|
+
// its own leading glyph). Routed through the helper for consistency with the
|
|
475
|
+
// rest of the bordered input family.
|
|
476
|
+
const {statusIcon, describedBy: statusTooltipDescribedBy} =
|
|
477
|
+
useInputStatusIcon({
|
|
478
|
+
status,
|
|
479
|
+
statusVariant: 'detached',
|
|
480
|
+
});
|
|
487
481
|
|
|
488
482
|
const ariaDescribedBy =
|
|
489
483
|
[
|
|
490
484
|
description ? descriptionID : null,
|
|
491
485
|
status?.message ? statusMessageID : null,
|
|
486
|
+
statusTooltipDescribedBy,
|
|
492
487
|
showsDisabledMessage ? disabledMessageTooltip.describedBy : null,
|
|
493
488
|
]
|
|
494
489
|
.filter(Boolean)
|
|
@@ -719,12 +714,22 @@ export function DateTimeInput({
|
|
|
719
714
|
if (e.key === 'Escape' && popover.isOpen) {
|
|
720
715
|
e.preventDefault();
|
|
721
716
|
popover.hide();
|
|
717
|
+
} else if (
|
|
718
|
+
(e.key === 'ArrowDown' || (e.altKey && e.key === 'ArrowDown')) &&
|
|
719
|
+
!popover.isOpen
|
|
720
|
+
) {
|
|
721
|
+
// APG combobox: ArrowDown (and Alt+ArrowDown) opens the calendar
|
|
722
|
+
// popover from the keyboard, keeping focus in the input (forms-13).
|
|
723
|
+
e.preventDefault();
|
|
724
|
+
if (!isEffectivelyDisabled) {
|
|
725
|
+
popover.show({skipAutoFocus: true});
|
|
726
|
+
}
|
|
722
727
|
} else if (e.key === 'Enter') {
|
|
723
728
|
e.preventDefault();
|
|
724
729
|
commitDatePendingInput();
|
|
725
730
|
}
|
|
726
731
|
},
|
|
727
|
-
[popover, commitDatePendingInput],
|
|
732
|
+
[popover, commitDatePendingInput, isEffectivelyDisabled],
|
|
728
733
|
);
|
|
729
734
|
|
|
730
735
|
// --- Time handlers ---
|
|
@@ -880,14 +885,22 @@ export function DateTimeInput({
|
|
|
880
885
|
{/* Date input */}
|
|
881
886
|
<div
|
|
882
887
|
ref={popover.triggerRef}
|
|
883
|
-
{...
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
888
|
+
{...mergeProps(
|
|
889
|
+
themeProps('date-time-input-date-segment', {
|
|
890
|
+
size,
|
|
891
|
+
status: status?.type ?? null,
|
|
892
|
+
}),
|
|
893
|
+
stylex.props(
|
|
894
|
+
inputWrapperStyles.base,
|
|
895
|
+
sizeStyles[size],
|
|
896
|
+
styles.dateWrapper,
|
|
897
|
+
isEffectivelyDisabled && inputWrapperStyles.disabled,
|
|
898
|
+
status && inputStatusBorderStyles[status.type],
|
|
899
|
+
status &&
|
|
900
|
+
!isEffectivelyDisabled &&
|
|
901
|
+
inputStatusHoverShadowStyles[status.type],
|
|
902
|
+
status && inputStatusFocusWithinStyles[status.type],
|
|
903
|
+
),
|
|
891
904
|
)}>
|
|
892
905
|
<button
|
|
893
906
|
type="button"
|
|
@@ -958,13 +971,7 @@ export function DateTimeInput({
|
|
|
958
971
|
</button>
|
|
959
972
|
)}
|
|
960
973
|
{isBusy && <Spinner size="sm" />}
|
|
961
|
-
{
|
|
962
|
-
<Icon
|
|
963
|
-
icon={statusIconMap[status.type]}
|
|
964
|
-
size="md"
|
|
965
|
-
color={statusIconColorMap[status.type]}
|
|
966
|
-
/>
|
|
967
|
-
)}
|
|
974
|
+
{statusIcon}
|
|
968
975
|
</div>
|
|
969
976
|
|
|
970
977
|
{/* Time input */}
|
|
@@ -972,14 +979,22 @@ export function DateTimeInput({
|
|
|
972
979
|
ref={timeContainerRef}
|
|
973
980
|
onClick={handleTimeWrapperClick}
|
|
974
981
|
onMouseUp={handleTimeWrapperMouseUp}
|
|
975
|
-
{...
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
982
|
+
{...mergeProps(
|
|
983
|
+
themeProps('date-time-input-time-segment', {
|
|
984
|
+
size,
|
|
985
|
+
status: status?.type ?? null,
|
|
986
|
+
}),
|
|
987
|
+
stylex.props(
|
|
988
|
+
inputWrapperStyles.base,
|
|
989
|
+
sizeStyles[size],
|
|
990
|
+
styles.timeWrapper,
|
|
991
|
+
isEffectivelyDisabled && inputWrapperStyles.disabled,
|
|
992
|
+
status && inputStatusBorderStyles[status.type],
|
|
993
|
+
status &&
|
|
994
|
+
!isEffectivelyDisabled &&
|
|
995
|
+
inputStatusHoverShadowStyles[status.type],
|
|
996
|
+
status && inputStatusFocusWithinStyles[status.type],
|
|
997
|
+
),
|
|
983
998
|
)}>
|
|
984
999
|
<div {...stylex.props(styles.icon)}>
|
|
985
1000
|
<Icon icon="clock" size="sm" color="secondary" />
|
|
@@ -1000,7 +1015,9 @@ export function DateTimeInput({
|
|
|
1000
1015
|
disabled={isEffectivelyDisabled && !showsDisabledMessage}
|
|
1001
1016
|
aria-disabled={showsDisabledMessage ? 'true' : undefined}
|
|
1002
1017
|
readOnly={showsDisabledMessage || undefined}
|
|
1003
|
-
aria-label={
|
|
1018
|
+
aria-label={
|
|
1019
|
+
timeLabel ?? t('@astryx.dateTimeInput.timeSuffix', {label})
|
|
1020
|
+
}
|
|
1004
1021
|
aria-describedby={ariaDescribedBy}
|
|
1005
1022
|
aria-required={isRequired === true ? 'true' : undefined}
|
|
1006
1023
|
aria-invalid={
|
|
@@ -111,7 +111,7 @@ export const docs = {
|
|
|
111
111
|
{ guidance: false, description: 'Use the fullscreen variant for simple confirmations; it is meant for complex content like editors or long forms.' },
|
|
112
112
|
],
|
|
113
113
|
anatomy: [
|
|
114
|
-
{name: 'Header', required: true, description: 'Title, optional subtitle, and close button. The title receives focus on open
|
|
114
|
+
{name: 'Header', required: true, description: 'Title, optional subtitle, and close button. The title receives focus on open and labels the dialog via aria-labelledby.'},
|
|
115
115
|
{name: 'Body', required: true, description: 'The main content area: text, forms, lists, or any layout.'},
|
|
116
116
|
{name: 'Footer', required: false, description: 'Action buttons like Save/Cancel or Accept/Decline, aligned to the end.'},
|
|
117
117
|
{name: 'Backdrop', required: true, description: 'Semi-transparent overlay behind the dialog that blocks page interaction.'},
|
|
@@ -133,7 +133,7 @@ export const docsZh = {
|
|
|
133
133
|
{ guidance: false, description: 'Use the fullscreen variant for simple confirmations; it is meant for complex content like editors or long forms.' },
|
|
134
134
|
],
|
|
135
135
|
anatomy: [
|
|
136
|
-
{name: 'Header', required: true, description: 'Title, optional subtitle, and close button. The title receives focus on open
|
|
136
|
+
{name: 'Header', required: true, description: 'Title, optional subtitle, and close button. The title receives focus on open and labels the dialog via aria-labelledby.'},
|
|
137
137
|
{name: 'Body', required: true, description: 'The main content area: text, forms, lists, or any layout.'},
|
|
138
138
|
{name: 'Footer', required: false, description: 'Action buttons like Save/Cancel or Accept/Decline, aligned to the end.'},
|
|
139
139
|
{name: 'Backdrop', required: true, description: 'Semi-transparent overlay behind the dialog that blocks page interaction.'},
|
|
@@ -212,10 +212,7 @@ describe('Dialog', () => {
|
|
|
212
212
|
|
|
213
213
|
it('forwards additional props to dialog element', () => {
|
|
214
214
|
render(
|
|
215
|
-
<Dialog
|
|
216
|
-
isOpen={true}
|
|
217
|
-
onOpenChange={() => {}}
|
|
218
|
-
data-testid="custom-dialog">
|
|
215
|
+
<Dialog isOpen={true} onOpenChange={() => {}} data-testid="custom-dialog">
|
|
219
216
|
Content
|
|
220
217
|
</Dialog>,
|
|
221
218
|
);
|
|
@@ -267,6 +264,82 @@ describe('Dialog', () => {
|
|
|
267
264
|
});
|
|
268
265
|
});
|
|
269
266
|
|
|
267
|
+
describe('accessible name', () => {
|
|
268
|
+
it('is labelled by the DialogHeader title by default', () => {
|
|
269
|
+
render(
|
|
270
|
+
<Dialog isOpen={true} onOpenChange={() => {}}>
|
|
271
|
+
<DialogHeader title="Dialog title" />
|
|
272
|
+
</Dialog>,
|
|
273
|
+
);
|
|
274
|
+
const dialog = screen.getByRole('dialog');
|
|
275
|
+
const heading = screen.getByRole('heading', {name: 'Dialog title'});
|
|
276
|
+
expect(heading.id).not.toBe('');
|
|
277
|
+
expect(dialog).toHaveAttribute('aria-labelledby', heading.id);
|
|
278
|
+
expect(dialog).toHaveAccessibleName('Dialog title');
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('prefers a consumer-provided aria-label over the header title', () => {
|
|
282
|
+
render(
|
|
283
|
+
<Dialog isOpen={true} onOpenChange={() => {}} aria-label="Custom name">
|
|
284
|
+
<DialogHeader title="Dialog title" />
|
|
285
|
+
</Dialog>,
|
|
286
|
+
);
|
|
287
|
+
const dialog = screen.getByRole('dialog');
|
|
288
|
+
expect(dialog).not.toHaveAttribute('aria-labelledby');
|
|
289
|
+
expect(dialog).toHaveAccessibleName('Custom name');
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('prefers a consumer-provided aria-labelledby over the header title', () => {
|
|
293
|
+
render(
|
|
294
|
+
<>
|
|
295
|
+
<span id="external-label">External name</span>
|
|
296
|
+
<Dialog
|
|
297
|
+
isOpen={true}
|
|
298
|
+
onOpenChange={() => {}}
|
|
299
|
+
aria-labelledby="external-label">
|
|
300
|
+
<DialogHeader title="Dialog title" />
|
|
301
|
+
</Dialog>
|
|
302
|
+
</>,
|
|
303
|
+
);
|
|
304
|
+
const dialog = screen.getByRole('dialog');
|
|
305
|
+
expect(dialog).toHaveAttribute('aria-labelledby', 'external-label');
|
|
306
|
+
expect(dialog).toHaveAccessibleName('External name');
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('omits aria-labelledby and warns when open with no name source', () => {
|
|
310
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
311
|
+
try {
|
|
312
|
+
render(
|
|
313
|
+
<Dialog isOpen={true} onOpenChange={() => {}}>
|
|
314
|
+
Content
|
|
315
|
+
</Dialog>,
|
|
316
|
+
);
|
|
317
|
+
const dialog = screen.getByRole('dialog');
|
|
318
|
+
expect(dialog).not.toHaveAttribute('aria-labelledby');
|
|
319
|
+
expect(warnSpy).toHaveBeenCalledTimes(1);
|
|
320
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
321
|
+
expect.stringContaining('accessible name'),
|
|
322
|
+
);
|
|
323
|
+
} finally {
|
|
324
|
+
warnSpy.mockRestore();
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it('does not warn when the header provides a title', () => {
|
|
329
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
330
|
+
try {
|
|
331
|
+
render(
|
|
332
|
+
<Dialog isOpen={true} onOpenChange={() => {}}>
|
|
333
|
+
<DialogHeader title="Dialog title" />
|
|
334
|
+
</Dialog>,
|
|
335
|
+
);
|
|
336
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
337
|
+
} finally {
|
|
338
|
+
warnSpy.mockRestore();
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
270
343
|
describe('inner flex wrapper', () => {
|
|
271
344
|
it('wraps children in a flex container for scroll support', () => {
|
|
272
345
|
render(
|
package/src/Dialog/Dialog.tsx
CHANGED
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
* - /packages/cli/templates/blocks/components/Dialog/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
useCallback,
|
|
21
|
+
useEffect,
|
|
22
|
+
useId,
|
|
23
|
+
useMemo,
|
|
24
|
+
useRef,
|
|
25
|
+
type ReactNode,
|
|
26
|
+
} from 'react';
|
|
20
27
|
import type {BaseProps} from '../BaseProps';
|
|
21
28
|
import * as stylex from '@stylexjs/stylex';
|
|
22
29
|
import {useScrollLock} from '../hooks/useScrollLock';
|
|
@@ -39,6 +46,7 @@ import {
|
|
|
39
46
|
} from '../Layout/padding.stylex';
|
|
40
47
|
import type {SpacingStep} from '../utils/types';
|
|
41
48
|
import {mergeProps, mergeRefs} from '../utils';
|
|
49
|
+
import {devWarn} from '../utils/devWarning';
|
|
42
50
|
import {DialogContext} from './DialogContext';
|
|
43
51
|
import {themeProps} from '../utils/themeProps';
|
|
44
52
|
|
|
@@ -152,7 +160,13 @@ const styles = stylex.create({
|
|
|
152
160
|
open: {
|
|
153
161
|
display: 'flex',
|
|
154
162
|
opacity: 1,
|
|
155
|
-
|
|
163
|
+
// Disable the entry keyframe animation under
|
|
164
|
+
// `prefers-reduced-motion: reduce` so the dialog appears instantly
|
|
165
|
+
// instead of translating/scaling in (same pattern as layerAnimations).
|
|
166
|
+
animationName: {
|
|
167
|
+
default: enterDirectional,
|
|
168
|
+
'@media (prefers-reduced-motion: reduce)': 'none',
|
|
169
|
+
},
|
|
156
170
|
},
|
|
157
171
|
// Backdrop using ::backdrop pseudo-element
|
|
158
172
|
backdrop: {
|
|
@@ -312,6 +326,9 @@ export interface DialogProps extends BaseProps<HTMLDialogElement> {
|
|
|
312
326
|
*
|
|
313
327
|
* Designed to be used with Layout as its child for structured content.
|
|
314
328
|
* Uses the browser's built-in modal behavior for optimal accessibility.
|
|
329
|
+
* When a DialogHeader is rendered inside, its title automatically names the
|
|
330
|
+
* dialog via aria-labelledby; pass `aria-label` or `aria-labelledby` to
|
|
331
|
+
* override.
|
|
315
332
|
*
|
|
316
333
|
* @example
|
|
317
334
|
* ```
|
|
@@ -348,10 +365,47 @@ export function Dialog({
|
|
|
348
365
|
const paddingToken = spacingStepToToken[effectivePadding] as SpacingToken;
|
|
349
366
|
|
|
350
367
|
const isFullscreen = variant === 'fullscreen';
|
|
351
|
-
|
|
368
|
+
|
|
369
|
+
// Default accessible name: publish a title id through DialogContext so a
|
|
370
|
+
// DialogHeader applies it to its heading (mirrors AlertDialog's explicit
|
|
371
|
+
// useId wiring). Whether to emit the default aria-labelledby is decided
|
|
372
|
+
// imperatively in the callback ref below by checking whether the title
|
|
373
|
+
// element actually rendered — so a dialog with no header never points at a
|
|
374
|
+
// missing id, and we avoid the extra render a registration-via-state effect
|
|
375
|
+
// would cost at the dialog level.
|
|
376
|
+
const titleId = useId();
|
|
377
|
+
|
|
378
|
+
const dialogContextValue = useMemo(
|
|
379
|
+
() => ({isInline, titleId}),
|
|
380
|
+
[isInline, titleId],
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Consumer-provided labels always win over the DialogHeader default.
|
|
384
|
+
const hasConsumerName =
|
|
385
|
+
props['aria-label'] != null || props['aria-labelledby'] != null;
|
|
352
386
|
|
|
353
387
|
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
354
388
|
|
|
389
|
+
// Callback ref on the <dialog>: sync the default aria-labelledby from the
|
|
390
|
+
// DialogHeader title (if one rendered) in the same commit, with no second
|
|
391
|
+
// render. Consumer aria-label/aria-labelledby win — when present we leave
|
|
392
|
+
// the attribute to the {...safeProps} spread and never touch it here.
|
|
393
|
+
const attachDialog = useCallback(
|
|
394
|
+
(node: HTMLDialogElement | null) => {
|
|
395
|
+
dialogRef.current = node;
|
|
396
|
+
if (!node || hasConsumerName) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const hasTitle = node.querySelector(`#${CSS.escape(titleId)}`) != null;
|
|
400
|
+
if (hasTitle) {
|
|
401
|
+
node.setAttribute('aria-labelledby', titleId);
|
|
402
|
+
} else {
|
|
403
|
+
node.removeAttribute('aria-labelledby');
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
[titleId, hasConsumerName],
|
|
407
|
+
);
|
|
408
|
+
|
|
355
409
|
// Capture the element that was focused when the dialog opened,
|
|
356
410
|
// for directional animation origin and focus restoration on close.
|
|
357
411
|
const triggerElementRef = useRef<HTMLElement | null>(null);
|
|
@@ -440,6 +494,29 @@ export function Dialog({
|
|
|
440
494
|
return () => dialog.removeEventListener('keydown', handleKeyDown);
|
|
441
495
|
}, [isOpen, isInline, allowEscape, onOpenChange]);
|
|
442
496
|
|
|
497
|
+
// Dev-time guardrail: an open modal should always have an accessible name.
|
|
498
|
+
// The header-title check reads the DOM, so this stays in an effect; the ref
|
|
499
|
+
// keeps it to one warning per component instance.
|
|
500
|
+
const warnedUnnamedDialogRef = useRef(false);
|
|
501
|
+
useEffect(() => {
|
|
502
|
+
const hasHeaderTitle =
|
|
503
|
+
dialogRef.current?.querySelector(`#${CSS.escape(titleId)}`) != null;
|
|
504
|
+
if (
|
|
505
|
+
isOpen &&
|
|
506
|
+
!isInline &&
|
|
507
|
+
!hasConsumerName &&
|
|
508
|
+
!hasHeaderTitle &&
|
|
509
|
+
!warnedUnnamedDialogRef.current
|
|
510
|
+
) {
|
|
511
|
+
warnedUnnamedDialogRef.current = true;
|
|
512
|
+
devWarn(
|
|
513
|
+
'Dialog',
|
|
514
|
+
'open dialog has no accessible name. Add a DialogHeader ' +
|
|
515
|
+
'with a `title`, or pass `aria-label`/`aria-labelledby`.',
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
}, [isOpen, isInline, hasConsumerName, titleId]);
|
|
519
|
+
|
|
443
520
|
// Handle backdrop click — when the user clicks the ::backdrop pseudo-element,
|
|
444
521
|
// the event target is the <dialog> element itself; clicks on child content
|
|
445
522
|
// always target the child. This avoids false positives from native browser
|
|
@@ -531,7 +608,11 @@ export function Dialog({
|
|
|
531
608
|
),
|
|
532
609
|
className,
|
|
533
610
|
style,
|
|
534
|
-
)}
|
|
611
|
+
)}
|
|
612
|
+
data-testid={
|
|
613
|
+
(props as Record<string, unknown>)['data-testid'] as
|
|
614
|
+
string | undefined
|
|
615
|
+
}>
|
|
535
616
|
{innerContent}
|
|
536
617
|
</div>
|
|
537
618
|
);
|
|
@@ -541,7 +622,7 @@ export function Dialog({
|
|
|
541
622
|
|
|
542
623
|
return (
|
|
543
624
|
<dialog
|
|
544
|
-
ref={mergeRefs(ref,
|
|
625
|
+
ref={mergeRefs(ref, attachDialog)}
|
|
545
626
|
{...safeProps}
|
|
546
627
|
{...mergeProps(
|
|
547
628
|
themeProps('dialog', {variant}),
|
|
@@ -566,6 +647,9 @@ export function Dialog({
|
|
|
566
647
|
onClick={handleClick}
|
|
567
648
|
onCancel={handleCancel}
|
|
568
649
|
aria-modal="true"
|
|
650
|
+
// The default aria-labelledby (from a DialogHeader title) is set
|
|
651
|
+
// imperatively in `attachDialog`; a consumer-provided aria-labelledby
|
|
652
|
+
// flows through {...safeProps} above and wins.
|
|
569
653
|
{...(purpose === 'required' ? {role: 'alertdialog'} : undefined)}>
|
|
570
654
|
{innerContent}
|
|
571
655
|
</dialog>
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @file DialogContext.ts
|
|
7
7
|
* @input React context
|
|
8
|
-
* @output Internal dialog context for child focus behavior
|
|
9
|
-
* @position Dialog internals; consumed by focus-managing children
|
|
8
|
+
* @output Internal dialog context for child focus behavior and default labelling
|
|
9
|
+
* @position Dialog internals; consumed by focus-managing children and DialogHeader
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {createContext, use} from 'react';
|
|
@@ -14,6 +14,13 @@ import {createContext, use} from 'react';
|
|
|
14
14
|
export interface DialogContextValue {
|
|
15
15
|
/** Whether the dialog is rendered inline for docs/showcases. */
|
|
16
16
|
isInline: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Id the DialogHeader title should render with so the dialog can name
|
|
19
|
+
* itself via aria-labelledby. The dialog detects the title element's
|
|
20
|
+
* presence directly (via a callback ref), so it only emits aria-labelledby
|
|
21
|
+
* when the title actually rendered — never pointing at a nonexistent id.
|
|
22
|
+
*/
|
|
23
|
+
titleId?: string;
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
export const DialogContext = createContext<DialogContextValue | null>(null);
|
|
@@ -12,7 +12,7 @@ export const docs = {
|
|
|
12
12
|
{
|
|
13
13
|
name: 'title',
|
|
14
14
|
type: 'string',
|
|
15
|
-
description: 'Dialog title (receives focus on open).',
|
|
15
|
+
description: 'Dialog title (receives focus on open and labels the dialog via aria-labelledby).',
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
name: 'subtitle',
|
|
@@ -158,7 +158,7 @@ export const docsDense = {
|
|
|
158
158
|
displayName: 'Dialog Header',
|
|
159
159
|
description: 'dialog header w/ title, optional subtitle, close button, start/end content slots',
|
|
160
160
|
propDescriptions: {
|
|
161
|
-
title: 'dialog title (
|
|
161
|
+
title: 'dialog title (focused on open; labels dialog via aria-labelledby)',
|
|
162
162
|
subtitle: 'subtitle below title',
|
|
163
163
|
onOpenChange: 'close button callback (omit=no button)',
|
|
164
164
|
startContent: 'content before title (e.g. back button)',
|