@primitiv-ui/react 0.1.28 → 0.1.30
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/README.md +19 -2
- package/package.json +6 -1
- package/src/AccessibleIcon/AccessibleIcon.tsx +32 -9
- package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +5 -0
- package/src/AccessibleIcon/types.ts +15 -2
- package/src/Accordion/Accordion.tsx +32 -11
- package/src/Accordion/README.md +2 -2
- package/src/Accordion/__tests__/Accordion.asChild.test.tsx +46 -0
- package/src/Accordion/__tests__/Accordion.basic-rendering.test.tsx +15 -0
- package/src/Accordion/__tests__/Accordion.disabled-items.test.tsx +42 -0
- package/src/Accordion/__tests__/Accordion.error-handling.test.tsx +33 -0
- package/src/Accordion/hooks/useAccordionRoot.ts +44 -7
- package/src/Accordion/hooks/useAccordionTrigger.ts +9 -1
- package/src/Accordion/types.ts +72 -21
- package/src/Alert/Alert.tsx +36 -7
- package/src/Alert/__tests__/Alert.test.tsx +5 -0
- package/src/Alert/types.ts +18 -2
- package/src/Avatar/Avatar.tsx +99 -15
- package/src/Avatar/__tests__/Avatar.basic-rendering.test.tsx +10 -0
- package/src/Avatar/__tests__/Avatar.fallback.test.tsx +30 -0
- package/src/Avatar/__tests__/Avatar.image-loading.test.tsx +35 -0
- package/src/Avatar/hooks/useAvatarImage.ts +16 -0
- package/src/Avatar/types.ts +15 -3
- package/src/Breadcrumb/Breadcrumb.tsx +139 -21
- package/src/Breadcrumb/README.md +47 -0
- package/src/Breadcrumb/__tests__/Breadcrumb.basic-rendering.test.tsx +11 -0
- package/src/Breadcrumb/__tests__/Breadcrumb.ellipsis.test.tsx +110 -0
- package/src/Breadcrumb/types.ts +73 -7
- package/src/Button/Button.tsx +2 -0
- package/src/Button/__tests__/Button.basic-rendering.test.tsx +6 -0
- package/src/Button/__tests__/Button.contract.test.tsx +1 -1
- package/src/Button/types.ts +21 -0
- package/src/Carousel/Carousel.tsx +268 -20
- package/src/Carousel/README.md +764 -87
- package/src/Carousel/__tests__/Carousel.autoplay-status.test.tsx +239 -0
- package/src/Carousel/__tests__/Carousel.drag-status.test.tsx +292 -0
- package/src/Carousel/__tests__/Carousel.dynamic-slides.test.tsx +38 -0
- package/src/Carousel/__tests__/Carousel.indicators.test.tsx +101 -0
- package/src/Carousel/__tests__/Carousel.infinite.test.tsx +1453 -0
- package/src/Carousel/__tests__/Carousel.instant-scroll.test.tsx +124 -0
- package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +90 -2
- package/src/Carousel/__tests__/Carousel.loop.test.tsx +163 -0
- package/src/Carousel/__tests__/Carousel.loopEngine.test.ts +77 -0
- package/src/Carousel/__tests__/Carousel.mouse-drag.test.tsx +504 -0
- package/src/Carousel/__tests__/Carousel.multi-slide-bounds.test.tsx +91 -0
- package/src/Carousel/__tests__/Carousel.orientation.test.tsx +207 -0
- package/src/Carousel/__tests__/Carousel.overscroll.test.tsx +532 -0
- package/src/Carousel/__tests__/Carousel.page-snap-points.test.tsx +50 -0
- package/src/Carousel/__tests__/Carousel.progress-text.test.tsx +76 -0
- package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +3 -6
- package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +2 -5
- package/src/Carousel/__tests__/Carousel.scroll-margin.test.tsx +167 -0
- package/src/Carousel/__tests__/Carousel.scroll-progress.test.tsx +518 -0
- package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +32 -11
- package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +237 -24
- package/src/Carousel/__tests__/Carousel.scroll-to-index.test.tsx +115 -0
- package/src/Carousel/__tests__/Carousel.slide-snap.test.tsx +172 -0
- package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +179 -1
- package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +91 -7
- package/src/Carousel/__tests__/Carousel.snap-type.test.tsx +35 -0
- package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +30 -5
- package/src/Carousel/__tests__/Carousel.translations.test.tsx +23 -0
- package/src/Carousel/__tests__/Carousel.wheel.test.tsx +160 -0
- package/src/Carousel/hooks/index.ts +1 -0
- package/src/Carousel/hooks/useCarouselLoop.ts +869 -0
- package/src/Carousel/hooks/useCarouselRoot.ts +338 -42
- package/src/Carousel/hooks/useCarouselSlide.ts +44 -9
- package/src/Carousel/hooks/useCarouselViewport.ts +649 -46
- package/src/Carousel/loopEngine.ts +54 -0
- package/src/Carousel/types.ts +458 -36
- package/src/Checkbox/Checkbox.tsx +11 -3
- package/src/Checkbox/__tests__/Checkbox.basic-rendering.test.tsx +14 -0
- package/src/Checkbox/hooks/useCheckboxInput.ts +4 -0
- package/src/Checkbox/types.ts +19 -0
- package/src/CheckboxCard/CheckboxCard.tsx +14 -5
- package/src/CheckboxCard/README.md +1 -1
- package/src/CheckboxCard/__tests__/CheckboxCard.basic-rendering.test.tsx +7 -0
- package/src/CheckboxCard/types.ts +65 -17
- package/src/Collapsible/Collapsible.tsx +49 -3
- package/src/Collapsible/README.md +41 -1
- package/src/Collapsible/__tests__/Collapsible.asChild.test.tsx +89 -0
- package/src/Collapsible/__tests__/Collapsible.basic-rendering.test.tsx +27 -0
- package/src/Collapsible/__tests__/Collapsible.collapsedHeight.test.tsx +140 -0
- package/src/Collapsible/hooks/useCollapsibleTrigger.ts +3 -1
- package/src/Collapsible/types.ts +89 -22
- package/src/Combobox/Combobox.tsx +508 -0
- package/src/Combobox/ComboboxContext.ts +23 -0
- package/src/Combobox/README.md +170 -0
- package/src/Combobox/__tests__/Combobox.asChild.test.tsx +62 -0
- package/src/Combobox/__tests__/Combobox.basic-rendering.test.tsx +16 -0
- package/src/Combobox/__tests__/Combobox.content.test.tsx +36 -0
- package/src/Combobox/__tests__/Combobox.controlled-state.test.tsx +88 -0
- package/src/Combobox/__tests__/Combobox.empty.test.tsx +42 -0
- package/src/Combobox/__tests__/Combobox.ids.test.tsx +66 -0
- package/src/Combobox/__tests__/Combobox.item.test.tsx +76 -0
- package/src/Combobox/__tests__/Combobox.keyboard-interaction.test.tsx +196 -0
- package/src/Combobox/__tests__/Combobox.light-dismiss.test.tsx +101 -0
- package/src/Combobox/__tests__/Combobox.query.test.tsx +105 -0
- package/src/Combobox/hooks/index.ts +1 -0
- package/src/Combobox/hooks/useComboboxRoot.ts +2 -0
- package/src/Combobox/index.ts +3 -0
- package/src/Combobox/types.ts +133 -0
- package/src/ContextMenu/ContextMenu.tsx +270 -4
- package/src/ContextMenu/README.md +1 -1
- package/src/ContextMenu/types.ts +148 -6
- package/src/DirectionProvider/DirectionProvider.tsx +41 -9
- package/src/DirectionProvider/README.md +4 -4
- package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +5 -0
- package/src/DirectionProvider/types.ts +28 -3
- package/src/Divider/Divider.tsx +24 -10
- package/src/Divider/__tests__/Divider.contract.test.tsx +1 -1
- package/src/Divider/__tests__/Divider.test.tsx +5 -0
- package/src/Divider/types.ts +10 -3
- package/src/Drawer/Drawer.tsx +315 -0
- package/src/Drawer/README.md +124 -0
- package/src/Drawer/__tests__/Drawer.behavior.test.tsx +100 -0
- package/src/Drawer/__tests__/Drawer.focus-trap.test.tsx +55 -0
- package/src/Drawer/__tests__/Drawer.rendering.test.tsx +111 -0
- package/src/Drawer/__tests__/Drawer.side.test.tsx +69 -0
- package/src/Drawer/__tests__/dialog-polyfill.ts +39 -0
- package/src/Drawer/index.ts +2 -0
- package/src/Drawer/types.ts +66 -0
- package/src/Dropdown/Dropdown.tsx +119 -2
- package/src/Dropdown/README.md +7 -5
- package/src/Dropdown/types.ts +241 -11
- package/src/EmptyState/EmptyState.tsx +74 -4
- package/src/EmptyState/README.md +2 -2
- package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +7 -2
- package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +3 -1
- package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +10 -0
- package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +3 -1
- package/src/EmptyState/types.ts +49 -6
- package/src/Field/Field.tsx +23 -0
- package/src/Field/README.md +1 -1
- package/src/Field/__tests__/Field.basic-rendering.test.tsx +11 -0
- package/src/Field/__tests__/Field.error-handling.test.tsx +23 -0
- package/src/Field/__tests__/Field.state-cascade.test.tsx +21 -0
- package/src/Field/hooks/__tests__/useFieldProps.test.tsx +104 -9
- package/src/Field/hooks/useFieldProps.ts +1 -1
- package/src/Field/types.ts +60 -12
- package/src/Fieldset/Fieldset.tsx +55 -19
- package/src/Fieldset/README.md +2 -2
- package/src/Fieldset/__tests__/Fieldset.basic-rendering.test.tsx +9 -0
- package/src/Fieldset/types.ts +20 -2
- package/src/Input/Input.tsx +15 -10
- package/src/Input/README.md +2 -2
- package/src/Input/__tests__/Input.basic-rendering.test.tsx +5 -0
- package/src/Input/types.ts +19 -2
- package/src/InputGroup/InputGroup.tsx +11 -3
- package/src/InputGroup/__tests__/InputGroup.basic-rendering.test.tsx +14 -0
- package/src/InputGroup/types.ts +26 -5
- package/src/Listbox/Listbox.tsx +475 -0
- package/src/Listbox/ListboxContext.ts +48 -0
- package/src/Listbox/README.md +248 -0
- package/src/Listbox/__tests__/Listbox.active-descendant.test.tsx +128 -0
- package/src/Listbox/__tests__/Listbox.asChild.test.tsx +91 -0
- package/src/Listbox/__tests__/Listbox.basic-rendering.test.tsx +16 -0
- package/src/Listbox/__tests__/Listbox.controlled-state.test.tsx +114 -0
- package/src/Listbox/__tests__/Listbox.disabled.test.tsx +90 -0
- package/src/Listbox/__tests__/Listbox.fixtures.ts +27 -0
- package/src/Listbox/__tests__/Listbox.group-label.test.tsx +97 -0
- package/src/Listbox/__tests__/Listbox.group.test.tsx +45 -0
- package/src/Listbox/__tests__/Listbox.keyboard-edge-cases.test.tsx +144 -0
- package/src/Listbox/__tests__/Listbox.keyboard-interaction.test.tsx +112 -0
- package/src/Listbox/__tests__/Listbox.modifier-keys.test.tsx +86 -0
- package/src/Listbox/__tests__/Listbox.multi-select-keyboard.test.tsx +368 -0
- package/src/Listbox/__tests__/Listbox.multiple-mode.test.tsx +91 -0
- package/src/Listbox/__tests__/Listbox.mutation-hardening.test.tsx +480 -0
- package/src/Listbox/__tests__/Listbox.orientation.test.tsx +59 -0
- package/src/Listbox/__tests__/Listbox.reading-direction.test.tsx +65 -0
- package/src/Listbox/__tests__/Listbox.reorder.test.tsx +78 -0
- package/src/Listbox/__tests__/Listbox.selection-follows-focus.test.tsx +64 -0
- package/src/Listbox/__tests__/Listbox.strict-context.test.tsx +21 -0
- package/src/Listbox/__tests__/Listbox.typeahead.test.tsx +123 -0
- package/src/Listbox/__tests__/Listbox.uncontrolled-state.test.tsx +48 -0
- package/src/Listbox/constants.ts +2 -0
- package/src/Listbox/hooks/index.ts +1 -0
- package/src/Listbox/hooks/useListboxRoot.ts +407 -0
- package/src/Listbox/index.ts +3 -0
- package/src/Listbox/types.ts +238 -0
- package/src/MillerColumns/MillerColumns.tsx +186 -45
- package/src/MillerColumns/README.md +90 -20
- package/src/MillerColumns/__tests__/MillerColumns.aria.test.tsx +45 -0
- package/src/MillerColumns/__tests__/MillerColumns.auto-scroll.test.tsx +4 -2
- package/src/MillerColumns/__tests__/MillerColumns.basic-rendering.test.tsx +18 -3
- package/src/MillerColumns/__tests__/MillerColumns.data-attributes.test.tsx +48 -0
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-interaction.test.tsx +35 -2
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-selection-state.test.tsx +96 -0
- package/src/MillerColumns/__tests__/MillerColumns.preview-panel.test.tsx +29 -4
- package/src/MillerColumns/__tests__/MillerColumns.preview-visibility.test.tsx +79 -0
- package/src/MillerColumns/__tests__/MillerColumns.resize.test.tsx +189 -0
- package/src/MillerColumns/__tests__/MillerColumns.styled-parts.test.tsx +143 -0
- package/src/MillerColumns/__tests__/MillerColumns.typeahead.test.tsx +104 -0
- package/src/MillerColumns/constants.ts +2 -0
- package/src/MillerColumns/hooks/useMillerColumnsColumn.ts +5 -2
- package/src/MillerColumns/hooks/useMillerColumnsItem.ts +29 -7
- package/src/MillerColumns/hooks/useMillerColumnsResizeHandle.ts +80 -10
- package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
- package/src/MillerColumns/index.ts +4 -0
- package/src/MillerColumns/types.ts +136 -30
- package/src/MillerColumns/utils.ts +69 -3
- package/src/Modal/Modal.tsx +35 -8
- package/src/Modal/README.md +24 -15
- package/src/Modal/__tests__/Modal.focus-trap.test.tsx +162 -0
- package/src/Modal/hooks/useModalContent.ts +32 -0
- package/src/Modal/types.ts +110 -29
- package/src/NavigationMenu/NavigationMenu.tsx +890 -0
- package/src/NavigationMenu/NavigationMenuContext.ts +67 -0
- package/src/NavigationMenu/README.md +355 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.anchor-positioning.test.tsx +132 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.asChild.test.tsx +73 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.basic-rendering.test.tsx +92 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.contract.test.tsx +45 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.controlled-state.test.tsx +134 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.error-handling.test.tsx +62 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.fixtures.tsx +79 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.forceMount.test.tsx +52 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.hover-interaction.test.tsx +254 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.indicator.test.tsx +252 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-interaction.test.tsx +294 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-navigation.test.tsx +126 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.link.test.tsx +139 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.motion.test.tsx +568 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.mouse-interaction.test.tsx +76 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.uncontrolled-state.test.tsx +30 -0
- package/src/NavigationMenu/__tests__/NavigationMenu.viewport.test.tsx +113 -0
- package/src/NavigationMenu/constants.ts +5 -0
- package/src/NavigationMenu/hooks/index.ts +7 -0
- package/src/NavigationMenu/hooks/useNavigationMenuEntry.ts +33 -0
- package/src/NavigationMenu/hooks/useNavigationMenuIndicator.ts +70 -0
- package/src/NavigationMenu/hooks/useNavigationMenuLink.ts +72 -0
- package/src/NavigationMenu/hooks/useNavigationMenuRoot.ts +301 -0
- package/src/NavigationMenu/hooks/useNavigationMenuTopLevelEntry.ts +65 -0
- package/src/NavigationMenu/hooks/useNavigationMenuTrigger.ts +158 -0
- package/src/NavigationMenu/hooks/useNavigationMenuViewport.ts +101 -0
- package/src/NavigationMenu/index.ts +3 -0
- package/src/NavigationMenu/types.ts +259 -0
- package/src/NavigationMenu/utils.ts +89 -0
- package/src/Popover/Popover.tsx +427 -0
- package/src/Popover/PopoverContext.ts +13 -0
- package/src/Popover/README.md +106 -0
- package/src/Popover/__tests__/Popover.anchor.test.tsx +38 -0
- package/src/Popover/__tests__/Popover.asChild.test.tsx +160 -0
- package/src/Popover/__tests__/Popover.basic-rendering.test.tsx +106 -0
- package/src/Popover/__tests__/Popover.click-outside.test.tsx +149 -0
- package/src/Popover/__tests__/Popover.close.test.tsx +70 -0
- package/src/Popover/__tests__/Popover.content.test.tsx +58 -0
- package/src/Popover/__tests__/Popover.controlled-state.test.tsx +45 -0
- package/src/Popover/__tests__/Popover.error-handling.test.tsx +51 -0
- package/src/Popover/__tests__/Popover.focus.test.tsx +43 -0
- package/src/Popover/__tests__/Popover.keyboard-interaction.test.tsx +71 -0
- package/src/Popover/__tests__/Popover.mouse-interaction.test.tsx +69 -0
- package/src/Popover/__tests__/Popover.uncontrolled-state.test.tsx +44 -0
- package/src/Popover/hooks/index.ts +3 -0
- package/src/Popover/hooks/usePopoverContent.ts +98 -0
- package/src/Popover/hooks/usePopoverRoot.ts +84 -0
- package/src/Popover/hooks/usePopoverTrigger.ts +33 -0
- package/src/Popover/index.ts +2 -0
- package/src/Popover/types.ts +197 -0
- package/src/Portal/Portal.tsx +50 -10
- package/src/Portal/README.md +2 -2
- package/src/Portal/__tests__/Portal.basic-rendering.test.tsx +5 -0
- package/src/Portal/types.ts +5 -0
- package/src/Progress/Progress.tsx +33 -1
- package/src/Progress/README.md +1 -1
- package/src/Progress/__tests__/Progress.basic-rendering.test.tsx +10 -0
- package/src/Progress/__tests__/Progress.value.test.tsx +21 -0
- package/src/Progress/types.ts +20 -4
- package/src/Radio/Radio.tsx +10 -2
- package/src/Radio/__tests__/Radio.basic-rendering.test.tsx +14 -0
- package/src/Radio/hooks/useRadioRoot.ts +3 -0
- package/src/Radio/types.ts +20 -0
- package/src/RadioCard/RadioCard.tsx +11 -0
- package/src/RadioCard/__tests__/RadioCard.basic-rendering.test.tsx +8 -0
- package/src/RadioCard/__tests__/RadioCard.disabled-items.test.tsx +27 -0
- package/src/RadioCard/__tests__/RadioCard.keyboard-interaction.test.tsx +53 -0
- package/src/RadioCard/__tests__/RadioCard.ref-forwarding.test.tsx +54 -0
- package/src/RadioCard/__tests__/RadioCard.uncontrolled-state.test.tsx +21 -0
- package/src/RadioCard/hooks/useRadioCardRoot.ts +11 -0
- package/src/RadioCard/types.ts +95 -22
- package/src/RadioGroup/README.md +2 -2
- package/src/RadioGroup/RadioGroup.tsx +12 -1
- package/src/RadioGroup/__tests__/RadioGroup.basic-rendering.test.tsx +8 -0
- package/src/RadioGroup/__tests__/RadioGroup.disabled.test.tsx +27 -0
- package/src/RadioGroup/__tests__/RadioGroup.ref-forwarding.test.tsx +29 -0
- package/src/RadioGroup/__tests__/RadioGroup.roving-tabindex.test.tsx +31 -0
- package/src/RadioGroup/hooks/useRadioGroupRoot.ts +11 -0
- package/src/RadioGroup/types.ts +73 -9
- package/src/SegmentedControl/README.md +154 -0
- package/src/SegmentedControl/SegmentedControl.tsx +309 -0
- package/src/SegmentedControl/SegmentedControlContext.ts +28 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.asChild.test.tsx +50 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.basic-rendering.test.tsx +100 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.controlled-state.test.tsx +107 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled-keydown-guards.test.tsx +62 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled.test.tsx +151 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.error-handling.test.tsx +17 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.keyboard-interaction.test.tsx +117 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.orientation.test.tsx +54 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.reading-direction.test.tsx +56 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.ref-forwarding.test.tsx +45 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.roving-tabindex.test.tsx +104 -0
- package/src/SegmentedControl/__tests__/SegmentedControl.uncontrolled-state.test.tsx +94 -0
- package/src/SegmentedControl/hooks/index.ts +2 -0
- package/src/SegmentedControl/hooks/useSegmentedControlContext.ts +1 -0
- package/src/SegmentedControl/hooks/useSegmentedControlRoot.ts +87 -0
- package/src/SegmentedControl/index.ts +2 -0
- package/src/SegmentedControl/types.ts +138 -0
- package/src/Select/README.md +122 -157
- package/src/Select/Select.tsx +596 -69
- package/src/Select/SelectContext.ts +38 -0
- package/src/Select/SelectItemIndicatorContext.ts +29 -0
- package/src/Select/__tests__/Select.asChild.test.tsx +2 -2
- package/src/Select/__tests__/Select.basic-rendering.test.tsx +22 -3
- package/src/Select/__tests__/Select.controlled-state.test.tsx +6 -6
- package/src/Select/__tests__/Select.data-attributes.test.tsx +4 -4
- package/src/Select/__tests__/Select.field-integration.test.tsx +11 -11
- package/src/Select/__tests__/Select.form.test.tsx +38 -0
- package/src/Select/__tests__/Select.group.test.tsx +6 -6
- package/src/Select/__tests__/Select.keyboard-edge.test.tsx +95 -0
- package/src/Select/__tests__/Select.keyboard.test.tsx +124 -0
- package/src/Select/__tests__/Select.mutation-hardening.test.tsx +317 -0
- package/src/Select/__tests__/Select.native-item.test.tsx +30 -0
- package/src/Select/__tests__/Select.open-close.test.tsx +57 -0
- package/src/Select/__tests__/Select.placeholder.test.tsx +7 -7
- package/src/Select/__tests__/Select.rich-asChild.test.tsx +60 -0
- package/src/Select/__tests__/Select.rich-mode.test.tsx +16 -0
- package/src/Select/__tests__/Select.selection.test.tsx +104 -0
- package/src/Select/__tests__/Select.separator.test.tsx +71 -0
- package/src/Select/__tests__/Select.strict-context.test.tsx +36 -0
- package/src/Select/__tests__/Select.typeahead.test.tsx +156 -0
- package/src/Select/__tests__/Select.value-mirror.test.tsx +240 -0
- package/src/Select/constants.ts +8 -0
- package/src/Select/hooks/index.ts +2 -0
- package/src/Select/hooks/useSelectContent.ts +149 -0
- package/src/Select/hooks/useSelectRoot.ts +149 -0
- package/src/Select/types.ts +199 -31
- package/src/SkipNav/README.md +3 -3
- package/src/SkipNav/SkipNav.tsx +72 -32
- package/src/SkipNav/__tests__/SkipNav.basic-rendering.test.tsx +6 -0
- package/src/SkipNav/types.ts +17 -9
- package/src/Slider/README.md +37 -7
- package/src/Slider/Slider.tsx +42 -4
- package/src/Slider/SliderContext.ts +28 -1
- package/src/Slider/types.ts +157 -9
- package/src/Slot/Slot.tsx +94 -19
- package/src/Slot/__tests__/Slot.test.tsx +112 -2
- package/src/Slot/composeEventHandlers.ts +26 -2
- package/src/Slot/types.ts +16 -0
- package/src/SplitButton/README.md +225 -0
- package/src/SplitButton/SplitButton.tsx +457 -0
- package/src/SplitButton/SplitButtonContext.ts +26 -0
- package/src/SplitButton/__tests__/SplitButton.accessibility.test.tsx +55 -0
- package/src/SplitButton/__tests__/SplitButton.asChild.test.tsx +51 -0
- package/src/SplitButton/__tests__/SplitButton.basic-rendering.test.tsx +57 -0
- package/src/SplitButton/__tests__/SplitButton.data-attributes.test.tsx +28 -0
- package/src/SplitButton/__tests__/SplitButton.disabled.test.tsx +79 -0
- package/src/SplitButton/__tests__/SplitButton.error-handling.test.tsx +29 -0
- package/src/SplitButton/__tests__/SplitButton.keyboard-interaction.test.tsx +56 -0
- package/src/SplitButton/__tests__/SplitButton.state-modes.test.tsx +68 -0
- package/src/SplitButton/index.ts +2 -0
- package/src/SplitButton/types.ts +186 -0
- package/src/Status/Status.tsx +36 -15
- package/src/Status/__tests__/Status.test.tsx +5 -0
- package/src/Status/types.ts +12 -1
- package/src/Switch/README.md +1 -1
- package/src/Switch/Switch.tsx +17 -4
- package/src/Switch/__tests__/Switch.basic-rendering.test.tsx +7 -0
- package/src/Switch/hooks/useSwitchRoot.ts +3 -0
- package/src/Switch/types.ts +49 -22
- package/src/Table/README.md +110 -8
- package/src/Table/Table.tsx +246 -16
- package/src/Table/TableExpandableContext.ts +7 -0
- package/src/Table/__tests__/Table.DetailRow.test.tsx +83 -0
- package/src/Table/__tests__/Table.ExpandTrigger.test.tsx +102 -0
- package/src/Table/__tests__/Table.Expandable.test.tsx +121 -0
- package/src/Table/types.ts +191 -17
- package/src/Tabs/README.md +4 -4
- package/src/Tabs/Tabs.tsx +13 -4
- package/src/Tabs/__tests__/Tabs.activation-mode.test.tsx +58 -0
- package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +15 -0
- package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +24 -0
- package/src/Tabs/__tests__/Tabs.disabled-tabs.test.tsx +36 -0
- package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +17 -0
- package/src/Tabs/hooks/useTabsContent.ts +5 -0
- package/src/Tabs/hooks/useTabsRoot.ts +29 -5
- package/src/Tabs/hooks/useTabsTrigger.ts +7 -2
- package/src/Tabs/types.ts +29 -4
- package/src/Textarea/Textarea.tsx +9 -1
- package/src/Textarea/__tests__/Textarea.basic-rendering.test.tsx +5 -0
- package/src/Textarea/types.ts +20 -3
- package/src/Toggle/Toggle.tsx +51 -13
- package/src/Toggle/__tests__/Toggle.basic-rendering.test.tsx +5 -0
- package/src/Toggle/types.ts +54 -4
- package/src/ToggleGroup/README.md +4 -4
- package/src/ToggleGroup/ToggleGroup.tsx +14 -1
- package/src/ToggleGroup/__tests__/ToggleGroup.asChild.test.tsx +20 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.basic-rendering.test.tsx +9 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.dynamic-items.test.tsx +70 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.error-handling.test.tsx +23 -0
- package/src/ToggleGroup/__tests__/ToggleGroup.keyboard-interaction.test.tsx +23 -1
- package/src/ToggleGroup/__tests__/ToggleGroup.ref-forwarding.test.tsx +58 -0
- package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +21 -1
- package/src/ToggleGroup/types.ts +55 -2
- package/src/Tooltip/README.md +7 -7
- package/src/Tooltip/Tooltip.tsx +100 -22
- package/src/Tooltip/__tests__/Tooltip.basic-rendering.test.tsx +50 -0
- package/src/Tooltip/__tests__/Tooltip.error-handling.test.tsx +37 -0
- package/src/Tooltip/__tests__/Tooltip.escape-hatches.test.tsx +73 -0
- package/src/Tooltip/__tests__/Tooltip.keyboard-interaction.test.tsx +134 -0
- package/src/Tooltip/__tests__/Tooltip.skip-delay.test.tsx +216 -0
- package/src/Tooltip/__tests__/Tooltip.timer-coordination.test.tsx +223 -0
- package/src/Tooltip/hooks/__tests__/useTooltipProvider.test.tsx +40 -0
- package/src/Tooltip/hooks/useTooltipContent.ts +3 -0
- package/src/Tooltip/hooks/useTooltipProvider.ts +46 -8
- package/src/Tooltip/hooks/useTooltipRoot.ts +30 -6
- package/src/Tooltip/types.ts +89 -8
- package/src/Tree/README.md +69 -5
- package/src/Tree/Tree.tsx +188 -34
- package/src/Tree/__tests__/Tree.styled-wrapper.test.tsx +159 -0
- package/src/Tree/hooks/useTreePath.ts +33 -1
- package/src/Tree/index.ts +6 -1
- package/src/Tree/types.ts +54 -12
- package/src/Tree/utils.ts +46 -4
- package/src/VisuallyHidden/VisuallyHidden.tsx +33 -8
- package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +15 -1
- package/src/VisuallyHidden/types.ts +11 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useTypeahead.ts +95 -0
- package/src/index.ts +10 -0
- package/src/test/intersectionObserverPolyfill.ts +7 -0
- package/src/test/resizeObserverPolyfill.ts +80 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.reading.test.tsx +31 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.resilience.test.tsx +97 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.ssr.test.tsx +20 -0
- package/src/useLocalStorage/__tests__/useLocalStorage.writing.test.tsx +72 -0
- package/src/useLocalStorage/index.ts +1 -0
- package/src/useLocalStorage/useLocalStorage.ts +140 -0
- package/src/useMediaQuery/README.md +66 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.matching.test.tsx +42 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.ssr.test.tsx +19 -0
- package/src/useMediaQuery/__tests__/useMediaQuery.subscription.test.tsx +89 -0
- package/src/useMediaQuery/index.ts +1 -0
- package/src/useMediaQuery/useMediaQuery.ts +49 -0
- package/src/usePagination/README.md +170 -0
- package/src/usePagination/__tests__/usePagination.navigation.test.tsx +109 -0
- package/src/usePagination/__tests__/usePagination.page-count.test.tsx +56 -0
- package/src/usePagination/__tests__/usePagination.page-state.test.tsx +87 -0
- package/src/usePagination/__tests__/usePagination.range.test.tsx +82 -0
- package/src/usePagination/__tests__/usePagination.slice.test.tsx +59 -0
- package/src/usePagination/__tests__/usePagination.windowing.test.tsx +68 -0
- package/src/usePagination/index.ts +1 -0
- package/src/usePagination/usePagination.ts +292 -0
- package/src/utils/focusable.ts +15 -0
- package/src/utils/getKeyToActionMap.ts +1 -1
- package/src/utils/index.ts +1 -0
package/src/ContextMenu/types.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { Direction } from "../DirectionProvider/index.ts";
|
|
|
8
8
|
* plus the reading-direction control.
|
|
9
9
|
*/
|
|
10
10
|
export type ContextMenuRootBaseProps = {
|
|
11
|
+
/** The {@link ContextMenu.Trigger} and {@link ContextMenu.Content} pair
|
|
12
|
+
* (Root renders no wrapping element of its own). */
|
|
11
13
|
children?: ReactNode;
|
|
12
14
|
/**
|
|
13
15
|
* Reading direction for the menu. Affects which arrow key opens / closes
|
|
@@ -24,8 +26,14 @@ export type ContextMenuRootBaseProps = {
|
|
|
24
26
|
* optional and `open` is forbidden.
|
|
25
27
|
*/
|
|
26
28
|
export type ContextMenuRootUncontrolledProps = ContextMenuRootBaseProps & {
|
|
29
|
+
/** Whether the menu is open on first render.
|
|
30
|
+
* @default false */
|
|
27
31
|
defaultOpen?: boolean;
|
|
32
|
+
/** Forbidden in uncontrolled mode — use `defaultOpen` instead. */
|
|
28
33
|
open?: never;
|
|
34
|
+
/** Observes open-state transitions. Fires only on user-driven changes
|
|
35
|
+
* (right-click, Escape, selection, outside click), never on external
|
|
36
|
+
* flips. Optional in uncontrolled mode. */
|
|
29
37
|
onOpenChange?: (open: boolean) => void;
|
|
30
38
|
};
|
|
31
39
|
|
|
@@ -35,8 +43,13 @@ export type ContextMenuRootUncontrolledProps = ContextMenuRootBaseProps & {
|
|
|
35
43
|
* forbidden.
|
|
36
44
|
*/
|
|
37
45
|
export type ContextMenuRootControlledProps = ContextMenuRootBaseProps & {
|
|
46
|
+
/** Forbidden in controlled mode — use `open` instead. */
|
|
38
47
|
defaultOpen?: never;
|
|
48
|
+
/** Whether the menu is open. Must be kept in sync by the parent via
|
|
49
|
+
* `onOpenChange`. */
|
|
39
50
|
open: boolean;
|
|
51
|
+
/** Called with the requested open state on each user-driven transition.
|
|
52
|
+
* Required in controlled mode. */
|
|
40
53
|
onOpenChange: (open: boolean) => void;
|
|
41
54
|
};
|
|
42
55
|
|
|
@@ -56,9 +69,18 @@ export type ContextMenuRootProps =
|
|
|
56
69
|
* onto a custom element and `disabled` to suppress the gesture.
|
|
57
70
|
*/
|
|
58
71
|
export type ContextMenuTriggerProps = ComponentProps<"span"> & {
|
|
72
|
+
/** The content the right-click gesture is bound to. */
|
|
59
73
|
children?: ReactNode;
|
|
74
|
+
/** Forwarded to the underlying `HTMLSpanElement` (or the `asChild` host). */
|
|
60
75
|
ref?: Ref<HTMLSpanElement>;
|
|
76
|
+
/** Render the child element instead of the default `<span>`, merging the
|
|
77
|
+
* trigger's `contextmenu` handler and data-attributes onto it via the
|
|
78
|
+
* {@link Slot} pattern. The child must accept a `ref`.
|
|
79
|
+
* @default false */
|
|
61
80
|
asChild?: boolean;
|
|
81
|
+
/** When `true`, the trigger ignores the `contextmenu` gesture entirely,
|
|
82
|
+
* letting the native browser menu through. Exposed as `data-disabled=""`.
|
|
83
|
+
* @default false */
|
|
62
84
|
disabled?: boolean;
|
|
63
85
|
};
|
|
64
86
|
|
|
@@ -69,10 +91,17 @@ export type ContextMenuTriggerProps = ComponentProps<"span"> & {
|
|
|
69
91
|
*/
|
|
70
92
|
export type ContextMenuContentProps = Omit<
|
|
71
93
|
ComponentProps<"menu">,
|
|
72
|
-
"role" | "popover" | "id"
|
|
94
|
+
"role" | "popover" | "id" | "ref"
|
|
73
95
|
> & {
|
|
96
|
+
/** The menu items — {@link ContextMenuItem}, {@link ContextMenuGroup},
|
|
97
|
+
* {@link ContextMenuSub}, and friends. */
|
|
74
98
|
children?: ReactNode;
|
|
99
|
+
/** Forwarded to the underlying `HTMLMenuElement` (or the `asChild` host). */
|
|
75
100
|
ref?: Ref<HTMLMenuElement>;
|
|
101
|
+
/** Render the child element instead of the default `<menu>`, merging the
|
|
102
|
+
* managed `role` / `popover` / positioning props and the keyboard handler
|
|
103
|
+
* onto it via the {@link Slot} pattern.
|
|
104
|
+
* @default false */
|
|
76
105
|
asChild?: boolean;
|
|
77
106
|
};
|
|
78
107
|
|
|
@@ -85,9 +114,19 @@ export type ContextMenuItemProps = Omit<
|
|
|
85
114
|
ComponentProps<"li">,
|
|
86
115
|
"role" | "tabIndex" | "onSelect"
|
|
87
116
|
> & {
|
|
117
|
+
/** The item's visible content. */
|
|
88
118
|
children?: ReactNode;
|
|
119
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
89
120
|
ref?: Ref<HTMLLIElement>;
|
|
121
|
+
/** Render the child element instead of the default `<li role="menuitem">`,
|
|
122
|
+
* merging the item's props onto it via the {@link Slot} pattern (e.g. to
|
|
123
|
+
* render a menu item as an `<a>`).
|
|
124
|
+
* @default false */
|
|
90
125
|
asChild?: boolean;
|
|
126
|
+
/** Removes the item from activation and marks it `aria-disabled`; it
|
|
127
|
+
* still renders for assistive technology but no-ops on click / Enter, and
|
|
128
|
+
* arrow navigation and typeahead skip it.
|
|
129
|
+
* @default false */
|
|
91
130
|
disabled?: boolean;
|
|
92
131
|
/**
|
|
93
132
|
* Fires when the item is activated (click, Enter, or Space). Called
|
|
@@ -103,8 +142,14 @@ export type ContextMenuItemProps = Omit<
|
|
|
103
142
|
* `asChild` merges the props onto a custom element.
|
|
104
143
|
*/
|
|
105
144
|
export type ContextMenuSeparatorProps = Omit<ComponentProps<"li">, "role"> & {
|
|
145
|
+
/** Usually empty — a separator renders no content by default. */
|
|
106
146
|
children?: ReactNode;
|
|
147
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
107
148
|
ref?: Ref<HTMLLIElement>;
|
|
149
|
+
/** Render the child element instead of the default
|
|
150
|
+
* `<li role="separator">`, merging the managed `role` onto it via the
|
|
151
|
+
* {@link Slot} pattern.
|
|
152
|
+
* @default false */
|
|
108
153
|
asChild?: boolean;
|
|
109
154
|
};
|
|
110
155
|
|
|
@@ -114,8 +159,14 @@ export type ContextMenuSeparatorProps = Omit<ComponentProps<"li">, "role"> & {
|
|
|
114
159
|
* `role` is omitted; `asChild` merges the props onto a custom element.
|
|
115
160
|
*/
|
|
116
161
|
export type ContextMenuGroupProps = Omit<ComponentProps<"li">, "role"> & {
|
|
162
|
+
/** The grouped items, optionally led by a {@link ContextMenu.Label}. */
|
|
117
163
|
children?: ReactNode;
|
|
164
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
118
165
|
ref?: Ref<HTMLLIElement>;
|
|
166
|
+
/** Render the child element instead of the default `<li role="group">`
|
|
167
|
+
* (which otherwise wraps an inner `<ul role="none">`), merging the group's
|
|
168
|
+
* props onto it via the {@link Slot} pattern.
|
|
169
|
+
* @default false */
|
|
119
170
|
asChild?: boolean;
|
|
120
171
|
};
|
|
121
172
|
|
|
@@ -125,8 +176,13 @@ export type ContextMenuGroupProps = Omit<ComponentProps<"li">, "role"> & {
|
|
|
125
176
|
* onto a custom element.
|
|
126
177
|
*/
|
|
127
178
|
export type ContextMenuLabelProps = ComponentProps<"li"> & {
|
|
179
|
+
/** The label text. */
|
|
128
180
|
children?: ReactNode;
|
|
181
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
129
182
|
ref?: Ref<HTMLLIElement>;
|
|
183
|
+
/** Render the child element instead of the default `<li>`, merging the
|
|
184
|
+
* (auto-wired) `id` onto it via the {@link Slot} pattern.
|
|
185
|
+
* @default false */
|
|
130
186
|
asChild?: boolean;
|
|
131
187
|
};
|
|
132
188
|
|
|
@@ -140,9 +196,19 @@ export type ContextMenuCheckboxItemBaseProps = Omit<
|
|
|
140
196
|
ComponentProps<"li">,
|
|
141
197
|
"role" | "tabIndex" | "aria-checked" | "defaultChecked" | "onSelect"
|
|
142
198
|
> & {
|
|
199
|
+
/** The item's visible content, typically including a
|
|
200
|
+
* {@link ContextMenuItemIndicator}. */
|
|
143
201
|
children?: ReactNode;
|
|
202
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
144
203
|
ref?: Ref<HTMLLIElement>;
|
|
204
|
+
/** Render the child element instead of the default
|
|
205
|
+
* `<li role="menuitemcheckbox">`, merging the item's props onto it via
|
|
206
|
+
* the {@link Slot} pattern.
|
|
207
|
+
* @default false */
|
|
145
208
|
asChild?: boolean;
|
|
209
|
+
/** Removes the item from activation and marks it `aria-disabled`; it
|
|
210
|
+
* still renders for assistive technology but no-ops on click / Enter.
|
|
211
|
+
* @default false */
|
|
146
212
|
disabled?: boolean;
|
|
147
213
|
/**
|
|
148
214
|
* Fires when activation completes and the auto-close fires. Call
|
|
@@ -159,8 +225,14 @@ export type ContextMenuCheckboxItemBaseProps = Omit<
|
|
|
159
225
|
*/
|
|
160
226
|
export type ContextMenuCheckboxItemUncontrolledProps =
|
|
161
227
|
ContextMenuCheckboxItemBaseProps & {
|
|
228
|
+
/** Checked state on first render. Accepts the tri-state
|
|
229
|
+
* {@link CheckedState} (`true` / `false` / `"indeterminate"`).
|
|
230
|
+
* @default false */
|
|
162
231
|
defaultChecked?: CheckedState;
|
|
232
|
+
/** Forbidden in uncontrolled mode — use `defaultChecked` instead. */
|
|
163
233
|
checked?: never;
|
|
234
|
+
/** Called with the resolved boolean checked state on each toggle.
|
|
235
|
+
* Optional in uncontrolled mode. */
|
|
164
236
|
onCheckedChange?: (checked: boolean) => void;
|
|
165
237
|
};
|
|
166
238
|
|
|
@@ -171,8 +243,14 @@ export type ContextMenuCheckboxItemUncontrolledProps =
|
|
|
171
243
|
*/
|
|
172
244
|
export type ContextMenuCheckboxItemControlledProps =
|
|
173
245
|
ContextMenuCheckboxItemBaseProps & {
|
|
246
|
+
/** Forbidden in controlled mode — use `checked` instead. */
|
|
174
247
|
defaultChecked?: never;
|
|
248
|
+
/** The current checked state. Accepts the tri-state {@link CheckedState}
|
|
249
|
+
* (`true` / `false` / `"indeterminate"`, the last rendered as
|
|
250
|
+
* `aria-checked="mixed"`). Must be kept in sync via `onCheckedChange`. */
|
|
175
251
|
checked: CheckedState;
|
|
252
|
+
/** Called with the resolved boolean checked state on each toggle.
|
|
253
|
+
* Required in controlled mode. */
|
|
176
254
|
onCheckedChange: (checked: boolean) => void;
|
|
177
255
|
};
|
|
178
256
|
|
|
@@ -193,12 +271,19 @@ export type ContextMenuCheckboxItemProps =
|
|
|
193
271
|
* onto a custom element.
|
|
194
272
|
*/
|
|
195
273
|
export type ContextMenuItemIndicatorProps = ComponentProps<"span"> & {
|
|
274
|
+
/** The mark to show — usually a checkmark or radio-dot icon. */
|
|
196
275
|
children?: ReactNode;
|
|
276
|
+
/** Forwarded to the underlying `HTMLSpanElement` (or the `asChild` host). */
|
|
197
277
|
ref?: Ref<HTMLSpanElement>;
|
|
278
|
+
/** Render the child element instead of the default `<span>`, merging the
|
|
279
|
+
* `data-state` attribute onto it via the {@link Slot} pattern (e.g. to
|
|
280
|
+
* compose onto an SVG icon).
|
|
281
|
+
* @default false */
|
|
198
282
|
asChild?: boolean;
|
|
199
283
|
/**
|
|
200
284
|
* Render the indicator even when its parent item is unchecked. The
|
|
201
285
|
* `data-state` attribute still reflects the live state.
|
|
286
|
+
* @default false
|
|
202
287
|
*/
|
|
203
288
|
forceMount?: boolean;
|
|
204
289
|
};
|
|
@@ -206,14 +291,22 @@ export type ContextMenuItemIndicatorProps = ComponentProps<"span"> & {
|
|
|
206
291
|
/**
|
|
207
292
|
* Shared base for both {@link ContextMenuRadioGroupProps} variants — the
|
|
208
293
|
* `<li>` host props plus `children`, `ref`, and `asChild`. The managed
|
|
209
|
-
* `role` host attribute is omitted
|
|
294
|
+
* `role` host attribute is omitted, along with the native `<li>` `value`
|
|
295
|
+
* and `defaultValue` attributes: the variants below re-declare both as the
|
|
296
|
+
* radio-group's selection state (`string`), narrowing the native
|
|
297
|
+
* `string | number | readonly string[]`. They must be `Omit`-ted here or
|
|
298
|
+
* the docs-data extractor silently drops the narrowed declaration (the
|
|
299
|
+
* §1.16 narrow-without-omit rule).
|
|
210
300
|
*/
|
|
211
301
|
export type ContextMenuRadioGroupBaseProps = Omit<
|
|
212
302
|
ComponentProps<"li">,
|
|
213
|
-
"role"
|
|
303
|
+
"role" | "value" | "defaultValue"
|
|
214
304
|
> & {
|
|
215
305
|
children?: ReactNode;
|
|
216
306
|
ref?: Ref<HTMLLIElement>;
|
|
307
|
+
/** Render the child element instead of the default `<li role="group">`,
|
|
308
|
+
* merging the group's props onto it via the {@link Slot} pattern.
|
|
309
|
+
* @default false */
|
|
217
310
|
asChild?: boolean;
|
|
218
311
|
};
|
|
219
312
|
|
|
@@ -225,8 +318,12 @@ export type ContextMenuRadioGroupBaseProps = Omit<
|
|
|
225
318
|
*/
|
|
226
319
|
export type ContextMenuRadioGroupUncontrolledProps =
|
|
227
320
|
ContextMenuRadioGroupBaseProps & {
|
|
321
|
+
/** Value of the {@link ContextMenuRadioItem} selected on first render. */
|
|
228
322
|
defaultValue?: string;
|
|
323
|
+
/** Forbidden in uncontrolled mode — use `defaultValue` instead. */
|
|
229
324
|
value?: never;
|
|
325
|
+
/** Called with the newly-selected item's `value` on each change.
|
|
326
|
+
* Optional in uncontrolled mode. */
|
|
230
327
|
onValueChange?: (value: string) => void;
|
|
231
328
|
};
|
|
232
329
|
|
|
@@ -237,8 +334,13 @@ export type ContextMenuRadioGroupUncontrolledProps =
|
|
|
237
334
|
*/
|
|
238
335
|
export type ContextMenuRadioGroupControlledProps =
|
|
239
336
|
ContextMenuRadioGroupBaseProps & {
|
|
337
|
+
/** Forbidden in controlled mode — use `value` instead. */
|
|
240
338
|
defaultValue?: never;
|
|
339
|
+
/** The `value` of the currently-selected {@link ContextMenuRadioItem}.
|
|
340
|
+
* Must be kept in sync by the parent via `onValueChange`. */
|
|
241
341
|
value: string;
|
|
342
|
+
/** Called with the newly-selected item's `value` on each change.
|
|
343
|
+
* Required in controlled mode. */
|
|
242
344
|
onValueChange: (value: string) => void;
|
|
243
345
|
};
|
|
244
346
|
|
|
@@ -256,17 +358,32 @@ export type ContextMenuRadioGroupProps =
|
|
|
256
358
|
* Props for {@link ContextMenu.RadioItem} — a mutually-exclusive choice
|
|
257
359
|
* within a {@link ContextMenu.RadioGroup}, identified by its required
|
|
258
360
|
* `value`. The managed `role`, `tabIndex`, `aria-checked`, and `onSelect`
|
|
259
|
-
* host attributes are omitted
|
|
361
|
+
* host attributes are omitted, as is the native `<li>` `value` attribute:
|
|
362
|
+
* the required `value: string` below narrows it (from the native
|
|
363
|
+
* `string | number | readonly string[]`), so it must be `Omit`-ted or the
|
|
364
|
+
* docs-data extractor silently drops it (the §1.16 narrow-without-omit
|
|
365
|
+
* rule).
|
|
260
366
|
*/
|
|
261
367
|
export type ContextMenuRadioItemProps = Omit<
|
|
262
368
|
ComponentProps<"li">,
|
|
263
|
-
"role" | "tabIndex" | "aria-checked" | "onSelect"
|
|
369
|
+
"role" | "tabIndex" | "aria-checked" | "onSelect" | "value"
|
|
264
370
|
> & {
|
|
265
371
|
children?: ReactNode;
|
|
266
372
|
ref?: Ref<HTMLLIElement>;
|
|
373
|
+
/** Render the child element instead of the default `<li role="menuitemradio">`,
|
|
374
|
+
* merging the item's props onto it via the {@link Slot} pattern.
|
|
375
|
+
* @default false */
|
|
267
376
|
asChild?: boolean;
|
|
377
|
+
/** Removes the item from activation and marks it `aria-disabled`; it
|
|
378
|
+
* still renders for assistive technology but no-ops on click / Enter.
|
|
379
|
+
* @default false */
|
|
268
380
|
disabled?: boolean;
|
|
381
|
+
/** Identifies this choice within the enclosing
|
|
382
|
+
* {@link ContextMenuRadioGroup}. When it matches the group's active
|
|
383
|
+
* value, the item is checked. */
|
|
269
384
|
value: string;
|
|
385
|
+
/** Fires when the item is activated (click, Enter, or Space). Call
|
|
386
|
+
* `event.preventDefault()` to skip the auto-close after selection. */
|
|
270
387
|
onSelect?: (event: Event) => void;
|
|
271
388
|
};
|
|
272
389
|
|
|
@@ -275,6 +392,8 @@ export type ContextMenuRadioItemProps = Omit<
|
|
|
275
392
|
* `children` of the submenu.
|
|
276
393
|
*/
|
|
277
394
|
export type ContextMenuSubBaseProps = {
|
|
395
|
+
/** The {@link ContextMenu.SubTrigger} and {@link ContextMenu.SubContent}
|
|
396
|
+
* pair (Sub renders no wrapping element of its own). */
|
|
278
397
|
children?: ReactNode;
|
|
279
398
|
};
|
|
280
399
|
|
|
@@ -284,8 +403,12 @@ export type ContextMenuSubBaseProps = {
|
|
|
284
403
|
* is optional and the controlled `open` prop is forbidden.
|
|
285
404
|
*/
|
|
286
405
|
export type ContextMenuSubUncontrolledProps = ContextMenuSubBaseProps & {
|
|
406
|
+
/** Whether the submenu is open on first render.
|
|
407
|
+
* @default false */
|
|
287
408
|
defaultOpen?: boolean;
|
|
409
|
+
/** Forbidden in uncontrolled mode — use `defaultOpen` instead. */
|
|
288
410
|
open?: never;
|
|
411
|
+
/** Observes submenu open-state transitions. Optional in uncontrolled mode. */
|
|
289
412
|
onOpenChange?: (open: boolean) => void;
|
|
290
413
|
};
|
|
291
414
|
|
|
@@ -295,8 +418,12 @@ export type ContextMenuSubUncontrolledProps = ContextMenuSubBaseProps & {
|
|
|
295
418
|
* `defaultOpen` is forbidden.
|
|
296
419
|
*/
|
|
297
420
|
export type ContextMenuSubControlledProps = ContextMenuSubBaseProps & {
|
|
421
|
+
/** Forbidden in controlled mode — use `open` instead. */
|
|
298
422
|
defaultOpen?: never;
|
|
423
|
+
/** Whether the submenu is open. Must be kept in sync via `onOpenChange`. */
|
|
299
424
|
open: boolean;
|
|
425
|
+
/** Called with the requested open state on each transition.
|
|
426
|
+
* Required in controlled mode. */
|
|
300
427
|
onOpenChange: (open: boolean) => void;
|
|
301
428
|
};
|
|
302
429
|
|
|
@@ -320,9 +447,18 @@ export type ContextMenuSubTriggerProps = Omit<
|
|
|
320
447
|
ComponentProps<"li">,
|
|
321
448
|
"role" | "tabIndex" | "aria-haspopup" | "aria-expanded" | "aria-controls"
|
|
322
449
|
> & {
|
|
450
|
+
/** The trigger's visible content (typically the submenu's name). */
|
|
323
451
|
children?: ReactNode;
|
|
452
|
+
/** Forwarded to the underlying `HTMLLIElement` (or the `asChild` host). */
|
|
324
453
|
ref?: Ref<HTMLLIElement>;
|
|
454
|
+
/** Render the child element instead of the default
|
|
455
|
+
* `<li role="menuitem">`, merging the submenu-wiring ARIA and handlers
|
|
456
|
+
* onto it via the {@link Slot} pattern.
|
|
457
|
+
* @default false */
|
|
325
458
|
asChild?: boolean;
|
|
459
|
+
/** When `true`, the trigger refuses to open the submenu on both click
|
|
460
|
+
* and the inline-forward arrow key, and is marked `aria-disabled`.
|
|
461
|
+
* @default false */
|
|
326
462
|
disabled?: boolean;
|
|
327
463
|
};
|
|
328
464
|
|
|
@@ -334,9 +470,15 @@ export type ContextMenuSubTriggerProps = Omit<
|
|
|
334
470
|
*/
|
|
335
471
|
export type ContextMenuSubContentProps = Omit<
|
|
336
472
|
ComponentProps<"menu">,
|
|
337
|
-
"role" | "popover" | "id"
|
|
473
|
+
"role" | "popover" | "id" | "ref"
|
|
338
474
|
> & {
|
|
475
|
+
/** The submenu's items. */
|
|
339
476
|
children?: ReactNode;
|
|
477
|
+
/** Forwarded to the underlying `HTMLMenuElement` (or the `asChild` host). */
|
|
340
478
|
ref?: Ref<HTMLMenuElement>;
|
|
479
|
+
/** Render the child element instead of the default `<menu>`, merging the
|
|
480
|
+
* managed `role` / `popover` / `id` and the keyboard handler onto it via
|
|
481
|
+
* the {@link Slot} pattern.
|
|
482
|
+
* @default false */
|
|
341
483
|
asChild?: boolean;
|
|
342
484
|
};
|
|
@@ -5,20 +5,52 @@ import { DirectionProviderProps } from "./types";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Broadcasts a reading direction to every descendant so direction-aware
|
|
8
|
-
* components can inherit it instead of each being passed
|
|
9
|
-
* `dir` prop.
|
|
8
|
+
* components can inherit it through context instead of each being passed
|
|
9
|
+
* an explicit `dir` prop.
|
|
10
10
|
*
|
|
11
|
-
* Renders **no DOM** — only a context provider.
|
|
12
|
-
* inferred from the DOM; the consumer still owns
|
|
13
|
-
* `<html>` (or another element) for
|
|
14
|
-
*
|
|
15
|
-
* to
|
|
11
|
+
* Renders **no DOM host element** — only a React context provider.
|
|
12
|
+
* Direction is never inferred from the DOM; the consumer still owns
|
|
13
|
+
* setting `dir` on their `<html>` (or another ancestor element) for
|
|
14
|
+
* CSS purposes. This component only propagates the {@link Direction}
|
|
15
|
+
* value to `@primitiv-ui/react` components.
|
|
16
|
+
*
|
|
17
|
+
* **Override precedence.** A descendant component's own `dir` prop
|
|
18
|
+
* always wins over the inherited value; components fall back to
|
|
19
|
+
* {@link useDirection} only when their `dir` prop is omitted:
|
|
20
|
+
*
|
|
21
|
+
* ```tsx
|
|
22
|
+
* <DirectionProvider dir="rtl">
|
|
23
|
+
* {/* inherits rtl *\/}
|
|
24
|
+
* <Tabs.Root defaultValue="a">...</Tabs.Root>
|
|
25
|
+
* {/* explicit ltr overrides the provider *\/}
|
|
26
|
+
* <Tabs.Root dir="ltr" defaultValue="a">...</Tabs.Root>
|
|
27
|
+
* </DirectionProvider>
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* **Nesting.** Providers nest — an inner `DirectionProvider` overrides an
|
|
31
|
+
* outer one for its subtree.
|
|
32
|
+
*
|
|
33
|
+
* **`useDirection` hook.** Direction-aware sub-components read the
|
|
34
|
+
* inherited value via {@link useDirection}, which falls back to `"ltr"`
|
|
35
|
+
* when no provider is present.
|
|
16
36
|
*
|
|
17
37
|
* @example Declare direction once near the app root
|
|
18
38
|
* ```tsx
|
|
39
|
+
* import { DirectionProvider } from "@primitiv-ui/react";
|
|
40
|
+
*
|
|
41
|
+
* <DirectionProvider dir="rtl">
|
|
42
|
+
* <Tabs.Root defaultValue="overview">...</Tabs.Root>
|
|
43
|
+
* <Slider.Root defaultValue={[50]} aria-label="Volume" />
|
|
44
|
+
* </DirectionProvider>
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example Nested providers — inner overrides outer for its subtree
|
|
48
|
+
* ```tsx
|
|
19
49
|
* <DirectionProvider dir="rtl">
|
|
20
|
-
* <Tabs.Root
|
|
21
|
-
* <
|
|
50
|
+
* <Tabs.Root defaultValue="a">...</Tabs.Root>
|
|
51
|
+
* <DirectionProvider dir="ltr">
|
|
52
|
+
* <Tabs.Root defaultValue="b">...</Tabs.Root>
|
|
53
|
+
* </DirectionProvider>
|
|
22
54
|
* </DirectionProvider>
|
|
23
55
|
* ```
|
|
24
56
|
*/
|
|
@@ -12,7 +12,7 @@ Renders **no DOM** — only a React context provider.
|
|
|
12
12
|
import { DirectionProvider } from "@primitiv-ui/react";
|
|
13
13
|
|
|
14
14
|
<DirectionProvider dir="rtl">
|
|
15
|
-
<Tabs.Root defaultValue="overview"
|
|
15
|
+
<Tabs.Root defaultValue="overview">...</Tabs.Root>
|
|
16
16
|
<Slider.Root defaultValue={[50]} aria-label="Volume" />
|
|
17
17
|
</DirectionProvider>;
|
|
18
18
|
```
|
|
@@ -23,9 +23,9 @@ components fall back to the provider only when `dir` is omitted:
|
|
|
23
23
|
```tsx
|
|
24
24
|
<DirectionProvider dir="rtl">
|
|
25
25
|
{/* inherits rtl */}
|
|
26
|
-
<Tabs.Root defaultValue="a"
|
|
26
|
+
<Tabs.Root defaultValue="a">...</Tabs.Root>
|
|
27
27
|
{/* explicit ltr overrides the provider */}
|
|
28
|
-
<Tabs.Root dir="ltr" defaultValue="a"
|
|
28
|
+
<Tabs.Root dir="ltr" defaultValue="a">...</Tabs.Root>
|
|
29
29
|
</DirectionProvider>;
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -48,7 +48,7 @@ import { useDirection } from "@primitiv-ui/react";
|
|
|
48
48
|
|
|
49
49
|
function MyControl({ dir }: { dir?: "ltr" | "rtl" }) {
|
|
50
50
|
const resolvedDir = dir ?? useDirection();
|
|
51
|
-
//
|
|
51
|
+
// ...
|
|
52
52
|
}
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -26,4 +26,9 @@ describe("DirectionProvider", () => {
|
|
|
26
26
|
// Assert
|
|
27
27
|
expect(screen.getByTestId("probe")).toHaveTextContent("rtl");
|
|
28
28
|
});
|
|
29
|
+
|
|
30
|
+
it('sets displayName to "DirectionProvider" for React DevTools and stack traces', () => {
|
|
31
|
+
// Assert — an empty displayName would render it as an anonymous component.
|
|
32
|
+
expect(DirectionProvider.displayName).toBe("DirectionProvider");
|
|
33
|
+
});
|
|
29
34
|
});
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* A reading direction value — left-to-right or right-to-left.
|
|
5
|
+
*
|
|
6
|
+
* Used as the {@link DirectionProviderProps.dir | `dir`} prop on
|
|
7
|
+
* {@link DirectionProvider} and as the `dir` prop accepted by every
|
|
8
|
+
* direction-aware component (e.g. `Tabs.Root`, `Slider.Root`).
|
|
9
|
+
* {@link useDirection} returns this type.
|
|
10
|
+
*/
|
|
4
11
|
export type Direction = "ltr" | "rtl";
|
|
5
12
|
|
|
6
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Props for {@link DirectionProvider} — the reading direction broadcast to
|
|
15
|
+
* all descendant components.
|
|
16
|
+
*
|
|
17
|
+
* `DirectionProvider` accepts no native HTML element props: it renders no
|
|
18
|
+
* DOM host element and is a pure React context provider.
|
|
19
|
+
*/
|
|
7
20
|
export type DirectionProviderProps = {
|
|
8
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* The reading direction to broadcast to every descendant.
|
|
23
|
+
* See {@link Direction}.
|
|
24
|
+
*
|
|
25
|
+
* Direction-aware components (e.g. `Tabs.Root`, `Slider.Root`) read
|
|
26
|
+
* this value via {@link useDirection} when their own `dir` prop is
|
|
27
|
+
* omitted. An explicit `dir` prop on a descendant always takes
|
|
28
|
+
* precedence over the inherited value.
|
|
29
|
+
*/
|
|
9
30
|
dir: Direction;
|
|
31
|
+
/**
|
|
32
|
+
* The subtree whose direction-aware components will inherit `dir`.
|
|
33
|
+
* Any React content is accepted; there is no DOM wrapper.
|
|
34
|
+
*/
|
|
10
35
|
children?: ReactNode;
|
|
11
36
|
};
|
package/src/Divider/Divider.tsx
CHANGED
|
@@ -3,29 +3,38 @@ import type { ReactElement } from "react";
|
|
|
3
3
|
import { DividerProps } from "./types";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* A
|
|
6
|
+
* A headless `<span role="separator">` that marks a visual and semantic
|
|
7
|
+
* boundary between content sections.
|
|
7
8
|
*
|
|
8
|
-
* Renders a `<span role="separator"
|
|
9
|
-
* attribute. Screen readers announce it as a separator
|
|
10
|
-
* appropriate when the divider conveys structural meaning
|
|
11
|
-
* navigation groups or distinct content
|
|
9
|
+
* Renders a native `<span>` with `role="separator"` and the matching
|
|
10
|
+
* `aria-orientation` attribute. Screen readers announce it as a separator,
|
|
11
|
+
* which is appropriate when the divider conveys genuine structural meaning
|
|
12
|
+
* (e.g. separating navigation groups or distinct content areas).
|
|
12
13
|
*
|
|
13
14
|
* **Decorative use.** When the divider is purely visual and carries no
|
|
14
15
|
* semantic meaning, pass `aria-hidden="true"` to remove it from the
|
|
15
|
-
* accessibility tree:
|
|
16
|
+
* accessibility tree entirely:
|
|
16
17
|
*
|
|
17
18
|
* ```tsx
|
|
18
19
|
* <Divider aria-hidden="true" />
|
|
19
20
|
* ```
|
|
20
21
|
*
|
|
21
|
-
* **Styling hooks.** No styles ship with the component.
|
|
22
|
-
* `
|
|
22
|
+
* **Styling hooks.** No styles ship with the component. Because Divider
|
|
23
|
+
* emits no `data-*` attributes, target the rendered element via the
|
|
24
|
+
* `aria-orientation` attribute selector or a `className`:
|
|
23
25
|
*
|
|
24
26
|
* ```css
|
|
25
|
-
* [role="separator"][aria-orientation="horizontal"] { height: 1px; width: 100%; }
|
|
26
|
-
* [role="separator"][aria-orientation="vertical"] { width: 1px; height: 100%; }
|
|
27
|
+
* [role="separator"][aria-orientation="horizontal"] { height: 1px; width: 100%; background: currentColor; }
|
|
28
|
+
* [role="separator"][aria-orientation="vertical"] { width: 1px; height: 100%; background: currentColor; }
|
|
27
29
|
* ```
|
|
28
30
|
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <Divider className="my-divider" />
|
|
33
|
+
* <Divider orientation="vertical" className="my-divider--vertical" />
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @extends HTMLSpanElement
|
|
37
|
+
*
|
|
29
38
|
* @example Horizontal (default)
|
|
30
39
|
* ```tsx
|
|
31
40
|
* <Divider />
|
|
@@ -40,6 +49,11 @@ import { DividerProps } from "./types";
|
|
|
40
49
|
* ```tsx
|
|
41
50
|
* <Divider aria-hidden="true" />
|
|
42
51
|
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example With a className
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <Divider className="my-section-rule" />
|
|
56
|
+
* ```
|
|
43
57
|
*/
|
|
44
58
|
export function Divider({
|
|
45
59
|
orientation = "horizontal",
|
|
@@ -12,7 +12,7 @@ import { Divider } from "../Divider";
|
|
|
12
12
|
* and asserted against the rendered headless component* so it can never drift
|
|
13
13
|
* from what the component actually emits. Divider has **no** data-* surface — it
|
|
14
14
|
* styles off `aria-orientation` — so the guard also pins that hook: the registry
|
|
15
|
-
* stylesheet's `[aria-orientation="
|
|
15
|
+
* stylesheet's `[aria-orientation="..."]` selectors depend on it.
|
|
16
16
|
*/
|
|
17
17
|
const contractPath = resolve(
|
|
18
18
|
dirname(fileURLToPath(import.meta.url)),
|
|
@@ -38,4 +38,9 @@ describe("Divider component", () => {
|
|
|
38
38
|
const divider = screen.getByRole("separator");
|
|
39
39
|
expect(divider).toHaveAttribute("class", "");
|
|
40
40
|
});
|
|
41
|
+
|
|
42
|
+
it('sets displayName to "Divider" for React DevTools and stack traces', () => {
|
|
43
|
+
// Assert — an empty displayName would render it as an anonymous component.
|
|
44
|
+
expect(Divider.displayName).toBe("Divider");
|
|
45
|
+
});
|
|
41
46
|
});
|
package/src/Divider/types.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { ComponentProps } from "react";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Props for
|
|
5
|
-
*
|
|
4
|
+
* Props for {@link Divider} — all native `<span>` attributes plus an
|
|
5
|
+
* `orientation` that controls both the visual axis and the `aria-orientation`
|
|
6
|
+
* value announced to assistive technology.
|
|
6
7
|
*/
|
|
7
8
|
export type DividerProps = ComponentProps<"span"> & {
|
|
8
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Axis the separator runs along. Sets `aria-orientation` on the rendered
|
|
11
|
+
* `<span role="separator">` so screen readers announce the correct
|
|
12
|
+
* orientation. Use `"horizontal"` for row-dividing rules and
|
|
13
|
+
* `"vertical"` for column-dividing rules.
|
|
14
|
+
* @default "horizontal"
|
|
15
|
+
*/
|
|
9
16
|
orientation?: "horizontal" | "vertical";
|
|
10
17
|
};
|