@astryxdesign/core 0.5.2-canary.2da7a39 → 0.5.2-canary.2e51213
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/dist/AppShell/AppShell.d.ts +2 -2
- package/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +10 -7
- package/dist/Banner/Banner.d.ts +5 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +7 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +3 -2
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +22 -15
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +2 -2
- package/dist/Chat/ChatComposer.d.ts +2 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +21 -2
- package/dist/Chat/ChatToolCalls.d.ts +1 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/Chat/ChatToolCalls.js +12 -34
- package/dist/Chat/useChatNewMessages.js +3 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts +5 -3
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +47 -13
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +269 -162
- package/dist/DateTimeInput/NativeDateSegment.d.ts +24 -0
- package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeDateSegment.js +235 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts +30 -0
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -0
- package/dist/DateTimeInput/NativeTimeSegment.js +248 -0
- package/dist/DateTimeInput/index.d.ts +1 -1
- package/dist/DateTimeInput/index.d.ts.map +1 -1
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +95 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -0
- package/dist/DateTimeInput/nativePickerSegmentStyles.js +103 -0
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +2 -4
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/Field.js +10 -4
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +3 -5
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +4 -2
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +2 -4
- package/dist/Layout/Layout.d.ts +7 -8
- package/dist/Layout/Layout.d.ts.map +1 -1
- package/dist/Layout/Layout.js +7 -8
- package/dist/MultiSelector/MultiSelector.d.ts +11 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +89 -45
- package/dist/RadioList/RadioListItem.d.ts +30 -5
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +17 -4
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +102 -44
- package/dist/Resizable/index.d.ts +2 -0
- package/dist/Resizable/index.d.ts.map +1 -1
- package/dist/Resizable/index.js +1 -0
- package/dist/Resizable/useResizable.d.ts +89 -8
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +521 -38
- package/dist/Resizable/utils.d.ts +35 -0
- package/dist/Resizable/utils.d.ts.map +1 -0
- package/dist/Resizable/utils.js +27 -0
- package/dist/Selector/Selector.d.ts +10 -0
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +105 -57
- package/dist/Selector/useSelectorPresentation.d.ts +1 -0
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +17 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +3 -5
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +9 -10
- package/dist/Stepper/Step.d.ts +2 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +75 -11
- package/dist/Stepper/Stepper.d.ts.map +1 -1
- package/dist/Stepper/Stepper.js +1 -0
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +2 -3
- package/dist/Table/index.d.ts +16 -1
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +4 -0
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +8 -9
- package/dist/Table/plugins/rowStatus/index.d.ts +1 -1
- package/dist/Table/plugins/rowStatus/index.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts +11 -30
- package/dist/Table/plugins/rowStatus/useTableRowStatus.d.ts.map +1 -1
- package/dist/Table/plugins/rowStatus/useTableRowStatus.js +108 -62
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +9 -1
- package/dist/Text/useTruncation.d.ts +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +8 -7
- package/dist/TimeInput/TimeInput.d.ts +16 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +98 -60
- package/dist/TimeInput/index.d.ts +1 -1
- package/dist/TimeInput/index.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.d.ts +2 -2
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +4 -145
- package/dist/Timestamp/formatRelativeTime.d.ts +20 -0
- package/dist/Timestamp/formatRelativeTime.d.ts.map +1 -0
- package/dist/Timestamp/formatRelativeTime.js +81 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +125 -77
- package/dist/Tokenizer/Tokenizer.d.ts +0 -38
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +94 -26
- package/dist/Tokenizer/useEndLaneReserve.d.ts +31 -0
- package/dist/Tokenizer/useEndLaneReserve.d.ts.map +1 -0
- package/dist/Tokenizer/useEndLaneReserve.js +136 -0
- package/dist/Tooltip/useTooltip.d.ts +1 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +53 -42
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +85 -30
- package/dist/Typeahead/Typeahead.d.ts +0 -21
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +108 -67
- package/dist/Typeahead/busyIndicatorLane.d.ts +62 -0
- package/dist/Typeahead/busyIndicatorLane.d.ts.map +1 -0
- package/dist/Typeahead/busyIndicatorLane.js +98 -0
- package/dist/astryx.css +25 -7
- package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
- package/dist/hooks/useFocusReturnVisibility.js +3 -5
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts +2 -2
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +11 -11
- package/dist/hooks/useScrollOverflow.d.ts.map +1 -1
- package/dist/hooks/useScrollOverflow.js +7 -4
- package/dist/theme/defineTheme.d.ts +13 -0
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +7 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +1 -1
- package/dist/theme/localTokens.d.ts +18 -0
- package/dist/theme/localTokens.d.ts.map +1 -0
- package/dist/theme/localTokens.js +162 -0
- package/dist/utils/interactionModality.d.ts +6 -28
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +72 -37
- package/dist/utils/sharedResizeObserver.d.ts +17 -9
- package/dist/utils/sharedResizeObserver.d.ts.map +1 -1
- package/dist/utils/sharedResizeObserver.js +54 -12
- package/locales/en.json +8 -0
- package/locales/pseudo.json +6 -0
- package/package.json +7 -2
- package/src/AlertDialog/useImperativeAlertDialog.test.tsx +163 -0
- package/src/AppShell/AppShell.doc.mjs +4 -3
- package/src/AppShell/AppShell.test.tsx +21 -0
- package/src/AppShell/AppShell.tsx +12 -7
- package/src/Banner/Banner.doc.mjs +5 -1
- package/src/Banner/Banner.tsx +12 -1
- package/src/BottomSheet/BottomSheet.doc.mjs +31 -0
- package/src/BottomSheet/BottomSheet.spec.md +178 -0
- package/src/Breadcrumbs/BreadcrumbItem.tsx +18 -9
- package/src/Breadcrumbs/Breadcrumbs.doc.mjs +4 -1
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +12 -0
- package/src/Button/Button.doc.mjs +56 -0
- package/src/ButtonGroup/ButtonGroup.doc.mjs +47 -0
- package/src/Calendar/hooks/useCalendarConstraints.test.ts +153 -0
- package/src/Calendar/hooks/useCalendarDays.test.ts +265 -0
- package/src/Calendar/hooks/useCalendarNavigation.test.ts +252 -0
- package/src/Carousel/Carousel.test.tsx +83 -0
- package/src/Carousel/Carousel.tsx +8 -2
- package/src/Chat/ChatComposer.doc.mjs +7 -4
- package/src/Chat/ChatComposer.test.tsx +84 -2
- package/src/Chat/ChatComposer.tsx +45 -3
- package/src/Chat/ChatSendButton.test.tsx +189 -0
- package/src/Chat/ChatToolCalls.doc.mjs +1 -1
- package/src/Chat/ChatToolCalls.test.tsx +33 -1
- package/src/Chat/ChatToolCalls.tsx +13 -34
- package/src/Chat/useChatNewMessages.ts +3 -3
- package/src/Chat/useChatPasteAsToken.test.ts +191 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +172 -31
- package/src/CheckboxList/CheckboxList.spec.md +215 -0
- package/src/CheckboxList/CheckboxList.test.tsx +45 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +11 -9
- package/src/CheckboxList/CheckboxListItem.tsx +5 -3
- package/src/Collapsible/useCollapsible.test.tsx +236 -0
- package/src/CommandPalette/CommandPalette.doc.mjs +72 -0
- package/src/CommandPalette/CommandPalette.spec.md +224 -0
- package/src/CommandPalette/CommandPaletteEmpty.test.tsx +101 -0
- package/src/ComplexSelector/ComplexSelector.doc.mjs +42 -0
- package/src/ComplexSelector/ComplexSelector.spec.md +190 -0
- package/src/ContextMenu/ContextMenu.doc.mjs +48 -0
- package/src/ContextMenu/ContextMenu.spec.md +207 -0
- package/src/DateTimeInput/DateTimeInput.doc.mjs +43 -23
- package/src/DateTimeInput/DateTimeInput.tsx +388 -181
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +10 -2
- package/src/DateTimeInput/NativeDateSegment.tsx +308 -0
- package/src/DateTimeInput/NativePickerSegments.test.tsx +626 -0
- package/src/DateTimeInput/NativeTimeSegment.tsx +331 -0
- package/src/DateTimeInput/index.ts +1 -0
- package/src/DateTimeInput/nativePickerSegmentStyles.ts +120 -0
- package/src/Divider/Divider.doc.mjs +24 -0
- package/src/Divider/Divider.spec.md +157 -0
- package/src/DropdownMenu/DropdownMenu.doc.mjs +104 -0
- package/src/DropdownMenu/DropdownMenu.spec.md +246 -0
- package/src/DropdownMenu/DropdownMenu.tsx +2 -4
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/Field.test.tsx +39 -0
- package/src/Field/Field.tsx +18 -1
- package/src/Field/InputClearButton.test.tsx +68 -6
- package/src/Field/PanelSearchInput.tsx +3 -5
- package/src/FieldStatus/FieldStatus.doc.mjs +21 -0
- package/src/FieldStatus/FieldStatus.spec.md +213 -0
- package/src/FieldStatus/FieldStatus.test.tsx +17 -0
- package/src/FieldStatus/FieldStatus.tsx +7 -2
- package/src/Grid/Grid.doc.mjs +19 -0
- package/src/Grid/Grid.spec.md +162 -0
- package/src/Icon/Icon.doc.mjs +196 -48
- package/src/Icon/Icon.spec.md +192 -0
- package/src/IconButton/IconButton.doc.mjs +38 -0
- package/src/Kbd/Kbd.doc.mjs +18 -0
- package/src/Kbd/Kbd.spec.md +142 -0
- package/src/Layer/useTouchTrigger.ts +2 -4
- package/src/Layout/Layout.doc.mjs +57 -17
- package/src/Layout/Layout.spec.md +235 -0
- package/src/Layout/Layout.test.tsx +1 -1
- package/src/Layout/Layout.tsx +7 -8
- package/src/Layout/LayoutHeader.doc.mjs +9 -0
- package/src/Layout/LayoutPanel.doc.mjs +4 -3
- package/src/Lightbox/Lightbox.doc.mjs +149 -33
- package/src/Lightbox/Lightbox.spec.md +198 -0
- package/src/Lightbox/useLightbox.test.tsx +263 -0
- package/src/Markdown/Markdown.doc.mjs +60 -0
- package/src/Markdown/Markdown.spec.md +207 -0
- package/src/MobileNav/MobileNav.doc.mjs +140 -32
- package/src/MobileNav/MobileNav.spec.md +209 -0
- package/src/MoreMenu/MoreMenu.doc.mjs +42 -0
- package/src/MoreMenu/MoreMenu.spec.md +222 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +124 -1
- package/src/MultiSelector/MultiSelector.spec.md +293 -0
- package/src/MultiSelector/MultiSelector.test.tsx +305 -2
- package/src/MultiSelector/MultiSelector.tsx +124 -55
- package/src/NavIcon/NavIcon.doc.mjs +17 -0
- package/src/NavIcon/NavIcon.spec.md +134 -0
- package/src/NavMenu/NavHeadingMenu.spec.md +210 -0
- package/src/NavMenu/NavMenu.doc.mjs +37 -0
- package/src/Outline/Outline.doc.mjs +35 -0
- package/src/Outline/Outline.spec.md +162 -0
- package/src/OverflowList/OverflowList.doc.mjs +24 -0
- package/src/OverflowList/OverflowList.spec.md +157 -0
- package/src/Pagination/Pagination.doc.mjs +74 -0
- package/src/Pagination/Pagination.spec.md +226 -0
- package/src/Popover/Popover.doc.mjs +264 -65
- package/src/Popover/Popover.spec.md +421 -0
- package/src/Popover/usePopover.doc.mjs +208 -33
- package/src/PowerSearch/PowerSearch.spec.md +291 -0
- package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +253 -0
- package/src/PowerSearch/PowerSearchToken.test.tsx +228 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +198 -38
- package/src/ProgressBar/ProgressBar.spec.md +261 -0
- package/src/RadioList/RadioList.test.tsx +136 -2
- package/src/RadioList/RadioListItem.doc.mjs +30 -11
- package/src/RadioList/RadioListItem.tsx +44 -8
- package/src/Resizable/Resizable.doc.mjs +130 -24
- package/src/Resizable/Resizable.spec.md +246 -0
- package/src/Resizable/ResizeHandle.test.tsx +177 -56
- package/src/Resizable/ResizeHandle.tsx +128 -45
- package/src/Resizable/index.ts +2 -0
- package/src/Resizable/shippedDirections.test.ts +462 -0
- package/src/Resizable/useResizable.doc.mjs +124 -29
- package/src/Resizable/useResizable.test.ts +1277 -3
- package/src/Resizable/useResizable.ts +760 -48
- package/src/Resizable/utils.test.ts +74 -0
- package/src/Resizable/utils.ts +35 -0
- package/src/Section/Section.doc.mjs +17 -0
- package/src/Section/Section.spec.md +139 -0
- package/src/SegmentedControl/SegmentedControl.doc.mjs +83 -0
- package/src/SegmentedControl/SegmentedControl.spec.md +152 -0
- package/src/Selector/Selector.doc.mjs +133 -97
- package/src/Selector/Selector.spec.md +300 -0
- package/src/Selector/Selector.test.tsx +318 -1
- package/src/Selector/Selector.tsx +127 -60
- package/src/Selector/useSelectorPresentation.ts +24 -4
- package/src/SideNav/SideNav.test.tsx +3 -3
- package/src/SideNav/SideNavCollapseButton.doc.mjs +8 -0
- package/src/SideNav/SideNavItem.doc.mjs +1 -1
- package/src/Skeleton/Skeleton.doc.mjs +12 -0
- package/src/Skeleton/Skeleton.spec.md +127 -0
- package/src/Slider/Slider.doc.mjs +184 -30
- package/src/Slider/Slider.spec.md +224 -0
- package/src/Slider/Slider.tsx +2 -5
- package/src/Spinner/Spinner.doc.mjs +5 -5
- package/src/Spinner/Spinner.test.tsx +32 -7
- package/src/Spinner/Spinner.tsx +46 -14
- package/src/Stack/Stack.doc.mjs +22 -0
- package/src/Stack/Stack.spec.md +155 -0
- package/src/StatusDot/StatusDot.doc.mjs +17 -0
- package/src/StatusDot/StatusDot.spec.md +138 -0
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +118 -5
- package/src/Stepper/Stepper.doc.mjs +51 -1
- package/src/Stepper/Stepper.spec.md +245 -0
- package/src/Stepper/Stepper.test.tsx +315 -0
- package/src/Stepper/Stepper.tsx +8 -0
- package/src/Switch/Switch.doc.mjs +40 -0
- package/src/Switch/Switch.spec.md +175 -0
- package/src/TabList/TabList.tsx +2 -3
- package/src/Table/Table.doc.mjs +102 -24
- package/src/Table/Table.perf.test.tsx +51 -1
- package/src/Table/Table.spec.md +325 -0
- package/src/Table/TableHeaderCell.test.tsx +291 -0
- package/src/Table/index.ts +19 -4
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -12
- package/src/Table/plugins/filtering/useTableFilterState.test.tsx +143 -0
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +2 -1
- package/src/Table/plugins/rowStatus/index.ts +1 -4
- package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +92 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +354 -0
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +431 -56
- package/src/Table/plugins/rowStatus/useTableRowStatus.tsx +155 -84
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +72 -0
- package/src/Table/plugins/sortable/useTableSortable.tsx +18 -1
- package/src/Table/useTableGroupedRows.doc.mjs +2 -2
- package/src/Table/useTableRowStatus.doc.mjs +5 -5
- package/src/Text/Text.doc.mjs +190 -43
- package/src/Text/Text.spec.md +206 -0
- package/src/Text/useTruncation.ts +8 -7
- package/src/TextArea/TextArea.doc.mjs +255 -45
- package/src/TextArea/TextArea.spec.md +205 -0
- package/src/TimeInput/NativeTimeInput.test.tsx +269 -0
- package/src/TimeInput/TimeInput.doc.mjs +47 -23
- package/src/TimeInput/TimeInput.tsx +109 -50
- package/src/TimeInput/index.ts +1 -0
- package/src/Timestamp/Timestamp.doc.mjs +2 -2
- package/src/Timestamp/Timestamp.test.tsx +75 -3
- package/src/Timestamp/Timestamp.tsx +7 -153
- package/src/Timestamp/formatRelativeTime.ts +96 -0
- package/src/Toast/ToastViewport.test.tsx +194 -0
- package/src/Toast/ToastViewport.tsx +136 -58
- package/src/ToggleButton/ToggleButton.doc.mjs +56 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +2 -0
- package/src/Tokenizer/Tokenizer.spec.md +293 -0
- package/src/Tokenizer/Tokenizer.test.tsx +335 -1
- package/src/Tokenizer/Tokenizer.tsx +129 -46
- package/src/Tokenizer/useEndLaneReserve.ts +146 -0
- package/src/Toolbar/Toolbar.doc.mjs +19 -0
- package/src/Toolbar/Toolbar.spec.md +174 -0
- package/src/Tooltip/Tooltip.doc.mjs +17 -0
- package/src/Tooltip/Tooltip.spec.md +142 -0
- package/src/Tooltip/Tooltip.test.tsx +21 -1
- package/src/Tooltip/useTooltip.test.tsx +318 -0
- package/src/Tooltip/useTooltip.tsx +60 -39
- package/src/TreeList/TreeList.doc.mjs +58 -0
- package/src/TreeList/TreeList.spec.md +224 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -25
- package/src/Typeahead/Typeahead.doc.mjs +89 -1
- package/src/Typeahead/Typeahead.spec.md +257 -0
- package/src/Typeahead/Typeahead.test.tsx +502 -1
- package/src/Typeahead/Typeahead.tsx +187 -69
- package/src/Typeahead/TypeaheadItem.test.tsx +93 -2
- package/src/Typeahead/busyIndicatorLane.tsx +109 -0
- package/src/__tests__/stylexDeclarations.ts +51 -0
- package/src/hooks/useFocusReturnVisibility.ts +3 -5
- package/src/hooks/useOverflow.ts +11 -11
- package/src/hooks/useScrollLock.test.ts +103 -0
- package/src/hooks/useScrollOverflow.ts +7 -4
- package/src/i18n/useTranslator.test.tsx +197 -0
- package/src/theme/defineTheme.test.ts +227 -0
- package/src/theme/defineTheme.ts +30 -0
- package/src/theme/derivedVarRegistry.test.ts +6 -0
- package/src/theme/generateThemeRules.ts +4 -1
- package/src/theme/localTokens.ts +272 -0
- package/src/theme/themingTargets.test.ts +126 -28
- package/src/utils/interactionModality.test.ts +83 -0
- package/src/utils/interactionModality.ts +88 -36
- package/src/utils/sharedResizeObserver.test.ts +124 -5
- package/src/utils/sharedResizeObserver.ts +60 -14
|
@@ -101,6 +101,15 @@ const styles = {
|
|
|
101
101
|
k3aq6I: "x1c071of x1pdlv7q",
|
|
102
102
|
$$css: true
|
|
103
103
|
},
|
|
104
|
+
triggerReadOnly: {
|
|
105
|
+
kkrTdU: "xt0e3qv",
|
|
106
|
+
$$css: true
|
|
107
|
+
},
|
|
108
|
+
triggerGhostReadOnly: {
|
|
109
|
+
kKwaWg: "x18o3ruo",
|
|
110
|
+
k3aq6I: "x1c071of x1pdlv7q",
|
|
111
|
+
$$css: true
|
|
112
|
+
},
|
|
104
113
|
statusButton: {
|
|
105
114
|
k1xSpc: "x78zum5",
|
|
106
115
|
kGNEyG: "x6s0dn4",
|
|
@@ -261,6 +270,7 @@ export function MultiSelector({
|
|
|
261
270
|
isOptional = false,
|
|
262
271
|
isRequired = false,
|
|
263
272
|
isDisabled = false,
|
|
273
|
+
isReadOnly = false,
|
|
264
274
|
disabledMessage,
|
|
265
275
|
options,
|
|
266
276
|
value,
|
|
@@ -308,11 +318,13 @@ export function MultiSelector({
|
|
|
308
318
|
const emptySearchText = emptySearchTextFromProps ?? t('@astryx.multiSelector.emptySearchResults');
|
|
309
319
|
const size = useSize(sizeProp, 'md');
|
|
310
320
|
const effectiveStatusVariant = variant === 'ghost' && statusVariant === 'attached' ? 'detached' : statusVariant;
|
|
321
|
+
const isEffectivelyReadOnly = isReadOnly && !isDisabled;
|
|
311
322
|
const triggerId = useId();
|
|
312
323
|
const listboxId = useId();
|
|
313
324
|
const descriptionId = useId();
|
|
314
325
|
const statusMessageId = useId();
|
|
315
326
|
const inputLabelId = useId();
|
|
327
|
+
const readOnlyDescriptionId = useId();
|
|
316
328
|
const searchId = useId();
|
|
317
329
|
const triggerRef = useRef(null);
|
|
318
330
|
const searchRef = useRef(null);
|
|
@@ -351,7 +363,7 @@ export function MultiSelector({
|
|
|
351
363
|
const {
|
|
352
364
|
ariaLabelledBy,
|
|
353
365
|
ariaDescribedBy
|
|
354
|
-
} = getInputARIA(inputLabelId, [description ? descriptionId : null, !inputGroup && effectiveStatusVariant !== 'tooltip' && status?.message ? statusMessageId : null, effectiveStatusVariant === 'tooltip' && status?.message ? statusTooltip.describedBy : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null], inputGroup);
|
|
366
|
+
} = getInputARIA(inputLabelId, [description ? descriptionId : null, !inputGroup && effectiveStatusVariant !== 'tooltip' && status?.message ? statusMessageId : null, effectiveStatusVariant === 'tooltip' && status?.message ? statusTooltip.describedBy : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null, isEffectivelyReadOnly ? readOnlyDescriptionId : null], inputGroup);
|
|
355
367
|
|
|
356
368
|
// Flatten options for keyboard navigation
|
|
357
369
|
const selectableItems = useMemo(() => getSelectableOptions(options), [options]);
|
|
@@ -457,16 +469,27 @@ export function MultiSelector({
|
|
|
457
469
|
const {
|
|
458
470
|
popover
|
|
459
471
|
} = surface;
|
|
472
|
+
const hideSurface = surface.hide;
|
|
473
|
+
const isSurfaceOpen = surface.isOpen;
|
|
460
474
|
const keepOpenProps = useKeepLayerOpenProps(popover.id, popover.isOpen);
|
|
461
475
|
|
|
462
|
-
// Open dropdown on mount when isDefaultOpen is true
|
|
476
|
+
// Open dropdown on mount when isDefaultOpen is true and interaction is allowed.
|
|
463
477
|
useEffect(() => {
|
|
464
|
-
if (isDefaultOpen) {
|
|
478
|
+
if (isDefaultOpen && !isEffectivelyReadOnly) {
|
|
465
479
|
surface.show();
|
|
466
480
|
}
|
|
467
481
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- mount-only: isDefaultOpen is not reactive
|
|
468
482
|
}, []);
|
|
469
483
|
|
|
484
|
+
// Read-only is controlled by caller policy, so an already-open surface must
|
|
485
|
+
// close when that policy changes. The presentation controller keeps a sheet
|
|
486
|
+
// mounted through its exit and lets BottomSheet return final focus.
|
|
487
|
+
useEffect(() => {
|
|
488
|
+
if (isEffectivelyReadOnly && isSurfaceOpen) {
|
|
489
|
+
hideSurface();
|
|
490
|
+
}
|
|
491
|
+
}, [isEffectivelyReadOnly, isSurfaceOpen, hideSurface]);
|
|
492
|
+
|
|
470
493
|
// Announce the filtered result count from the query-change handler (matching
|
|
471
494
|
// BaseTypeahead) rather than a reactive effect: computing the count for the
|
|
472
495
|
// next query here fires the announcement exactly once per keystroke and does
|
|
@@ -595,7 +618,7 @@ export function MultiSelector({
|
|
|
595
618
|
} = useMultiCombobox({
|
|
596
619
|
wasJustDismissed: surface.wasJustDismissed,
|
|
597
620
|
selectableItems: sortedItems,
|
|
598
|
-
isDisabled,
|
|
621
|
+
isDisabled: isDisabled || isEffectivelyReadOnly,
|
|
599
622
|
isOpen: surface.isOpen,
|
|
600
623
|
hasSearch,
|
|
601
624
|
onOpen: useCallback(() => {
|
|
@@ -975,19 +998,48 @@ export function MultiSelector({
|
|
|
975
998
|
children: renderOptions()
|
|
976
999
|
})
|
|
977
1000
|
});
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
})
|
|
1001
|
+
let selectionSurface = null;
|
|
1002
|
+
if (surface.activePresentation === 'bottom-sheet') {
|
|
1003
|
+
if (!isEffectivelyReadOnly || surface.isSheetPresented) {
|
|
1004
|
+
selectionSurface = /*#__PURE__*/_jsx(SelectorBottomSheet, {
|
|
1005
|
+
isOpen: surface.isSheetOpen,
|
|
1006
|
+
onOpenChange: surface.onSheetOpenChange,
|
|
1007
|
+
finalFocusRef: triggerRef,
|
|
1008
|
+
initialFocusRef: hasSearch ? searchRef : listboxRef,
|
|
1009
|
+
label: label,
|
|
1010
|
+
children: panelContent
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
} else if (!isEffectivelyReadOnly) {
|
|
1014
|
+
selectionSurface = popover.render(panelContent, {
|
|
1015
|
+
placement: 'below',
|
|
1016
|
+
alignment: 'start',
|
|
1017
|
+
offset: spacingVars['--spacing-1'],
|
|
1018
|
+
xstyle: styles.popover
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
const triggerSharedProps = {
|
|
1022
|
+
id: triggerId,
|
|
1023
|
+
'aria-describedby': ariaDescribedBy,
|
|
1024
|
+
'aria-labelledby': ariaLabelledBy,
|
|
1025
|
+
'aria-required': isEffectivelyRequired ? 'true' : undefined,
|
|
1026
|
+
'aria-invalid': status?.type === 'error' ? 'true' : undefined,
|
|
1027
|
+
'aria-busy': isBusy || undefined,
|
|
1028
|
+
onKeyDown,
|
|
1029
|
+
onFocus: event => {
|
|
1030
|
+
onFocus?.(event);
|
|
1031
|
+
surface.onTriggerFocus(event);
|
|
1032
|
+
},
|
|
1033
|
+
tabIndex: isDisabled && !showsDisabledMessage ? -1 : 0,
|
|
1034
|
+
...{
|
|
1035
|
+
0: {
|
|
1036
|
+
className: "x78zum5 x6s0dn4 x1qughib x1txdalj x1iyjqo2 xs83m0k x1r8uery xeuugli x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x15bjb6t x1heor9g x1ypdohk x16khyan x1a2a7pz xh6dtrn"
|
|
1037
|
+
},
|
|
1038
|
+
1: {
|
|
1039
|
+
className: "x78zum5 x6s0dn4 x1qughib x1txdalj x1iyjqo2 xs83m0k x1r8uery xeuugli x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x15bjb6t x1heor9g x1a2a7pz xh6dtrn xt0e3qv"
|
|
1040
|
+
}
|
|
1041
|
+
}[!!isEffectivelyReadOnly << 0]
|
|
1042
|
+
};
|
|
991
1043
|
const multiSelectorContent = /*#__PURE__*/_jsxs(_Fragment, {
|
|
992
1044
|
children: [/*#__PURE__*/_jsxs("div", {
|
|
993
1045
|
ref: el => {
|
|
@@ -1003,47 +1055,39 @@ export function MultiSelector({
|
|
|
1003
1055
|
variant,
|
|
1004
1056
|
size,
|
|
1005
1057
|
status: status?.type ?? null,
|
|
1006
|
-
disabled: isDisabled ? 'disabled' : null
|
|
1007
|
-
|
|
1058
|
+
disabled: isDisabled ? 'disabled' : null,
|
|
1059
|
+
readonly: isEffectivelyReadOnly ? 'readonly' : null
|
|
1060
|
+
}), stylex.props(inputWrapperStyles.base, styles.triggerContainer, sizeStyles[size], variant === 'ghost' && styles.triggerGhost, variant === 'ghost' && interactionOverlayStyles.backgroundImage, variant === 'ghost' && focusOutlineStyles.focusWithin, surface.isTriggerFocusRingSuppressed && selectorPresentationStyles.pointerRestoredFocus, isDisabled && inputWrapperStyles.disabled, isEffectivelyReadOnly && styles.triggerReadOnly, variant === 'ghost' && isDisabled && styles.triggerGhostDisabled, variant === 'ghost' && isEffectivelyReadOnly && styles.triggerGhostReadOnly, optimisticValue.length === 0 && styles.triggerPlaceholder, variant !== 'ghost' && status && inputStatusBorderStyles[status.type], variant !== 'ghost' && status && !isDisabled && inputStatusHoverShadowStyles[status.type], variant !== 'ghost' && inputGroup && groupStyles.inGroup, xstyle), className, style),
|
|
1008
1061
|
children: [startIcon && renderIconSlot(startIcon, {
|
|
1009
1062
|
size: 'sm',
|
|
1010
1063
|
color: 'secondary'
|
|
1011
1064
|
}), inputGroup && /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
1012
1065
|
id: inputLabelId,
|
|
1013
1066
|
children: label
|
|
1067
|
+
}), isEffectivelyReadOnly && /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
1068
|
+
id: readOnlyDescriptionId,
|
|
1069
|
+
children: t('@astryx.input.readOnly')
|
|
1014
1070
|
}), /*#__PURE__*/_jsx("button", {
|
|
1071
|
+
...triggerSharedProps,
|
|
1015
1072
|
ref: triggerRef,
|
|
1016
|
-
id: triggerId,
|
|
1017
1073
|
type: "button"
|
|
1018
|
-
//
|
|
1019
|
-
//
|
|
1020
|
-
//
|
|
1074
|
+
// The read-only trigger stays a combobox even when hasSearch is set:
|
|
1075
|
+
// no search input is rendered in that state, and preserving the role
|
|
1076
|
+
// keeps the control's programmatic identity stable. Editable search
|
|
1077
|
+
// mode still moves combobox semantics to the popup input.
|
|
1021
1078
|
,
|
|
1022
|
-
role: hasSearch ?
|
|
1023
|
-
"aria-haspopup": surface.activePresentation === 'bottom-sheet' ? 'dialog' : 'listbox',
|
|
1024
|
-
"aria-expanded": surface.isOpen,
|
|
1025
|
-
"aria-controls": listboxId,
|
|
1026
|
-
"aria-
|
|
1027
|
-
"aria-
|
|
1028
|
-
"aria-labelledby": ariaLabelledBy,
|
|
1029
|
-
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
1030
|
-
"aria-invalid": status?.type === 'error' ? 'true' : undefined,
|
|
1031
|
-
"aria-busy": isBusy || undefined
|
|
1079
|
+
role: isEffectivelyReadOnly || !hasSearch ? 'combobox' : undefined,
|
|
1080
|
+
"aria-haspopup": isEffectivelyReadOnly ? undefined : surface.activePresentation === 'bottom-sheet' ? 'dialog' : 'listbox',
|
|
1081
|
+
"aria-expanded": isEffectivelyReadOnly ? false : surface.isOpen,
|
|
1082
|
+
"aria-controls": isEffectivelyReadOnly ? undefined : listboxId,
|
|
1083
|
+
"aria-readonly": isEffectivelyReadOnly || undefined,
|
|
1084
|
+
"aria-activedescendant": !isEffectivelyReadOnly && !hasSearch && surface.isOpen && highlightedIndex >= 0 ? getItemId(highlightedIndex) : undefined
|
|
1032
1085
|
// With a disabledMessage the trigger keeps focusability via
|
|
1033
1086
|
// aria-disabled so the reason is focus-discoverable; activation is
|
|
1034
1087
|
// still blocked by the isDisabled guards in useMultiCombobox.
|
|
1035
1088
|
,
|
|
1036
1089
|
disabled: isDisabled && !showsDisabledMessage,
|
|
1037
1090
|
"aria-disabled": showsDisabledMessage ? 'true' : undefined,
|
|
1038
|
-
onKeyDown: onKeyDown,
|
|
1039
|
-
onFocus: event => {
|
|
1040
|
-
onFocus?.(event);
|
|
1041
|
-
surface.onTriggerFocus(event);
|
|
1042
|
-
},
|
|
1043
|
-
tabIndex: isDisabled && !showsDisabledMessage ? -1 : 0,
|
|
1044
|
-
...{
|
|
1045
|
-
className: "x78zum5 x6s0dn4 x1qughib x1txdalj x1iyjqo2 xs83m0k x1r8uery xeuugli x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x15bjb6t x1heor9g x1ypdohk x16khyan x1a2a7pz xh6dtrn"
|
|
1046
|
-
},
|
|
1047
1091
|
children: /*#__PURE__*/_jsx("span", {
|
|
1048
1092
|
...{
|
|
1049
1093
|
className: "x78zum5 x6s0dn4 xzye2dw x1iyjqo2 xs83m0k x1r8uery xeuugli xb3r6kr"
|
|
@@ -1060,7 +1104,7 @@ export function MultiSelector({
|
|
|
1060
1104
|
disabled: isDisabled
|
|
1061
1105
|
}, v)), isBusy && /*#__PURE__*/_jsx(Spinner, {
|
|
1062
1106
|
size: "sm"
|
|
1063
|
-
}), hasClear && value.length > 0 && !isDisabled && /*#__PURE__*/_jsx(InternalInputClearButton, {
|
|
1107
|
+
}), hasClear && value.length > 0 && !isDisabled && !isEffectivelyReadOnly && /*#__PURE__*/_jsx(InternalInputClearButton, {
|
|
1064
1108
|
...keepOpenProps,
|
|
1065
1109
|
label: t('@astryx.multiSelector.clearAll', {
|
|
1066
1110
|
label
|
|
@@ -1086,7 +1130,7 @@ export function MultiSelector({
|
|
|
1086
1130
|
size: "sm",
|
|
1087
1131
|
color: STATUS_ICON_COLOR_MAP[status.type],
|
|
1088
1132
|
xstyle: styles.triggerIcon
|
|
1089
|
-
}) : /*#__PURE__*/_jsx(Icon, {
|
|
1133
|
+
}) : !isEffectivelyReadOnly ? /*#__PURE__*/_jsx(Icon, {
|
|
1090
1134
|
icon: "chevronDown",
|
|
1091
1135
|
size: "sm",
|
|
1092
1136
|
color: "secondary"
|
|
@@ -1104,7 +1148,7 @@ export function MultiSelector({
|
|
|
1104
1148
|
...themeProps('multi-selector-indicator-icon', {
|
|
1105
1149
|
state: surface.isOpen ? 'expanded' : 'collapsed'
|
|
1106
1150
|
})
|
|
1107
|
-
})]
|
|
1151
|
+
}) : null]
|
|
1108
1152
|
}), selectionSurface, showStatusTooltip && statusTooltip.renderTooltip(status?.message ?? ''), showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
|
|
1109
1153
|
});
|
|
1110
1154
|
if (inputGroup) {
|
|
@@ -18,17 +18,42 @@ import type { BaseProps } from '../BaseProps';
|
|
|
18
18
|
export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
|
|
19
19
|
ref?: React.Ref<HTMLDivElement>;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Primary label for the radio item.
|
|
22
|
+
*
|
|
23
|
+
* Accepts a plain string or a ReactNode for rich content. Links and buttons
|
|
24
|
+
* in the label keep their own behavior; only non-interactive row clicks
|
|
25
|
+
* delegate to the radio. The radio points at the rendered label for its
|
|
26
|
+
* accessible name, so a rich label still names it from its own text — pass
|
|
27
|
+
* `aria-label` when that text is absent or too noisy to announce.
|
|
22
28
|
*/
|
|
23
|
-
label:
|
|
29
|
+
label: ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Plain-text accessible name for the radio, applied to the control rather
|
|
32
|
+
* than the row. It replaces the name the label would otherwise supply — a
|
|
33
|
+
* plain string label included — so reach for it when a rich label's own
|
|
34
|
+
* text is absent or reads badly, not as a routine addition.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```
|
|
38
|
+
* <RadioListItem
|
|
39
|
+
* label={<span>Pro plan <Badge label="Recommended" /></span>}
|
|
40
|
+
* aria-label="Pro plan"
|
|
41
|
+
* value="pro"
|
|
42
|
+
* />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
'aria-label'?: string;
|
|
24
46
|
/**
|
|
25
47
|
* Value of this radio item.
|
|
26
48
|
*/
|
|
27
49
|
value: string;
|
|
28
50
|
/**
|
|
29
|
-
*
|
|
51
|
+
* Secondary content displayed below the label. Accepts a plain string or a
|
|
52
|
+
* ReactNode. Links and buttons anywhere in the row keep their own click
|
|
53
|
+
* behaviour — the row only delegates clicks from its non-interactive
|
|
54
|
+
* surface to the radio.
|
|
30
55
|
*/
|
|
31
|
-
description?:
|
|
56
|
+
description?: ReactNode;
|
|
32
57
|
/**
|
|
33
58
|
* Whether this individual radio item is disabled.
|
|
34
59
|
* @default false
|
|
@@ -56,7 +81,7 @@ export interface RadioListItemProps extends BaseProps<HTMLDivElement> {
|
|
|
56
81
|
* />
|
|
57
82
|
* ```
|
|
58
83
|
*/
|
|
59
|
-
export declare function RadioListItem({ ref, label, value, description, isDisabled: isItemDisabled, startContent, endContent, xstyle, className, style, onClick, ...rest }: RadioListItemProps): React.JSX.Element;
|
|
84
|
+
export declare function RadioListItem({ ref, label, 'aria-label': ariaLabel, value, description, isDisabled: isItemDisabled, startContent, endContent, xstyle, className, style, onClick, ...rest }: RadioListItemProps): React.JSX.Element;
|
|
60
85
|
export declare namespace RadioListItem {
|
|
61
86
|
var displayName: string;
|
|
62
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyF5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC
|
|
1
|
+
{"version":3,"file":"RadioListItem.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyF5C,MAAM,WAAW,kBAAmB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACnE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;OAQG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;OAcG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EAAE,cAAsB,EAClC,YAAY,EACZ,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,IAAI,EACR,EAAE,kBAAkB,qBAsJpB;yBApKe,aAAa"}
|
|
@@ -94,6 +94,7 @@ const rowStyles = {
|
|
|
94
94
|
export function RadioListItem({
|
|
95
95
|
ref,
|
|
96
96
|
label,
|
|
97
|
+
'aria-label': ariaLabel,
|
|
97
98
|
value,
|
|
98
99
|
description,
|
|
99
100
|
isDisabled: isItemDisabled = false,
|
|
@@ -110,6 +111,7 @@ export function RadioListItem({
|
|
|
110
111
|
throw new Error('RadioListItem must be used within an RadioList');
|
|
111
112
|
}
|
|
112
113
|
const id = useId();
|
|
114
|
+
const labelID = useId();
|
|
113
115
|
const descriptionID = useId();
|
|
114
116
|
const isDisabled = context.isDisabled || isItemDisabled;
|
|
115
117
|
// When the whole group is disabled with a disabledMessage, radios stay
|
|
@@ -118,6 +120,10 @@ export function RadioListItem({
|
|
|
118
120
|
// and always uses the native disabled attribute.
|
|
119
121
|
const keepsFocusableForMessage = context.hasDisabledMessage && !isItemDisabled;
|
|
120
122
|
const isChecked = context.value === value;
|
|
123
|
+
// One predicate for both the rendered element and the aria-describedby that
|
|
124
|
+
// points at it. A ReactNode description can be `false` or `''`, which render
|
|
125
|
+
// nothing — a `!= null` check would leave the link dangling.
|
|
126
|
+
const hasDescription = isRenderable(description);
|
|
121
127
|
const size = context.size;
|
|
122
128
|
// The radio visual is an indicator: a theme can restyle it through the
|
|
123
129
|
// `radio` / `radio-dot` targets or replace the component outright.
|
|
@@ -148,7 +154,6 @@ export function RadioListItem({
|
|
|
148
154
|
name: context.name,
|
|
149
155
|
value: value,
|
|
150
156
|
checked: isChecked,
|
|
151
|
-
"aria-label": label,
|
|
152
157
|
disabled: isDisabled && !keepsFocusableForMessage,
|
|
153
158
|
"aria-disabled": keepsFocusableForMessage ? 'true' : undefined
|
|
154
159
|
// A focusable-disabled radio is not natively disabled, so detach it
|
|
@@ -167,8 +172,15 @@ export function RadioListItem({
|
|
|
167
172
|
// both direct control clicks and row-surface clicks the row delegates
|
|
168
173
|
// to the input — the same routing CheckboxListItem uses.
|
|
169
174
|
,
|
|
170
|
-
onClick: onClick
|
|
171
|
-
|
|
175
|
+
onClick: onClick
|
|
176
|
+
// The radio names itself from the visible label element, which works
|
|
177
|
+
// for a rich label as well as a plain string. `aria-label` replaces
|
|
178
|
+
// that name rather than adding to it, so the two are mutually
|
|
179
|
+
// exclusive — aria-labelledby would otherwise win over it.
|
|
180
|
+
,
|
|
181
|
+
"aria-label": ariaLabel,
|
|
182
|
+
"aria-labelledby": ariaLabel == null ? labelID : undefined,
|
|
183
|
+
"aria-describedby": hasDescription ? descriptionID : undefined,
|
|
172
184
|
...stylex.props(styles.input, wrapperSizeStyles[size], isDisabled && styles.inputDisabled)
|
|
173
185
|
}), /*#__PURE__*/_jsx("span", {
|
|
174
186
|
ref: indicatorRef,
|
|
@@ -195,9 +207,10 @@ export function RadioListItem({
|
|
|
195
207
|
interactiveRef: radioRef,
|
|
196
208
|
isDisabled: isDisabled,
|
|
197
209
|
label: /*#__PURE__*/_jsx("span", {
|
|
210
|
+
id: labelID,
|
|
198
211
|
children: label
|
|
199
212
|
}),
|
|
200
|
-
description:
|
|
213
|
+
description: hasDescription ? /*#__PURE__*/_jsx("span", {
|
|
201
214
|
id: descriptionID,
|
|
202
215
|
children: description
|
|
203
216
|
}) : undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResizeHandle.d.ts","sourceRoot":"","sources":["../../src/Resizable/ResizeHandle.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ResizeHandle.d.ts","sourceRoot":"","sources":["../../src/Resizable/ResizeHandle.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAQnD,KAAK,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAyOzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,OAAO,CACR;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,SAAS,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IAEtC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAEhC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAE9B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,6CAA6C;IAC7C,SAAS,CAAC,EAAE,cAAc,CAAC;IAE3B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAwB,EACxB,QAAQ,EAAE,YAAuB,EACjC,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAsB,EACtB,aAAsB,EACtB,KAAK,EAAE,cAAc,EACrB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,iBAAiB,+BAuVnB;yBAtWe,YAAY"}
|
|
@@ -21,9 +21,19 @@
|
|
|
21
21
|
* While the panel is collapsed, aria-valuenow is clamped to aria-valuemin
|
|
22
22
|
* (a value below the minimum is invalid per WCAG 4.1.2) and a localized
|
|
23
23
|
* "Collapsed" aria-valuetext announces the real state.
|
|
24
|
+
*
|
|
25
|
+
* Dragging takes pointer capture on the grab zone, so the rest of the gesture
|
|
26
|
+
* is delivered to that element instead of being hit-tested against whatever
|
|
27
|
+
* the cursor happens to be over. A resizable region that contains an embedded
|
|
28
|
+
* frame otherwise loses the drag the moment the cursor crosses the frame: the
|
|
29
|
+
* events go to the guest document, and a listener on the host window never
|
|
30
|
+
* hears them again. Captured events are delivered to the capturing element,
|
|
31
|
+
* so the move/up/cancel handlers live on the grab zone (as in Slider), not on
|
|
32
|
+
* window.
|
|
24
33
|
*/
|
|
25
34
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
26
35
|
import * as stylex from '@stylexjs/stylex';
|
|
36
|
+
import { devWarn } from "../utils/devWarning.js";
|
|
27
37
|
import "../theme/tokens.stylex.js";
|
|
28
38
|
import { colorVars, durationVars, easeVars, radiusVars, spacingVars } from "../theme/tokens.stylex.js";
|
|
29
39
|
import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
|
|
@@ -66,6 +76,20 @@ function hitAreaBiasDir(effectiveSide) {
|
|
|
66
76
|
}
|
|
67
77
|
return effectiveSide === 'start' ? -1 : 1;
|
|
68
78
|
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Drag feedback lives on `<body>`, not on the handle: the pointer spends the
|
|
82
|
+
* drag off the handle, over whatever the panels contain, and the resize cursor
|
|
83
|
+
* has to hold there. Module scope so the writes stay outside the component.
|
|
84
|
+
*/
|
|
85
|
+
function applyBodyDragStyles(isHorizontal) {
|
|
86
|
+
document.body.style.cursor = isHorizontal ? 'col-resize' : 'row-resize';
|
|
87
|
+
document.body.style.userSelect = 'none';
|
|
88
|
+
}
|
|
89
|
+
function clearBodyDragStyles() {
|
|
90
|
+
document.body.style.cursor = '';
|
|
91
|
+
document.body.style.userSelect = '';
|
|
92
|
+
}
|
|
69
93
|
const styles = {
|
|
70
94
|
handle: {
|
|
71
95
|
kVAEAm: "x1n2onr6",
|
|
@@ -273,9 +297,10 @@ export function ResizeHandle({
|
|
|
273
297
|
const t = useTranslator();
|
|
274
298
|
const label = labelFromProps ?? t('@astryx.resizable.handle.label');
|
|
275
299
|
const handleRef = useRef(null);
|
|
276
|
-
//
|
|
277
|
-
//
|
|
278
|
-
|
|
300
|
+
// The pointer that owns the in-flight drag, plus the values its deltas are
|
|
301
|
+
// measured against. A ref so moves don't re-render, and so unmount can tell
|
|
302
|
+
// a live drag from a finished one.
|
|
303
|
+
const dragRef = useRef(null);
|
|
279
304
|
const [isDragging, setIsDragging] = useState(false);
|
|
280
305
|
const [isHovered, setIsHovered] = useState(false);
|
|
281
306
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -295,48 +320,73 @@ export function ResizeHandle({
|
|
|
295
320
|
}, []);
|
|
296
321
|
const isInteracting = isHovered || isFocused;
|
|
297
322
|
|
|
323
|
+
// A handle whose axis disagrees with its hook drags along one axis while the
|
|
324
|
+
// hook measures percentage bounds on the other. `ResizableProps` is exported,
|
|
325
|
+
// so `_direction` is optional for old hand-built objects; absent means there
|
|
326
|
+
// is no hook axis to compare, not that the hook is horizontal.
|
|
327
|
+
const didWarnAxisRef = useRef(false);
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
const hookDirection = resizable?._direction;
|
|
330
|
+
if (hookDirection != null && hookDirection !== direction && !didWarnAxisRef.current) {
|
|
331
|
+
didWarnAxisRef.current = true;
|
|
332
|
+
devWarn('ResizeHandle', `direction="${direction}" but its useResizable region is ` + `"${hookDirection}". They must match: the hook measures one axis ` + 'and the handle drags the other.');
|
|
333
|
+
}
|
|
334
|
+
}, [direction, resizable]);
|
|
335
|
+
|
|
298
336
|
// --- Pointer drag ---
|
|
337
|
+
const clearDrag = useCallback(() => {
|
|
338
|
+
dragRef.current = null;
|
|
339
|
+
setIsDragging(false);
|
|
340
|
+
clearBodyDragStyles();
|
|
341
|
+
}, []);
|
|
299
342
|
const handlePointerDown = useCallback(e => {
|
|
300
|
-
if (isDisabled || !resizable) {
|
|
343
|
+
if (isDisabled || !resizable || dragRef.current) {
|
|
301
344
|
return;
|
|
302
345
|
}
|
|
303
346
|
e.preventDefault();
|
|
304
347
|
e.stopPropagation();
|
|
348
|
+
// Take the pointer for the whole gesture. Without capture the browser
|
|
349
|
+
// re-hit-tests every move, so a frame anywhere under the drag path
|
|
350
|
+
// swallows the rest of it into the guest document.
|
|
351
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
352
|
+
dragRef.current = {
|
|
353
|
+
pointerId: e.pointerId,
|
|
354
|
+
startPos: isHorizontal ? e.clientX : e.clientY,
|
|
355
|
+
rtl: isHorizontal ? getRTLMultiplier() : 1
|
|
356
|
+
};
|
|
305
357
|
setIsDragging(true);
|
|
306
358
|
resizable._onResizeStart();
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const delta = (currentPos - startPos) * rtl * sign;
|
|
314
|
-
resizable._onResizeMove(delta);
|
|
315
|
-
};
|
|
316
|
-
const onUp = () => {
|
|
317
|
-
cleanup();
|
|
318
|
-
setIsDragging(false);
|
|
319
|
-
resizable._onResizeEnd();
|
|
320
|
-
document.body.style.cursor = '';
|
|
321
|
-
document.body.style.userSelect = '';
|
|
322
|
-
};
|
|
323
|
-
const onCancel = () => {
|
|
324
|
-
cleanup();
|
|
325
|
-
setIsDragging(false);
|
|
326
|
-
document.body.style.cursor = '';
|
|
327
|
-
document.body.style.userSelect = '';
|
|
328
|
-
};
|
|
329
|
-
function cleanup() {
|
|
330
|
-
window.removeEventListener('pointermove', onMove);
|
|
331
|
-
window.removeEventListener('pointerup', onUp);
|
|
332
|
-
window.removeEventListener('pointercancel', onCancel);
|
|
333
|
-
dragCleanupRef.current = null;
|
|
359
|
+
applyBodyDragStyles(isHorizontal);
|
|
360
|
+
}, [isDisabled, resizable, isHorizontal, getRTLMultiplier]);
|
|
361
|
+
const handlePointerMove = useCallback(e => {
|
|
362
|
+
const drag = dragRef.current;
|
|
363
|
+
if (!drag || drag.pointerId !== e.pointerId || !resizable) {
|
|
364
|
+
return;
|
|
334
365
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
366
|
+
const currentPos = isHorizontal ? e.clientX : e.clientY;
|
|
367
|
+
resizable._onResizeMove((currentPos - drag.startPos) * drag.rtl * sign);
|
|
368
|
+
}, [resizable, isHorizontal, sign]);
|
|
369
|
+
const handlePointerUp = useCallback(e => {
|
|
370
|
+
if (dragRef.current?.pointerId !== e.pointerId) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
clearDrag();
|
|
374
|
+
resizable?._onResizeEnd();
|
|
375
|
+
}, [clearDrag, resizable]);
|
|
376
|
+
|
|
377
|
+
// Serves pointercancel and lostpointercapture alike: an interrupted drag
|
|
378
|
+
// ends without signalling a resize end. lostpointercapture also fires on the
|
|
379
|
+
// implicit release after every pointerup/pointercancel, by which point the
|
|
380
|
+
// drag is already cleared and this is a no-op.
|
|
381
|
+
const cancelDrag = useCallback(e => {
|
|
382
|
+
if (dragRef.current?.pointerId !== e.pointerId) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
clearDrag();
|
|
386
|
+
// Not a resize end, but still the end of the gesture: the region froze
|
|
387
|
+
// state for the duration of the drag and has to be told it is over.
|
|
388
|
+
resizable?._onResizeCancel?.();
|
|
389
|
+
}, [clearDrag, resizable]);
|
|
340
390
|
|
|
341
391
|
// --- Keyboard ---
|
|
342
392
|
const handleKeyDown = useCallback(e => {
|
|
@@ -406,16 +456,20 @@ export function ResizeHandle({
|
|
|
406
456
|
}, [isDisabled, resizable]);
|
|
407
457
|
|
|
408
458
|
// --- Cleanup on unmount ---
|
|
409
|
-
//
|
|
410
|
-
//
|
|
411
|
-
//
|
|
412
|
-
//
|
|
459
|
+
// Removing the grab zone implicitly releases its captured pointer and takes
|
|
460
|
+
// its listeners with it, so an in-flight drag stops driving the region on
|
|
461
|
+
// its own. The body cursor/user-select overrides are not on the element,
|
|
462
|
+
// though, so they have to be released here or they stick after the handle
|
|
463
|
+
// is gone — and the region, which outlives this handle, still has to hear
|
|
464
|
+
// that its gesture is over.
|
|
465
|
+
const cancelOnUnmountRef = useRef(undefined);
|
|
466
|
+
cancelOnUnmountRef.current = resizable?._onResizeCancel;
|
|
413
467
|
useEffect(() => {
|
|
414
468
|
return () => {
|
|
415
|
-
if (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
469
|
+
if (dragRef.current) {
|
|
470
|
+
dragRef.current = null;
|
|
471
|
+
clearBodyDragStyles();
|
|
472
|
+
cancelOnUnmountRef.current?.();
|
|
419
473
|
}
|
|
420
474
|
};
|
|
421
475
|
}, []);
|
|
@@ -464,6 +518,10 @@ export function ResizeHandle({
|
|
|
464
518
|
// construction so the two stay aligned in LTR and RTL alike.
|
|
465
519
|
hitBiasDir == null ? isHorizontal ? rtlStyles.centerInline('0px') : styles.hitAreaCenteredY : isHorizontal ? dynamicStyles.hitAreaOffsetX(hitBiasDir) : dynamicStyles.hitAreaOffsetY(hitBiasDir), isDisabled && styles.disabled),
|
|
466
520
|
onPointerDown: handlePointerDown,
|
|
521
|
+
onPointerMove: handlePointerMove,
|
|
522
|
+
onPointerUp: handlePointerUp,
|
|
523
|
+
onPointerCancel: cancelDrag,
|
|
524
|
+
onLostPointerCapture: cancelDrag,
|
|
467
525
|
onPointerEnter: () => setIsHovered(true),
|
|
468
526
|
onPointerLeave: () => {
|
|
469
527
|
if (!isDragging) {
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* @output Re-exports all public Resizable API
|
|
5
5
|
* @position Package entry point for Resizable
|
|
6
6
|
*/
|
|
7
|
+
export { percent } from './utils';
|
|
7
8
|
export { useResizable } from './useResizable';
|
|
9
|
+
export type { ResizablePercentSize, ResizableSize } from './utils';
|
|
8
10
|
export type { ResizableRegion, ResizableRegionConfig, ResizableProps, ResizableConfig, UseResizableSingleConfig, UseResizableMultiConfig, } from './useResizable';
|
|
9
11
|
export { ResizeHandle } from './ResizeHandle';
|
|
10
12
|
export type { ResizeHandleProps } from './ResizeHandle';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Resizable/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Resizable/index.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,SAAS,CAAC;AAChC,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,oBAAoB,EAAE,aAAa,EAAC,MAAM,SAAS,CAAC;AACjE,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAC"}
|
package/dist/Resizable/index.js
CHANGED