@primitiv-ui/react 0.1.38 → 0.1.39
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 +24 -2
- package/dist/AccessibleIcon/AccessibleIcon.d.ts +51 -0
- package/dist/AccessibleIcon/AccessibleIcon.js +55 -0
- package/dist/AccessibleIcon/index.d.ts +2 -0
- package/dist/AccessibleIcon/index.js +2 -0
- package/dist/AccessibleIcon/types.d.ts +24 -0
- package/dist/AccessibleIcon/types.js +1 -0
- package/dist/Accordion/Accordion.d.ts +287 -0
- package/dist/Accordion/Accordion.js +330 -0
- package/dist/Accordion/AccordionContext.d.ts +3 -0
- package/dist/Accordion/AccordionContext.js +4 -0
- package/dist/Accordion/hooks/index.d.ts +6 -0
- package/dist/Accordion/hooks/index.js +6 -0
- package/dist/Accordion/hooks/useAccordionContext.d.ts +1 -0
- package/dist/Accordion/hooks/useAccordionContext.js +1 -0
- package/dist/Accordion/hooks/useAccordionHeaderContext.d.ts +1 -0
- package/dist/Accordion/hooks/useAccordionHeaderContext.js +10 -0
- package/dist/Accordion/hooks/useAccordionItem.d.ts +8 -0
- package/dist/Accordion/hooks/useAccordionItem.js +15 -0
- package/dist/Accordion/hooks/useAccordionItemContext.d.ts +1 -0
- package/dist/Accordion/hooks/useAccordionItemContext.js +1 -0
- package/dist/Accordion/hooks/useAccordionRoot.d.ts +16 -0
- package/dist/Accordion/hooks/useAccordionRoot.js +133 -0
- package/dist/Accordion/hooks/useAccordionTrigger.d.ts +298 -0
- package/dist/Accordion/hooks/useAccordionTrigger.js +73 -0
- package/dist/Accordion/index.d.ts +2 -0
- package/dist/Accordion/index.js +2 -0
- package/dist/Accordion/types.d.ts +152 -0
- package/dist/Accordion/types.js +1 -0
- package/dist/Alert/Alert.d.ts +64 -0
- package/dist/Alert/Alert.js +70 -0
- package/dist/Alert/index.d.ts +2 -0
- package/dist/Alert/index.js +2 -0
- package/dist/Alert/types.d.ts +21 -0
- package/dist/Alert/types.js +1 -0
- package/dist/Avatar/Avatar.d.ts +144 -0
- package/dist/Avatar/Avatar.js +187 -0
- package/dist/Avatar/AvatarContext.d.ts +16 -0
- package/dist/Avatar/AvatarContext.js +7 -0
- package/dist/Avatar/hooks/index.d.ts +2 -0
- package/dist/Avatar/hooks/index.js +2 -0
- package/dist/Avatar/hooks/useAvatarContext.d.ts +1 -0
- package/dist/Avatar/hooks/useAvatarContext.js +1 -0
- package/dist/Avatar/hooks/useAvatarImage.d.ts +21 -0
- package/dist/Avatar/hooks/useAvatarImage.js +47 -0
- package/dist/Avatar/index.d.ts +3 -0
- package/dist/Avatar/index.js +3 -0
- package/dist/Avatar/types.d.ts +52 -0
- package/dist/Avatar/types.js +1 -0
- package/dist/Breadcrumb/Breadcrumb.d.ts +280 -0
- package/dist/Breadcrumb/Breadcrumb.js +299 -0
- package/dist/Breadcrumb/index.d.ts +2 -0
- package/dist/Breadcrumb/index.js +2 -0
- package/dist/Breadcrumb/types.d.ts +81 -0
- package/dist/Breadcrumb/types.js +1 -0
- package/dist/Button/Button.d.ts +73 -0
- package/dist/Button/Button.js +84 -0
- package/dist/Button/index.d.ts +2 -0
- package/dist/Button/index.js +2 -0
- package/dist/Button/types.d.ts +32 -0
- package/dist/Button/types.js +1 -0
- package/dist/Carousel/Carousel.d.ts +498 -0
- package/dist/Carousel/Carousel.js +660 -0
- package/dist/Carousel/CarouselContext.d.ts +7 -0
- package/dist/Carousel/CarouselContext.js +8 -0
- package/dist/Carousel/hooks/index.d.ts +5 -0
- package/dist/Carousel/hooks/index.js +5 -0
- package/dist/Carousel/hooks/useCarouselContext.d.ts +1 -0
- package/dist/Carousel/hooks/useCarouselContext.js +10 -0
- package/dist/Carousel/hooks/useCarouselLoop.d.ts +39 -0
- package/dist/Carousel/hooks/useCarouselLoop.js +735 -0
- package/dist/Carousel/hooks/useCarouselRoot.d.ts +97 -0
- package/dist/Carousel/hooks/useCarouselRoot.js +545 -0
- package/dist/Carousel/hooks/useCarouselSlide.d.ts +24 -0
- package/dist/Carousel/hooks/useCarouselSlide.js +62 -0
- package/dist/Carousel/hooks/useCarouselViewport.d.ts +46 -0
- package/dist/Carousel/hooks/useCarouselViewport.js +786 -0
- package/dist/Carousel/index.d.ts +3 -0
- package/dist/Carousel/index.js +3 -0
- package/dist/Carousel/loopEngine.d.ts +26 -0
- package/dist/Carousel/loopEngine.js +48 -0
- package/dist/Carousel/types.d.ts +783 -0
- package/dist/Carousel/types.js +1 -0
- package/dist/Checkbox/Checkbox.d.ts +120 -0
- package/dist/Checkbox/Checkbox.js +155 -0
- package/dist/Checkbox/CheckboxContext.d.ts +13 -0
- package/dist/Checkbox/CheckboxContext.js +3 -0
- package/dist/Checkbox/hooks/index.d.ts +3 -0
- package/dist/Checkbox/hooks/index.js +3 -0
- package/dist/Checkbox/hooks/useCheckboxContext.d.ts +1 -0
- package/dist/Checkbox/hooks/useCheckboxContext.js +1 -0
- package/dist/Checkbox/hooks/useCheckboxInput.d.ts +33 -0
- package/dist/Checkbox/hooks/useCheckboxInput.js +37 -0
- package/dist/Checkbox/hooks/useCheckboxRoot.d.ts +11 -0
- package/dist/Checkbox/hooks/useCheckboxRoot.js +14 -0
- package/dist/Checkbox/index.d.ts +2 -0
- package/dist/Checkbox/index.js +2 -0
- package/dist/Checkbox/types.d.ts +74 -0
- package/dist/Checkbox/types.js +1 -0
- package/dist/CheckboxCard/CheckboxCard.d.ts +132 -0
- package/dist/CheckboxCard/CheckboxCard.js +175 -0
- package/dist/CheckboxCard/CheckboxCardContext.d.ts +15 -0
- package/dist/CheckboxCard/CheckboxCardContext.js +10 -0
- package/dist/CheckboxCard/hooks/index.d.ts +2 -0
- package/dist/CheckboxCard/hooks/index.js +2 -0
- package/dist/CheckboxCard/hooks/useCheckboxCardContext.d.ts +1 -0
- package/dist/CheckboxCard/hooks/useCheckboxCardContext.js +1 -0
- package/dist/CheckboxCard/hooks/useCheckboxCardRoot.d.ts +11 -0
- package/dist/CheckboxCard/hooks/useCheckboxCardRoot.js +12 -0
- package/dist/CheckboxCard/index.d.ts +3 -0
- package/dist/CheckboxCard/index.js +3 -0
- package/dist/CheckboxCard/types.d.ts +87 -0
- package/dist/CheckboxCard/types.js +1 -0
- package/dist/Collapsible/Collapsible.d.ts +243 -0
- package/dist/Collapsible/Collapsible.js +275 -0
- package/dist/Collapsible/CollapsibleContext.d.ts +2 -0
- package/dist/Collapsible/CollapsibleContext.js +3 -0
- package/dist/Collapsible/hooks/index.d.ts +2 -0
- package/dist/Collapsible/hooks/index.js +2 -0
- package/dist/Collapsible/hooks/useCollapsibleRoot.d.ts +9 -0
- package/dist/Collapsible/hooks/useCollapsibleRoot.js +18 -0
- package/dist/Collapsible/hooks/useCollapsibleTrigger.d.ts +299 -0
- package/dist/Collapsible/hooks/useCollapsibleTrigger.js +39 -0
- package/dist/Collapsible/index.d.ts +2 -0
- package/dist/Collapsible/index.js +2 -0
- package/dist/Collapsible/types.d.ts +134 -0
- package/dist/Collapsible/types.js +1 -0
- package/dist/Combobox/Combobox.d.ts +149 -0
- package/dist/Combobox/Combobox.js +355 -0
- package/dist/Combobox/ComboboxContext.d.ts +10 -0
- package/dist/Combobox/ComboboxContext.js +13 -0
- package/dist/Combobox/hooks/index.d.ts +1 -0
- package/dist/Combobox/hooks/index.js +1 -0
- package/dist/Combobox/hooks/useComboboxRoot.d.ts +1 -0
- package/dist/Combobox/hooks/useComboboxRoot.js +1 -0
- package/dist/Combobox/index.d.ts +3 -0
- package/dist/Combobox/index.js +3 -0
- package/dist/Combobox/types.d.ts +126 -0
- package/dist/Combobox/types.js +1 -0
- package/dist/ContextMenu/ContextMenu.d.ts +508 -0
- package/dist/ContextMenu/ContextMenu.js +1005 -0
- package/dist/ContextMenu/ContextMenuContentContext.d.ts +12 -0
- package/dist/ContextMenu/ContextMenuContentContext.js +3 -0
- package/dist/ContextMenu/ContextMenuContext.d.ts +16 -0
- package/dist/ContextMenu/ContextMenuContext.js +3 -0
- package/dist/ContextMenu/ContextMenuGroupContext.d.ts +4 -0
- package/dist/ContextMenu/ContextMenuGroupContext.js +3 -0
- package/dist/ContextMenu/ContextMenuItemIndicatorContext.d.ts +4 -0
- package/dist/ContextMenu/ContextMenuItemIndicatorContext.js +3 -0
- package/dist/ContextMenu/ContextMenuRadioGroupContext.d.ts +5 -0
- package/dist/ContextMenu/ContextMenuRadioGroupContext.js +3 -0
- package/dist/ContextMenu/ContextMenuSubContext.d.ts +8 -0
- package/dist/ContextMenu/ContextMenuSubContext.js +3 -0
- package/dist/ContextMenu/constants.d.ts +2 -0
- package/dist/ContextMenu/constants.js +3 -0
- package/dist/ContextMenu/index.d.ts +2 -0
- package/dist/ContextMenu/index.js +2 -0
- package/dist/ContextMenu/types.d.ts +424 -0
- package/dist/ContextMenu/types.js +1 -0
- package/dist/DirectionProvider/DirectionContext.d.ts +15 -0
- package/dist/DirectionProvider/DirectionContext.js +18 -0
- package/dist/DirectionProvider/DirectionProvider.d.ts +57 -0
- package/dist/DirectionProvider/DirectionProvider.js +59 -0
- package/dist/DirectionProvider/index.d.ts +3 -0
- package/dist/DirectionProvider/index.js +2 -0
- package/dist/DirectionProvider/types.d.ts +34 -0
- package/dist/DirectionProvider/types.js +1 -0
- package/dist/Divider/Divider.d.ts +59 -0
- package/dist/Divider/Divider.js +60 -0
- package/dist/Divider/index.d.ts +2 -0
- package/dist/Divider/index.js +2 -0
- package/dist/Divider/types.d.ts +16 -0
- package/dist/Divider/types.js +1 -0
- package/dist/Drawer/Drawer.d.ts +268 -0
- package/dist/Drawer/Drawer.js +271 -0
- package/dist/Drawer/index.d.ts +2 -0
- package/dist/Drawer/index.js +2 -0
- package/dist/Drawer/types.d.ts +45 -0
- package/dist/Drawer/types.js +1 -0
- package/dist/Dropdown/Dropdown.d.ts +476 -0
- package/dist/Dropdown/Dropdown.js +745 -0
- package/dist/Dropdown/DropdownContentContext.d.ts +12 -0
- package/dist/Dropdown/DropdownContentContext.js +3 -0
- package/dist/Dropdown/DropdownContext.d.ts +10 -0
- package/dist/Dropdown/DropdownContext.js +3 -0
- package/dist/Dropdown/DropdownGroupContext.d.ts +4 -0
- package/dist/Dropdown/DropdownGroupContext.js +3 -0
- package/dist/Dropdown/DropdownItemIndicatorContext.d.ts +9 -0
- package/dist/Dropdown/DropdownItemIndicatorContext.js +3 -0
- package/dist/Dropdown/DropdownRadioGroupContext.d.ts +5 -0
- package/dist/Dropdown/DropdownRadioGroupContext.js +3 -0
- package/dist/Dropdown/DropdownSubContext.d.ts +8 -0
- package/dist/Dropdown/DropdownSubContext.js +3 -0
- package/dist/Dropdown/constants.d.ts +2 -0
- package/dist/Dropdown/constants.js +3 -0
- package/dist/Dropdown/hooks/index.d.ts +9 -0
- package/dist/Dropdown/hooks/index.js +9 -0
- package/dist/Dropdown/hooks/useCloseSiblingSub.d.ts +7 -0
- package/dist/Dropdown/hooks/useCloseSiblingSub.js +13 -0
- package/dist/Dropdown/hooks/useDropdownContent.d.ts +296 -0
- package/dist/Dropdown/hooks/useDropdownContent.js +149 -0
- package/dist/Dropdown/hooks/useDropdownContext.d.ts +1 -0
- package/dist/Dropdown/hooks/useDropdownContext.js +1 -0
- package/dist/Dropdown/hooks/useDropdownGroup.d.ts +294 -0
- package/dist/Dropdown/hooks/useDropdownGroup.js +12 -0
- package/dist/Dropdown/hooks/useDropdownItem.d.ts +13 -0
- package/dist/Dropdown/hooks/useDropdownItem.js +34 -0
- package/dist/Dropdown/hooks/useDropdownLabel.d.ts +292 -0
- package/dist/Dropdown/hooks/useDropdownLabel.js +8 -0
- package/dist/Dropdown/hooks/useDropdownRoot.d.ts +19 -0
- package/dist/Dropdown/hooks/useDropdownRoot.js +25 -0
- package/dist/Dropdown/hooks/useDropdownSubContext.d.ts +1 -0
- package/dist/Dropdown/hooks/useDropdownSubContext.js +1 -0
- package/dist/Dropdown/hooks/useDropdownTrigger.d.ts +302 -0
- package/dist/Dropdown/hooks/useDropdownTrigger.js +18 -0
- package/dist/Dropdown/index.d.ts +2 -0
- package/dist/Dropdown/index.js +2 -0
- package/dist/Dropdown/types.d.ts +496 -0
- package/dist/Dropdown/types.js +1 -0
- package/dist/EmptyState/EmptyState.d.ts +246 -0
- package/dist/EmptyState/EmptyState.js +268 -0
- package/dist/EmptyState/index.d.ts +2 -0
- package/dist/EmptyState/index.js +2 -0
- package/dist/EmptyState/types.d.ts +59 -0
- package/dist/EmptyState/types.js +1 -0
- package/dist/Field/Field.d.ts +178 -0
- package/dist/Field/Field.js +211 -0
- package/dist/Field/FieldContext.d.ts +15 -0
- package/dist/Field/FieldContext.js +3 -0
- package/dist/Field/hooks/index.d.ts +2 -0
- package/dist/Field/hooks/index.js +2 -0
- package/dist/Field/hooks/useFieldContext.d.ts +1 -0
- package/dist/Field/hooks/useFieldContext.js +1 -0
- package/dist/Field/hooks/useFieldProps.d.ts +25 -0
- package/dist/Field/hooks/useFieldProps.js +39 -0
- package/dist/Field/index.d.ts +2 -0
- package/dist/Field/index.js +2 -0
- package/dist/Field/types.d.ts +81 -0
- package/dist/Field/types.js +1 -0
- package/dist/Fieldset/Fieldset.d.ts +124 -0
- package/dist/Fieldset/Fieldset.js +124 -0
- package/dist/Fieldset/index.d.ts +2 -0
- package/dist/Fieldset/index.js +2 -0
- package/dist/Fieldset/types.d.ts +23 -0
- package/dist/Fieldset/types.js +1 -0
- package/dist/Input/Input.d.ts +104 -0
- package/dist/Input/Input.js +116 -0
- package/dist/Input/index.d.ts +2 -0
- package/dist/Input/index.js +2 -0
- package/dist/Input/types.d.ts +27 -0
- package/dist/Input/types.js +1 -0
- package/dist/InputGroup/InputGroup.d.ts +176 -0
- package/dist/InputGroup/InputGroup.js +205 -0
- package/dist/InputGroup/index.d.ts +2 -0
- package/dist/InputGroup/index.js +2 -0
- package/dist/InputGroup/types.d.ts +41 -0
- package/dist/InputGroup/types.js +1 -0
- package/dist/Listbox/Listbox.d.ts +231 -0
- package/dist/Listbox/Listbox.js +339 -0
- package/dist/Listbox/ListboxContext.d.ts +19 -0
- package/dist/Listbox/ListboxContext.js +25 -0
- package/dist/Listbox/constants.d.ts +2 -0
- package/dist/Listbox/constants.js +3 -0
- package/dist/Listbox/hooks/index.d.ts +1 -0
- package/dist/Listbox/hooks/index.js +1 -0
- package/dist/Listbox/hooks/useListboxRoot.d.ts +39 -0
- package/dist/Listbox/hooks/useListboxRoot.js +299 -0
- package/dist/Listbox/index.d.ts +3 -0
- package/dist/Listbox/index.js +3 -0
- package/dist/Listbox/types.d.ts +214 -0
- package/dist/Listbox/types.js +1 -0
- package/dist/MillerColumns/MillerColumns.d.ts +309 -0
- package/dist/MillerColumns/MillerColumns.js +332 -0
- package/dist/MillerColumns/MillerColumnsContext.d.ts +4 -0
- package/dist/MillerColumns/MillerColumnsContext.js +5 -0
- package/dist/MillerColumns/constants.d.ts +2 -0
- package/dist/MillerColumns/constants.js +3 -0
- package/dist/MillerColumns/hooks/index.d.ts +7 -0
- package/dist/MillerColumns/hooks/index.js +7 -0
- package/dist/MillerColumns/hooks/useMillerColumnsColumn.d.ts +8 -0
- package/dist/MillerColumns/hooks/useMillerColumnsColumn.js +16 -0
- package/dist/MillerColumns/hooks/useMillerColumnsColumnContext.d.ts +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsColumnContext.js +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsContext.d.ts +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsContext.js +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsItem.d.ts +295 -0
- package/dist/MillerColumns/hooks/useMillerColumnsItem.js +122 -0
- package/dist/MillerColumns/hooks/useMillerColumnsItemContext.d.ts +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsItemContext.js +1 -0
- package/dist/MillerColumns/hooks/useMillerColumnsResizeHandle.d.ts +290 -0
- package/dist/MillerColumns/hooks/useMillerColumnsResizeHandle.js +105 -0
- package/dist/MillerColumns/hooks/useMillerColumnsRoot.d.ts +9 -0
- package/dist/MillerColumns/hooks/useMillerColumnsRoot.js +0 -0
- package/dist/MillerColumns/index.d.ts +4 -0
- package/dist/MillerColumns/index.js +4 -0
- package/dist/MillerColumns/types.d.ts +224 -0
- package/dist/MillerColumns/types.js +1 -0
- package/dist/MillerColumns/useMillerColumnsSelection.d.ts +21 -0
- package/dist/MillerColumns/useMillerColumnsSelection.js +28 -0
- package/dist/MillerColumns/utils.d.ts +62 -0
- package/dist/MillerColumns/utils.js +102 -0
- package/dist/Modal/Modal.d.ts +331 -0
- package/dist/Modal/Modal.js +386 -0
- package/dist/Modal/ModalContext.d.ts +9 -0
- package/dist/Modal/ModalContext.js +10 -0
- package/dist/Modal/hooks/index.d.ts +4 -0
- package/dist/Modal/hooks/index.js +4 -0
- package/dist/Modal/hooks/useModalContent.d.ts +5 -0
- package/dist/Modal/hooks/useModalContent.js +94 -0
- package/dist/Modal/hooks/useModalContext.d.ts +1 -0
- package/dist/Modal/hooks/useModalContext.js +1 -0
- package/dist/Modal/hooks/useModalRoot.d.ts +11 -0
- package/dist/Modal/hooks/useModalRoot.js +39 -0
- package/dist/Modal/hooks/useModalTrigger.d.ts +297 -0
- package/dist/Modal/hooks/useModalTrigger.js +18 -0
- package/dist/Modal/index.d.ts +3 -0
- package/dist/Modal/index.js +3 -0
- package/dist/Modal/types.d.ts +186 -0
- package/dist/Modal/types.js +1 -0
- package/dist/NavigationMenu/NavigationMenu.d.ts +495 -0
- package/dist/NavigationMenu/NavigationMenu.js +645 -0
- package/dist/NavigationMenu/NavigationMenuContext.d.ts +31 -0
- package/dist/NavigationMenu/NavigationMenuContext.js +34 -0
- package/dist/NavigationMenu/constants.d.ts +4 -0
- package/dist/NavigationMenu/constants.js +5 -0
- package/dist/NavigationMenu/hooks/index.d.ts +7 -0
- package/dist/NavigationMenu/hooks/index.js +7 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuEntry.d.ts +13 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuEntry.js +21 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuIndicator.d.ts +16 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuIndicator.js +53 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuLink.d.ts +8 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuLink.js +37 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuRoot.d.ts +26 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuRoot.js +202 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuTopLevelEntry.d.ts +21 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuTopLevelEntry.js +54 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuTrigger.d.ts +16 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuTrigger.js +100 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuViewport.d.ts +21 -0
- package/dist/NavigationMenu/hooks/useNavigationMenuViewport.js +85 -0
- package/dist/NavigationMenu/index.d.ts +3 -0
- package/dist/NavigationMenu/index.js +3 -0
- package/dist/NavigationMenu/types.d.ts +236 -0
- package/dist/NavigationMenu/types.js +1 -0
- package/dist/NavigationMenu/utils.d.ts +37 -0
- package/dist/NavigationMenu/utils.js +64 -0
- package/dist/Popover/Popover.d.ts +239 -0
- package/dist/Popover/Popover.js +293 -0
- package/dist/Popover/PopoverContext.d.ts +4 -0
- package/dist/Popover/PopoverContext.js +5 -0
- package/dist/Popover/hooks/index.d.ts +3 -0
- package/dist/Popover/hooks/index.js +3 -0
- package/dist/Popover/hooks/usePopoverContent.d.ts +19 -0
- package/dist/Popover/hooks/usePopoverContent.js +83 -0
- package/dist/Popover/hooks/usePopoverRoot.d.ts +10 -0
- package/dist/Popover/hooks/usePopoverRoot.js +49 -0
- package/dist/Popover/hooks/usePopoverTrigger.d.ts +297 -0
- package/dist/Popover/hooks/usePopoverTrigger.js +19 -0
- package/dist/Popover/index.d.ts +2 -0
- package/dist/Popover/index.js +2 -0
- package/dist/Popover/types.d.ts +183 -0
- package/dist/Popover/types.js +1 -0
- package/dist/Portal/Portal.d.ts +70 -0
- package/dist/Portal/Portal.js +92 -0
- package/dist/Portal/index.d.ts +2 -0
- package/dist/Portal/index.js +2 -0
- package/dist/Portal/types.d.ts +14 -0
- package/dist/Portal/types.js +1 -0
- package/dist/Progress/Progress.d.ts +126 -0
- package/dist/Progress/Progress.js +172 -0
- package/dist/Progress/ProgressContext.d.ts +16 -0
- package/dist/Progress/ProgressContext.js +7 -0
- package/dist/Progress/hooks/index.d.ts +2 -0
- package/dist/Progress/hooks/index.js +2 -0
- package/dist/Progress/hooks/useProgressContext.d.ts +1 -0
- package/dist/Progress/hooks/useProgressContext.js +1 -0
- package/dist/Progress/hooks/useProgressRoot.d.ts +17 -0
- package/dist/Progress/hooks/useProgressRoot.js +22 -0
- package/dist/Progress/index.d.ts +3 -0
- package/dist/Progress/index.js +3 -0
- package/dist/Progress/types.d.ts +53 -0
- package/dist/Progress/types.js +1 -0
- package/dist/Radio/Radio.d.ts +128 -0
- package/dist/Radio/Radio.js +153 -0
- package/dist/Radio/RadioContext.d.ts +13 -0
- package/dist/Radio/RadioContext.js +3 -0
- package/dist/Radio/hooks/index.d.ts +2 -0
- package/dist/Radio/hooks/index.js +2 -0
- package/dist/Radio/hooks/useRadioContext.d.ts +1 -0
- package/dist/Radio/hooks/useRadioContext.js +1 -0
- package/dist/Radio/hooks/useRadioRoot.d.ts +32 -0
- package/dist/Radio/hooks/useRadioRoot.js +35 -0
- package/dist/Radio/index.d.ts +2 -0
- package/dist/Radio/index.js +2 -0
- package/dist/Radio/types.d.ts +79 -0
- package/dist/Radio/types.js +1 -0
- package/dist/RadioCard/RadioCard.d.ts +176 -0
- package/dist/RadioCard/RadioCard.js +264 -0
- package/dist/RadioCard/RadioCardContext.d.ts +21 -0
- package/dist/RadioCard/RadioCardContext.js +9 -0
- package/dist/RadioCard/RadioCardItemContext.d.ts +14 -0
- package/dist/RadioCard/RadioCardItemContext.js +10 -0
- package/dist/RadioCard/hooks/index.d.ts +3 -0
- package/dist/RadioCard/hooks/index.js +3 -0
- package/dist/RadioCard/hooks/useRadioCardContext.d.ts +1 -0
- package/dist/RadioCard/hooks/useRadioCardContext.js +1 -0
- package/dist/RadioCard/hooks/useRadioCardItemContext.d.ts +1 -0
- package/dist/RadioCard/hooks/useRadioCardItemContext.js +1 -0
- package/dist/RadioCard/hooks/useRadioCardRoot.d.ts +14 -0
- package/dist/RadioCard/hooks/useRadioCardRoot.js +42 -0
- package/dist/RadioCard/index.d.ts +4 -0
- package/dist/RadioCard/index.js +4 -0
- package/dist/RadioCard/types.d.ts +129 -0
- package/dist/RadioCard/types.js +1 -0
- package/dist/RadioGroup/RadioGroup.d.ts +192 -0
- package/dist/RadioGroup/RadioGroup.js +281 -0
- package/dist/RadioGroup/RadioGroupContext.d.ts +12 -0
- package/dist/RadioGroup/RadioGroupContext.js +3 -0
- package/dist/RadioGroup/RadioGroupItemContext.d.ts +4 -0
- package/dist/RadioGroup/RadioGroupItemContext.js +3 -0
- package/dist/RadioGroup/hooks/index.d.ts +3 -0
- package/dist/RadioGroup/hooks/index.js +3 -0
- package/dist/RadioGroup/hooks/useRadioGroupContext.d.ts +1 -0
- package/dist/RadioGroup/hooks/useRadioGroupContext.js +1 -0
- package/dist/RadioGroup/hooks/useRadioGroupItemContext.d.ts +1 -0
- package/dist/RadioGroup/hooks/useRadioGroupItemContext.js +1 -0
- package/dist/RadioGroup/hooks/useRadioGroupRoot.d.ts +14 -0
- package/dist/RadioGroup/hooks/useRadioGroupRoot.js +53 -0
- package/dist/RadioGroup/index.d.ts +2 -0
- package/dist/RadioGroup/index.js +2 -0
- package/dist/RadioGroup/types.d.ts +130 -0
- package/dist/RadioGroup/types.js +1 -0
- package/dist/SegmentedControl/SegmentedControl.d.ts +145 -0
- package/dist/SegmentedControl/SegmentedControl.js +229 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +14 -0
- package/dist/SegmentedControl/SegmentedControlContext.js +3 -0
- package/dist/SegmentedControl/hooks/index.d.ts +2 -0
- package/dist/SegmentedControl/hooks/index.js +2 -0
- package/dist/SegmentedControl/hooks/useSegmentedControlContext.d.ts +1 -0
- package/dist/SegmentedControl/hooks/useSegmentedControlContext.js +1 -0
- package/dist/SegmentedControl/hooks/useSegmentedControlRoot.d.ts +14 -0
- package/dist/SegmentedControl/hooks/useSegmentedControlRoot.js +45 -0
- package/dist/SegmentedControl/index.d.ts +2 -0
- package/dist/SegmentedControl/index.js +2 -0
- package/dist/SegmentedControl/types.d.ts +121 -0
- package/dist/SegmentedControl/types.js +1 -0
- package/dist/Select/Select.d.ts +390 -0
- package/dist/Select/Select.js +561 -0
- package/dist/Select/SelectContext.d.ts +31 -0
- package/dist/Select/SelectContext.js +3 -0
- package/dist/Select/SelectItemIndicatorContext.d.ts +23 -0
- package/dist/Select/SelectItemIndicatorContext.js +3 -0
- package/dist/Select/constants.d.ts +6 -0
- package/dist/Select/constants.js +7 -0
- package/dist/Select/hooks/index.d.ts +2 -0
- package/dist/Select/hooks/index.js +2 -0
- package/dist/Select/hooks/useSelectContent.d.ts +301 -0
- package/dist/Select/hooks/useSelectContent.js +134 -0
- package/dist/Select/hooks/useSelectRoot.d.ts +23 -0
- package/dist/Select/hooks/useSelectRoot.js +90 -0
- package/dist/Select/index.d.ts +2 -0
- package/dist/Select/index.js +2 -0
- package/dist/Select/types.d.ts +246 -0
- package/dist/Select/types.js +1 -0
- package/dist/SkipNav/SkipNav.d.ts +137 -0
- package/dist/SkipNav/SkipNav.js +138 -0
- package/dist/SkipNav/index.d.ts +1 -0
- package/dist/SkipNav/index.js +1 -0
- package/dist/SkipNav/types.d.ts +32 -0
- package/dist/SkipNav/types.js +1 -0
- package/dist/Slider/Slider.d.ts +189 -0
- package/dist/Slider/Slider.js +253 -0
- package/dist/Slider/SliderContext.d.ts +48 -0
- package/dist/Slider/SliderContext.js +7 -0
- package/dist/Slider/hooks/index.d.ts +3 -0
- package/dist/Slider/hooks/index.js +3 -0
- package/dist/Slider/hooks/useSliderContext.d.ts +1 -0
- package/dist/Slider/hooks/useSliderContext.js +1 -0
- package/dist/Slider/hooks/useSliderRoot.d.ts +23 -0
- package/dist/Slider/hooks/useSliderRoot.js +123 -0
- package/dist/Slider/hooks/useSliderThumb.d.ts +11 -0
- package/dist/Slider/hooks/useSliderThumb.js +57 -0
- package/dist/Slider/index.d.ts +3 -0
- package/dist/Slider/index.js +3 -0
- package/dist/Slider/types.d.ts +194 -0
- package/dist/Slider/types.js +1 -0
- package/dist/Slider/utils.d.ts +48 -0
- package/dist/Slider/utils.js +105 -0
- package/dist/Slot/Slot.d.ts +126 -0
- package/dist/Slot/Slot.js +210 -0
- package/dist/Slot/composeEventHandlers.d.ts +50 -0
- package/dist/Slot/composeEventHandlers.js +57 -0
- package/dist/Slot/index.d.ts +3 -0
- package/dist/Slot/index.js +3 -0
- package/dist/Slot/types.d.ts +20 -0
- package/dist/Slot/types.js +1 -0
- package/dist/SplitButton/SplitButton.d.ts +286 -0
- package/dist/SplitButton/SplitButton.js +343 -0
- package/dist/SplitButton/SplitButtonContext.d.ts +11 -0
- package/dist/SplitButton/SplitButtonContext.js +12 -0
- package/dist/SplitButton/index.d.ts +2 -0
- package/dist/SplitButton/index.js +1 -0
- package/dist/SplitButton/types.d.ts +161 -0
- package/dist/SplitButton/types.js +1 -0
- package/dist/Status/Status.d.ts +57 -0
- package/dist/Status/Status.js +63 -0
- package/dist/Status/index.d.ts +2 -0
- package/dist/Status/index.js +2 -0
- package/dist/Status/types.d.ts +19 -0
- package/dist/Status/types.js +1 -0
- package/dist/Switch/Switch.d.ts +122 -0
- package/dist/Switch/Switch.js +143 -0
- package/dist/Switch/SwitchContext.d.ts +12 -0
- package/dist/Switch/SwitchContext.js +7 -0
- package/dist/Switch/hooks/index.d.ts +2 -0
- package/dist/Switch/hooks/index.js +2 -0
- package/dist/Switch/hooks/useSwitchContext.d.ts +1 -0
- package/dist/Switch/hooks/useSwitchContext.js +1 -0
- package/dist/Switch/hooks/useSwitchRoot.d.ts +30 -0
- package/dist/Switch/hooks/useSwitchRoot.js +33 -0
- package/dist/Switch/index.d.ts +3 -0
- package/dist/Switch/index.js +3 -0
- package/dist/Switch/types.d.ts +83 -0
- package/dist/Switch/types.js +1 -0
- package/dist/Table/Table.d.ts +443 -0
- package/dist/Table/Table.js +494 -0
- package/dist/Table/TableExpandableContext.d.ts +2 -0
- package/dist/Table/TableExpandableContext.js +3 -0
- package/dist/Table/index.d.ts +2 -0
- package/dist/Table/index.js +2 -0
- package/dist/Table/types.d.ts +214 -0
- package/dist/Table/types.js +1 -0
- package/dist/Tabs/Tabs.d.ts +270 -0
- package/dist/Tabs/Tabs.js +324 -0
- package/dist/Tabs/TabsContext.d.ts +11 -0
- package/dist/Tabs/TabsContext.js +12 -0
- package/dist/Tabs/hooks/index.d.ts +4 -0
- package/dist/Tabs/hooks/index.js +4 -0
- package/dist/Tabs/hooks/useTabsContent.d.ts +10 -0
- package/dist/Tabs/hooks/useTabsContent.js +27 -0
- package/dist/Tabs/hooks/useTabsContext.d.ts +1 -0
- package/dist/Tabs/hooks/useTabsContext.js +1 -0
- package/dist/Tabs/hooks/useTabsRoot.d.ts +21 -0
- package/dist/Tabs/hooks/useTabsRoot.js +97 -0
- package/dist/Tabs/hooks/useTabsTrigger.d.ts +13 -0
- package/dist/Tabs/hooks/useTabsTrigger.js +83 -0
- package/dist/Tabs/index.d.ts +3 -0
- package/dist/Tabs/index.js +3 -0
- package/dist/Tabs/types.d.ts +139 -0
- package/dist/Tabs/types.js +1 -0
- package/dist/Tabs/utils.d.ts +4 -0
- package/dist/Tabs/utils.js +8 -0
- package/dist/Textarea/Textarea.d.ts +81 -0
- package/dist/Textarea/Textarea.js +93 -0
- package/dist/Textarea/index.d.ts +2 -0
- package/dist/Textarea/index.js +2 -0
- package/dist/Textarea/types.d.ts +27 -0
- package/dist/Textarea/types.js +1 -0
- package/dist/Toggle/Toggle.d.ts +82 -0
- package/dist/Toggle/Toggle.js +102 -0
- package/dist/Toggle/index.d.ts +2 -0
- package/dist/Toggle/index.js +2 -0
- package/dist/Toggle/types.d.ts +72 -0
- package/dist/Toggle/types.js +1 -0
- package/dist/ToggleGroup/ToggleGroup.d.ts +144 -0
- package/dist/ToggleGroup/ToggleGroup.js +227 -0
- package/dist/ToggleGroup/ToggleGroupContext.d.ts +2 -0
- package/dist/ToggleGroup/ToggleGroupContext.js +3 -0
- package/dist/ToggleGroup/hooks/index.d.ts +2 -0
- package/dist/ToggleGroup/hooks/index.js +2 -0
- package/dist/ToggleGroup/hooks/useToggleGroupContext.d.ts +1 -0
- package/dist/ToggleGroup/hooks/useToggleGroupContext.js +1 -0
- package/dist/ToggleGroup/hooks/useToggleGroupRoot.d.ts +21 -0
- package/dist/ToggleGroup/hooks/useToggleGroupRoot.js +79 -0
- package/dist/ToggleGroup/index.d.ts +2 -0
- package/dist/ToggleGroup/index.js +2 -0
- package/dist/ToggleGroup/types.d.ts +141 -0
- package/dist/ToggleGroup/types.js +1 -0
- package/dist/Tooltip/Tooltip.d.ts +231 -0
- package/dist/Tooltip/Tooltip.js +279 -0
- package/dist/Tooltip/TooltipContext.d.ts +6 -0
- package/dist/Tooltip/TooltipContext.js +7 -0
- package/dist/Tooltip/hooks/index.d.ts +4 -0
- package/dist/Tooltip/hooks/index.js +4 -0
- package/dist/Tooltip/hooks/useTooltipContent.d.ts +289 -0
- package/dist/Tooltip/hooks/useTooltipContent.js +50 -0
- package/dist/Tooltip/hooks/useTooltipProvider.d.ts +9 -0
- package/dist/Tooltip/hooks/useTooltipProvider.js +60 -0
- package/dist/Tooltip/hooks/useTooltipRoot.d.ts +6 -0
- package/dist/Tooltip/hooks/useTooltipRoot.js +100 -0
- package/dist/Tooltip/hooks/useTooltipTrigger.d.ts +299 -0
- package/dist/Tooltip/hooks/useTooltipTrigger.js +22 -0
- package/dist/Tooltip/index.d.ts +2 -0
- package/dist/Tooltip/index.js +2 -0
- package/dist/Tooltip/types.d.ts +183 -0
- package/dist/Tooltip/types.js +1 -0
- package/dist/Tree/Tree.d.ts +398 -0
- package/dist/Tree/Tree.js +536 -0
- package/dist/Tree/TreeContext.d.ts +4 -0
- package/dist/Tree/TreeContext.js +5 -0
- package/dist/Tree/hooks/index.d.ts +3 -0
- package/dist/Tree/hooks/index.js +3 -0
- package/dist/Tree/hooks/useTreeItemKeyboard.d.ts +16 -0
- package/dist/Tree/hooks/useTreeItemKeyboard.js +71 -0
- package/dist/Tree/hooks/useTreePath.d.ts +88 -0
- package/dist/Tree/hooks/useTreePath.js +96 -0
- package/dist/Tree/hooks/useTreeRoot.d.ts +19 -0
- package/dist/Tree/hooks/useTreeRoot.js +185 -0
- package/dist/Tree/index.d.ts +4 -0
- package/dist/Tree/index.js +4 -0
- package/dist/Tree/types.d.ts +269 -0
- package/dist/Tree/types.js +1 -0
- package/dist/Tree/utils.d.ts +45 -0
- package/dist/Tree/utils.js +79 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +62 -0
- package/dist/VisuallyHidden/VisuallyHidden.js +83 -0
- package/dist/VisuallyHidden/index.d.ts +2 -0
- package/dist/VisuallyHidden/index.js +2 -0
- package/dist/VisuallyHidden/types.d.ts +18 -0
- package/dist/VisuallyHidden/types.js +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/useCollection.d.ts +50 -0
- package/dist/hooks/useCollection.js +47 -0
- package/dist/hooks/useControllableState.d.ts +50 -0
- package/dist/hooks/useControllableState.js +14 -0
- package/dist/hooks/useRovingTabindex.d.ts +106 -0
- package/dist/hooks/useRovingTabindex.js +110 -0
- package/dist/hooks/useTypeahead.d.ts +31 -0
- package/dist/hooks/useTypeahead.js +65 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +50 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +1 -0
- package/dist/useLocalStorage/index.d.ts +1 -0
- package/dist/useLocalStorage/index.js +1 -0
- package/dist/useLocalStorage/useLocalStorage.d.ts +46 -0
- package/dist/useLocalStorage/useLocalStorage.js +125 -0
- package/dist/useMediaQuery/index.d.ts +1 -0
- package/dist/useMediaQuery/index.js +1 -0
- package/dist/useMediaQuery/useMediaQuery.d.ts +30 -0
- package/dist/useMediaQuery/useMediaQuery.js +43 -0
- package/dist/usePagination/index.d.ts +1 -0
- package/dist/usePagination/index.js +1 -0
- package/dist/usePagination/usePagination.d.ts +163 -0
- package/dist/usePagination/usePagination.js +130 -0
- package/dist/utils/createStrictContext.d.ts +33 -0
- package/dist/utils/createStrictContext.js +47 -0
- package/dist/utils/deriveId.d.ts +25 -0
- package/dist/utils/deriveId.js +28 -0
- package/dist/utils/focusable.d.ts +8 -0
- package/dist/utils/focusable.js +16 -0
- package/dist/utils/getKeyToActionMap.d.ts +64 -0
- package/dist/utils/getKeyToActionMap.js +49 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -0
- package/package.json +7 -6
- package/src/AccessibleIcon/AccessibleIcon.tsx +0 -67
- package/src/AccessibleIcon/README.md +0 -42
- package/src/AccessibleIcon/__tests__/AccessibleIcon.test.tsx +0 -52
- package/src/AccessibleIcon/index.ts +0 -2
- package/src/AccessibleIcon/types.ts +0 -25
- package/src/Accordion/Accordion.tsx +0 -455
- package/src/Accordion/AccordionContext.ts +0 -12
- package/src/Accordion/README.md +0 -202
- package/src/Accordion/__tests__/Accordion.asChild.test.tsx +0 -283
- package/src/Accordion/__tests__/Accordion.basic-rendering.test.tsx +0 -348
- package/src/Accordion/__tests__/Accordion.controlled-state.test.tsx +0 -175
- package/src/Accordion/__tests__/Accordion.data-attributes.test.tsx +0 -272
- package/src/Accordion/__tests__/Accordion.disabled-items.test.tsx +0 -353
- package/src/Accordion/__tests__/Accordion.error-handling.test.tsx +0 -152
- package/src/Accordion/__tests__/Accordion.forceMount.test.tsx +0 -119
- package/src/Accordion/__tests__/Accordion.keyboard-interaction.test.tsx +0 -736
- package/src/Accordion/__tests__/Accordion.mouse-interaction.test.tsx +0 -212
- package/src/Accordion/__tests__/Accordion.multiple-mode.test.tsx +0 -90
- package/src/Accordion/__tests__/Accordion.reading-direction.test.tsx +0 -139
- package/src/Accordion/__tests__/Accordion.uncontrolled-state.test.tsx +0 -154
- package/src/Accordion/hooks/index.ts +0 -6
- package/src/Accordion/hooks/useAccordionContext.ts +0 -1
- package/src/Accordion/hooks/useAccordionHeaderContext.ts +0 -10
- package/src/Accordion/hooks/useAccordionItem.ts +0 -22
- package/src/Accordion/hooks/useAccordionItemContext.ts +0 -1
- package/src/Accordion/hooks/useAccordionRoot.ts +0 -188
- package/src/Accordion/hooks/useAccordionTrigger.ts +0 -98
- package/src/Accordion/index.ts +0 -2
- package/src/Accordion/types.ts +0 -174
- package/src/Alert/Alert.tsx +0 -79
- package/src/Alert/README.md +0 -54
- package/src/Alert/__tests__/Alert.test.tsx +0 -33
- package/src/Alert/index.ts +0 -2
- package/src/Alert/types.ts +0 -22
- package/src/Avatar/Avatar.tsx +0 -246
- package/src/Avatar/AvatarContext.ts +0 -26
- package/src/Avatar/README.md +0 -116
- package/src/Avatar/__tests__/Avatar.asChild.test.tsx +0 -53
- package/src/Avatar/__tests__/Avatar.basic-rendering.test.tsx +0 -24
- package/src/Avatar/__tests__/Avatar.error-handling.test.tsx +0 -30
- package/src/Avatar/__tests__/Avatar.fallback.test.tsx +0 -105
- package/src/Avatar/__tests__/Avatar.image-loading.test.tsx +0 -116
- package/src/Avatar/hooks/index.ts +0 -2
- package/src/Avatar/hooks/useAvatarContext.ts +0 -1
- package/src/Avatar/hooks/useAvatarImage.ts +0 -56
- package/src/Avatar/index.ts +0 -3
- package/src/Avatar/types.ts +0 -56
- package/src/Breadcrumb/Breadcrumb.tsx +0 -374
- package/src/Breadcrumb/README.md +0 -158
- package/src/Breadcrumb/__tests__/Breadcrumb.asChild.test.tsx +0 -33
- package/src/Breadcrumb/__tests__/Breadcrumb.basic-rendering.test.tsx +0 -143
- package/src/Breadcrumb/__tests__/Breadcrumb.ellipsis.test.tsx +0 -110
- package/src/Breadcrumb/index.ts +0 -2
- package/src/Breadcrumb/types.ts +0 -88
- package/src/Button/Button.tsx +0 -100
- package/src/Button/README.md +0 -112
- package/src/Button/__tests__/Button.asChild.test.tsx +0 -91
- package/src/Button/__tests__/Button.basic-rendering.test.tsx +0 -132
- package/src/Button/__tests__/Button.contract.test.tsx +0 -72
- package/src/Button/__tests__/Button.disabled.test.tsx +0 -52
- package/src/Button/__tests__/Button.icon-usage.test.tsx +0 -57
- package/src/Button/__tests__/Button.keyboard-interaction.test.tsx +0 -70
- package/src/Button/index.ts +0 -2
- package/src/Button/types.ts +0 -33
- package/src/Carousel/Carousel.tsx +0 -972
- package/src/Carousel/CarouselContext.ts +0 -15
- package/src/Carousel/README.md +0 -1447
- package/src/Carousel/__tests__/Carousel.asChild.test.tsx +0 -178
- package/src/Carousel/__tests__/Carousel.auto-play.test.tsx +0 -617
- package/src/Carousel/__tests__/Carousel.autoplay-status.test.tsx +0 -239
- package/src/Carousel/__tests__/Carousel.basic-rendering.test.tsx +0 -569
- package/src/Carousel/__tests__/Carousel.controlled-state.test.tsx +0 -137
- package/src/Carousel/__tests__/Carousel.drag-status.test.tsx +0 -292
- package/src/Carousel/__tests__/Carousel.dynamic-slides.test.tsx +0 -38
- package/src/Carousel/__tests__/Carousel.error-handling.test.tsx +0 -81
- package/src/Carousel/__tests__/Carousel.ids.test.tsx +0 -111
- package/src/Carousel/__tests__/Carousel.imperative-api.test.tsx +0 -213
- package/src/Carousel/__tests__/Carousel.indicators.test.tsx +0 -661
- package/src/Carousel/__tests__/Carousel.infinite.test.tsx +0 -1453
- package/src/Carousel/__tests__/Carousel.instant-scroll.test.tsx +0 -124
- package/src/Carousel/__tests__/Carousel.intersection-observer.test.tsx +0 -364
- package/src/Carousel/__tests__/Carousel.keyboard-navigation.test.tsx +0 -158
- package/src/Carousel/__tests__/Carousel.loop.test.tsx +0 -163
- package/src/Carousel/__tests__/Carousel.loopEngine.test.ts +0 -77
- package/src/Carousel/__tests__/Carousel.mouse-drag.test.tsx +0 -504
- package/src/Carousel/__tests__/Carousel.multi-slide-bounds.test.tsx +0 -91
- package/src/Carousel/__tests__/Carousel.orientation.test.tsx +0 -207
- package/src/Carousel/__tests__/Carousel.overscroll.test.tsx +0 -532
- package/src/Carousel/__tests__/Carousel.page-snap-points.test.tsx +0 -50
- package/src/Carousel/__tests__/Carousel.play-pause.test.tsx +0 -232
- package/src/Carousel/__tests__/Carousel.prev-next.test.tsx +0 -68
- package/src/Carousel/__tests__/Carousel.progress-text.test.tsx +0 -76
- package/src/Carousel/__tests__/Carousel.reduced-motion.test.tsx +0 -46
- package/src/Carousel/__tests__/Carousel.refresh-progress.test.tsx +0 -84
- package/src/Carousel/__tests__/Carousel.scroll-margin.test.tsx +0 -167
- package/src/Carousel/__tests__/Carousel.scroll-progress.test.tsx +0 -518
- package/src/Carousel/__tests__/Carousel.scroll-snap-change.test.tsx +0 -200
- package/src/Carousel/__tests__/Carousel.scroll-sync.test.tsx +0 -322
- package/src/Carousel/__tests__/Carousel.scroll-to-index.test.tsx +0 -115
- package/src/Carousel/__tests__/Carousel.slide-snap.test.tsx +0 -172
- package/src/Carousel/__tests__/Carousel.slides-per-move.test.tsx +0 -329
- package/src/Carousel/__tests__/Carousel.slides-per-page.test.tsx +0 -267
- package/src/Carousel/__tests__/Carousel.snap-type.test.tsx +0 -35
- package/src/Carousel/__tests__/Carousel.ssr.test.tsx +0 -28
- package/src/Carousel/__tests__/Carousel.touch-interaction.test.tsx +0 -96
- package/src/Carousel/__tests__/Carousel.transition-modes.test.tsx +0 -95
- package/src/Carousel/__tests__/Carousel.translations.test.tsx +0 -180
- package/src/Carousel/__tests__/Carousel.uncontrolled-state.test.tsx +0 -146
- package/src/Carousel/__tests__/Carousel.wheel.test.tsx +0 -160
- package/src/Carousel/hooks/index.ts +0 -5
- package/src/Carousel/hooks/useCarouselContext.ts +0 -13
- package/src/Carousel/hooks/useCarouselLoop.ts +0 -869
- package/src/Carousel/hooks/useCarouselRoot.ts +0 -746
- package/src/Carousel/hooks/useCarouselSlide.ts +0 -80
- package/src/Carousel/hooks/useCarouselViewport.ts +0 -898
- package/src/Carousel/index.ts +0 -3
- package/src/Carousel/loopEngine.ts +0 -54
- package/src/Carousel/types.ts +0 -830
- package/src/Checkbox/Checkbox.tsx +0 -217
- package/src/Checkbox/CheckboxContext.ts +0 -20
- package/src/Checkbox/README.md +0 -137
- package/src/Checkbox/__tests__/Checkbox.basic-rendering.test.tsx +0 -93
- package/src/Checkbox/__tests__/Checkbox.contract.test.tsx +0 -106
- package/src/Checkbox/__tests__/Checkbox.controlled-state.test.tsx +0 -74
- package/src/Checkbox/__tests__/Checkbox.disabled.test.tsx +0 -45
- package/src/Checkbox/__tests__/Checkbox.form.test.tsx +0 -53
- package/src/Checkbox/__tests__/Checkbox.indeterminate.test.tsx +0 -76
- package/src/Checkbox/__tests__/Checkbox.indicator.test.tsx +0 -92
- package/src/Checkbox/__tests__/Checkbox.uncontrolled-state.test.tsx +0 -105
- package/src/Checkbox/hooks/index.ts +0 -3
- package/src/Checkbox/hooks/useCheckboxContext.ts +0 -1
- package/src/Checkbox/hooks/useCheckboxInput.ts +0 -53
- package/src/Checkbox/hooks/useCheckboxRoot.ts +0 -32
- package/src/Checkbox/index.ts +0 -2
- package/src/Checkbox/types.ts +0 -86
- package/src/CheckboxCard/CheckboxCard.tsx +0 -219
- package/src/CheckboxCard/CheckboxCardContext.ts +0 -25
- package/src/CheckboxCard/README.md +0 -114
- package/src/CheckboxCard/__tests__/CheckboxCard.asChild.test.tsx +0 -54
- package/src/CheckboxCard/__tests__/CheckboxCard.basic-rendering.test.tsx +0 -65
- package/src/CheckboxCard/__tests__/CheckboxCard.controlled-state.test.tsx +0 -77
- package/src/CheckboxCard/__tests__/CheckboxCard.disabled.test.tsx +0 -55
- package/src/CheckboxCard/__tests__/CheckboxCard.error-handling.test.tsx +0 -20
- package/src/CheckboxCard/__tests__/CheckboxCard.indeterminate.test.tsx +0 -60
- package/src/CheckboxCard/__tests__/CheckboxCard.indicator.test.tsx +0 -136
- package/src/CheckboxCard/__tests__/CheckboxCard.uncontrolled-state.test.tsx +0 -73
- package/src/CheckboxCard/hooks/index.ts +0 -2
- package/src/CheckboxCard/hooks/useCheckboxCardContext.ts +0 -1
- package/src/CheckboxCard/hooks/useCheckboxCardRoot.ts +0 -30
- package/src/CheckboxCard/index.ts +0 -3
- package/src/CheckboxCard/types.ts +0 -97
- package/src/Collapsible/Collapsible.tsx +0 -378
- package/src/Collapsible/CollapsibleContext.ts +0 -7
- package/src/Collapsible/README.md +0 -214
- package/src/Collapsible/__tests__/Collapsible.asChild.test.tsx +0 -329
- package/src/Collapsible/__tests__/Collapsible.basic-rendering.test.tsx +0 -145
- package/src/Collapsible/__tests__/Collapsible.collapsedHeight.test.tsx +0 -140
- package/src/Collapsible/__tests__/Collapsible.controlled-state.test.tsx +0 -134
- package/src/Collapsible/__tests__/Collapsible.disabled.test.tsx +0 -132
- package/src/Collapsible/__tests__/Collapsible.error-handling.test.tsx +0 -40
- package/src/Collapsible/__tests__/Collapsible.forceMount.test.tsx +0 -111
- package/src/Collapsible/__tests__/Collapsible.triggerIcon.test.tsx +0 -93
- package/src/Collapsible/__tests__/Collapsible.uncontrolled-state.test.tsx +0 -125
- package/src/Collapsible/hooks/index.ts +0 -2
- package/src/Collapsible/hooks/useCollapsibleRoot.ts +0 -34
- package/src/Collapsible/hooks/useCollapsibleTrigger.ts +0 -51
- package/src/Collapsible/index.ts +0 -2
- package/src/Collapsible/types.ts +0 -148
- package/src/Combobox/Combobox.tsx +0 -508
- package/src/Combobox/ComboboxContext.ts +0 -23
- package/src/Combobox/README.md +0 -170
- package/src/Combobox/__tests__/Combobox.asChild.test.tsx +0 -62
- package/src/Combobox/__tests__/Combobox.basic-rendering.test.tsx +0 -16
- package/src/Combobox/__tests__/Combobox.content.test.tsx +0 -36
- package/src/Combobox/__tests__/Combobox.controlled-state.test.tsx +0 -88
- package/src/Combobox/__tests__/Combobox.empty.test.tsx +0 -42
- package/src/Combobox/__tests__/Combobox.ids.test.tsx +0 -66
- package/src/Combobox/__tests__/Combobox.item.test.tsx +0 -76
- package/src/Combobox/__tests__/Combobox.keyboard-interaction.test.tsx +0 -196
- package/src/Combobox/__tests__/Combobox.light-dismiss.test.tsx +0 -101
- package/src/Combobox/__tests__/Combobox.query.test.tsx +0 -105
- package/src/Combobox/hooks/index.ts +0 -1
- package/src/Combobox/hooks/useComboboxRoot.ts +0 -2
- package/src/Combobox/index.ts +0 -3
- package/src/Combobox/types.ts +0 -133
- package/src/ContextMenu/ContextMenu.tsx +0 -1296
- package/src/ContextMenu/ContextMenuContentContext.ts +0 -15
- package/src/ContextMenu/ContextMenuContext.ts +0 -21
- package/src/ContextMenu/ContextMenuGroupContext.ts +0 -8
- package/src/ContextMenu/ContextMenuItemIndicatorContext.ts +0 -8
- package/src/ContextMenu/ContextMenuRadioGroupContext.ts +0 -9
- package/src/ContextMenu/ContextMenuSubContext.ts +0 -15
- package/src/ContextMenu/README.md +0 -275
- package/src/ContextMenu/__tests__/ContextMenu.asChild.test.tsx +0 -186
- package/src/ContextMenu/__tests__/ContextMenu.basic-rendering.test.tsx +0 -39
- package/src/ContextMenu/__tests__/ContextMenu.checkbox-item.test.tsx +0 -168
- package/src/ContextMenu/__tests__/ContextMenu.error-handling.test.tsx +0 -113
- package/src/ContextMenu/__tests__/ContextMenu.group-label.test.tsx +0 -48
- package/src/ContextMenu/__tests__/ContextMenu.item-indicator.test.tsx +0 -88
- package/src/ContextMenu/__tests__/ContextMenu.item.test.tsx +0 -106
- package/src/ContextMenu/__tests__/ContextMenu.keyboard-interaction.test.tsx +0 -227
- package/src/ContextMenu/__tests__/ContextMenu.mouse-interaction.test.tsx +0 -268
- package/src/ContextMenu/__tests__/ContextMenu.radio-item.test.tsx +0 -152
- package/src/ContextMenu/__tests__/ContextMenu.reading-direction.test.tsx +0 -152
- package/src/ContextMenu/__tests__/ContextMenu.separator.test.tsx +0 -47
- package/src/ContextMenu/__tests__/ContextMenu.state-modes.test.tsx +0 -119
- package/src/ContextMenu/__tests__/ContextMenu.sub.test.tsx +0 -407
- package/src/ContextMenu/__tests__/ContextMenu.typeahead.test.tsx +0 -134
- package/src/ContextMenu/constants.ts +0 -4
- package/src/ContextMenu/index.ts +0 -2
- package/src/ContextMenu/types.ts +0 -484
- package/src/DirectionProvider/DirectionContext.ts +0 -21
- package/src/DirectionProvider/DirectionProvider.tsx +0 -69
- package/src/DirectionProvider/README.md +0 -62
- package/src/DirectionProvider/__tests__/DirectionProvider.test.tsx +0 -34
- package/src/DirectionProvider/index.ts +0 -3
- package/src/DirectionProvider/types.ts +0 -36
- package/src/Divider/Divider.tsx +0 -74
- package/src/Divider/README.md +0 -57
- package/src/Divider/__tests__/Divider.contract.test.tsx +0 -66
- package/src/Divider/__tests__/Divider.test.tsx +0 -46
- package/src/Divider/index.ts +0 -2
- package/src/Divider/types.ts +0 -17
- package/src/Drawer/Drawer.tsx +0 -315
- package/src/Drawer/README.md +0 -124
- package/src/Drawer/__tests__/Drawer.behavior.test.tsx +0 -100
- package/src/Drawer/__tests__/Drawer.focus-trap.test.tsx +0 -55
- package/src/Drawer/__tests__/Drawer.rendering.test.tsx +0 -111
- package/src/Drawer/__tests__/Drawer.side.test.tsx +0 -69
- package/src/Drawer/__tests__/dialog-polyfill.ts +0 -39
- package/src/Drawer/index.ts +0 -2
- package/src/Drawer/types.ts +0 -66
- package/src/Dropdown/Dropdown.tsx +0 -985
- package/src/Dropdown/DropdownContentContext.ts +0 -15
- package/src/Dropdown/DropdownContext.ts +0 -17
- package/src/Dropdown/DropdownGroupContext.ts +0 -8
- package/src/Dropdown/DropdownItemIndicatorContext.ts +0 -13
- package/src/Dropdown/DropdownRadioGroupContext.ts +0 -9
- package/src/Dropdown/DropdownSubContext.ts +0 -15
- package/src/Dropdown/README.md +0 -286
- package/src/Dropdown/__tests__/Dropdown.asChild.test.tsx +0 -286
- package/src/Dropdown/__tests__/Dropdown.basic-rendering.test.tsx +0 -43
- package/src/Dropdown/__tests__/Dropdown.checkbox-item.test.tsx +0 -121
- package/src/Dropdown/__tests__/Dropdown.disabled.test.tsx +0 -143
- package/src/Dropdown/__tests__/Dropdown.error-handling.test.tsx +0 -85
- package/src/Dropdown/__tests__/Dropdown.group-label.test.tsx +0 -68
- package/src/Dropdown/__tests__/Dropdown.item-indicator.test.tsx +0 -260
- package/src/Dropdown/__tests__/Dropdown.item.test.tsx +0 -72
- package/src/Dropdown/__tests__/Dropdown.keyboard-edge-cases.test.tsx +0 -77
- package/src/Dropdown/__tests__/Dropdown.keyboard-interaction.test.tsx +0 -310
- package/src/Dropdown/__tests__/Dropdown.mouse-interaction.test.tsx +0 -347
- package/src/Dropdown/__tests__/Dropdown.radio-item.test.tsx +0 -134
- package/src/Dropdown/__tests__/Dropdown.reading-direction.test.tsx +0 -153
- package/src/Dropdown/__tests__/Dropdown.separator.test.tsx +0 -46
- package/src/Dropdown/__tests__/Dropdown.state-modes.test.tsx +0 -100
- package/src/Dropdown/__tests__/Dropdown.sub.test.tsx +0 -185
- package/src/Dropdown/__tests__/Dropdown.trigger.test.tsx +0 -110
- package/src/Dropdown/__tests__/Dropdown.typeahead.test.tsx +0 -133
- package/src/Dropdown/constants.ts +0 -4
- package/src/Dropdown/hooks/index.ts +0 -9
- package/src/Dropdown/hooks/useCloseSiblingSub.ts +0 -13
- package/src/Dropdown/hooks/useDropdownContent.ts +0 -162
- package/src/Dropdown/hooks/useDropdownContext.ts +0 -1
- package/src/Dropdown/hooks/useDropdownGroup.ts +0 -18
- package/src/Dropdown/hooks/useDropdownItem.ts +0 -49
- package/src/Dropdown/hooks/useDropdownLabel.ts +0 -15
- package/src/Dropdown/hooks/useDropdownRoot.ts +0 -57
- package/src/Dropdown/hooks/useDropdownSubContext.ts +0 -1
- package/src/Dropdown/hooks/useDropdownTrigger.ts +0 -31
- package/src/Dropdown/index.ts +0 -2
- package/src/Dropdown/types.ts +0 -558
- package/src/EmptyState/EmptyState.tsx +0 -329
- package/src/EmptyState/README.md +0 -129
- package/src/EmptyState/__tests__/EmptyState.Actions.test.tsx +0 -37
- package/src/EmptyState/__tests__/EmptyState.Description.test.tsx +0 -32
- package/src/EmptyState/__tests__/EmptyState.Media.test.tsx +0 -34
- package/src/EmptyState/__tests__/EmptyState.Root.test.tsx +0 -38
- package/src/EmptyState/__tests__/EmptyState.Title.test.tsx +0 -28
- package/src/EmptyState/index.ts +0 -2
- package/src/EmptyState/types.ts +0 -65
- package/src/Field/Field.tsx +0 -276
- package/src/Field/FieldContext.ts +0 -22
- package/src/Field/README.md +0 -167
- package/src/Field/__tests__/Field.asChild.test.tsx +0 -83
- package/src/Field/__tests__/Field.basic-rendering.test.tsx +0 -115
- package/src/Field/__tests__/Field.contract.test.tsx +0 -91
- package/src/Field/__tests__/Field.error-handling.test.tsx +0 -23
- package/src/Field/__tests__/Field.state-cascade.test.tsx +0 -96
- package/src/Field/hooks/__tests__/useFieldProps.test.tsx +0 -142
- package/src/Field/hooks/index.ts +0 -2
- package/src/Field/hooks/useFieldContext.ts +0 -1
- package/src/Field/hooks/useFieldProps.ts +0 -57
- package/src/Field/index.ts +0 -2
- package/src/Field/types.ts +0 -85
- package/src/Fieldset/Fieldset.tsx +0 -156
- package/src/Fieldset/README.md +0 -74
- package/src/Fieldset/__tests__/Fieldset.basic-rendering.test.tsx +0 -90
- package/src/Fieldset/__tests__/Fieldset.disabled.test.tsx +0 -41
- package/src/Fieldset/index.ts +0 -2
- package/src/Fieldset/types.ts +0 -25
- package/src/Input/Input.tsx +0 -128
- package/src/Input/README.md +0 -180
- package/src/Input/__tests__/Input.asChild.test.tsx +0 -85
- package/src/Input/__tests__/Input.basic-rendering.test.tsx +0 -123
- package/src/Input/__tests__/Input.contract.test.tsx +0 -77
- package/src/Input/__tests__/Input.disabled.test.tsx +0 -49
- package/src/Input/__tests__/Input.field-integration.test.tsx +0 -148
- package/src/Input/index.ts +0 -2
- package/src/Input/types.ts +0 -28
- package/src/InputGroup/InputGroup.tsx +0 -243
- package/src/InputGroup/README.md +0 -178
- package/src/InputGroup/__tests__/InputGroup.asChild.test.tsx +0 -110
- package/src/InputGroup/__tests__/InputGroup.basic-rendering.test.tsx +0 -120
- package/src/InputGroup/__tests__/InputGroup.contract.test.tsx +0 -60
- package/src/InputGroup/index.ts +0 -2
- package/src/InputGroup/types.ts +0 -43
- package/src/Listbox/Listbox.tsx +0 -475
- package/src/Listbox/ListboxContext.ts +0 -48
- package/src/Listbox/README.md +0 -248
- package/src/Listbox/__tests__/Listbox.active-descendant.test.tsx +0 -128
- package/src/Listbox/__tests__/Listbox.asChild.test.tsx +0 -91
- package/src/Listbox/__tests__/Listbox.basic-rendering.test.tsx +0 -16
- package/src/Listbox/__tests__/Listbox.controlled-state.test.tsx +0 -114
- package/src/Listbox/__tests__/Listbox.disabled.test.tsx +0 -90
- package/src/Listbox/__tests__/Listbox.fixtures.ts +0 -27
- package/src/Listbox/__tests__/Listbox.group-label.test.tsx +0 -97
- package/src/Listbox/__tests__/Listbox.group.test.tsx +0 -45
- package/src/Listbox/__tests__/Listbox.keyboard-edge-cases.test.tsx +0 -144
- package/src/Listbox/__tests__/Listbox.keyboard-interaction.test.tsx +0 -112
- package/src/Listbox/__tests__/Listbox.modifier-keys.test.tsx +0 -86
- package/src/Listbox/__tests__/Listbox.multi-select-keyboard.test.tsx +0 -368
- package/src/Listbox/__tests__/Listbox.multiple-mode.test.tsx +0 -91
- package/src/Listbox/__tests__/Listbox.mutation-hardening.test.tsx +0 -480
- package/src/Listbox/__tests__/Listbox.orientation.test.tsx +0 -59
- package/src/Listbox/__tests__/Listbox.reading-direction.test.tsx +0 -65
- package/src/Listbox/__tests__/Listbox.reorder.test.tsx +0 -78
- package/src/Listbox/__tests__/Listbox.selection-follows-focus.test.tsx +0 -64
- package/src/Listbox/__tests__/Listbox.strict-context.test.tsx +0 -21
- package/src/Listbox/__tests__/Listbox.typeahead.test.tsx +0 -123
- package/src/Listbox/__tests__/Listbox.uncontrolled-state.test.tsx +0 -48
- package/src/Listbox/constants.ts +0 -2
- package/src/Listbox/hooks/index.ts +0 -1
- package/src/Listbox/hooks/useListboxRoot.ts +0 -407
- package/src/Listbox/index.ts +0 -3
- package/src/Listbox/types.ts +0 -238
- package/src/MillerColumns/MillerColumns.tsx +0 -490
- package/src/MillerColumns/MillerColumnsContext.ts +0 -25
- package/src/MillerColumns/README.md +0 -348
- package/src/MillerColumns/__tests__/MillerColumns.aria.test.tsx +0 -127
- package/src/MillerColumns/__tests__/MillerColumns.asChild.test.tsx +0 -106
- package/src/MillerColumns/__tests__/MillerColumns.auto-scroll.test.tsx +0 -70
- package/src/MillerColumns/__tests__/MillerColumns.basic-rendering.test.tsx +0 -67
- package/src/MillerColumns/__tests__/MillerColumns.column-projection.test.tsx +0 -161
- package/src/MillerColumns/__tests__/MillerColumns.controlled-state.test.tsx +0 -90
- package/src/MillerColumns/__tests__/MillerColumns.data-attributes.test.tsx +0 -125
- package/src/MillerColumns/__tests__/MillerColumns.disabled-items.test.tsx +0 -65
- package/src/MillerColumns/__tests__/MillerColumns.error-handling.test.tsx +0 -57
- package/src/MillerColumns/__tests__/MillerColumns.fixtures.ts +0 -15
- package/src/MillerColumns/__tests__/MillerColumns.item-indicator.test.tsx +0 -57
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-interaction.test.tsx +0 -214
- package/src/MillerColumns/__tests__/MillerColumns.keyboard-selection-state.test.tsx +0 -96
- package/src/MillerColumns/__tests__/MillerColumns.preview-panel.test.tsx +0 -72
- package/src/MillerColumns/__tests__/MillerColumns.preview-visibility.test.tsx +0 -79
- package/src/MillerColumns/__tests__/MillerColumns.resize.test.tsx +0 -326
- package/src/MillerColumns/__tests__/MillerColumns.roving-tabindex.test.tsx +0 -91
- package/src/MillerColumns/__tests__/MillerColumns.selection.test.tsx +0 -54
- package/src/MillerColumns/__tests__/MillerColumns.styled-parts.test.tsx +0 -143
- package/src/MillerColumns/__tests__/MillerColumns.typeahead.test.tsx +0 -104
- package/src/MillerColumns/__tests__/MillerColumns.uncontrolled-state.test.tsx +0 -70
- package/src/MillerColumns/constants.ts +0 -2
- package/src/MillerColumns/hooks/index.ts +0 -7
- package/src/MillerColumns/hooks/useMillerColumnsColumn.ts +0 -26
- package/src/MillerColumns/hooks/useMillerColumnsColumnContext.ts +0 -1
- package/src/MillerColumns/hooks/useMillerColumnsContext.ts +0 -1
- package/src/MillerColumns/hooks/useMillerColumnsItem.ts +0 -179
- package/src/MillerColumns/hooks/useMillerColumnsItemContext.ts +0 -1
- package/src/MillerColumns/hooks/useMillerColumnsResizeHandle.ts +0 -146
- package/src/MillerColumns/hooks/useMillerColumnsRoot.ts +0 -0
- package/src/MillerColumns/index.ts +0 -7
- package/src/MillerColumns/types.ts +0 -252
- package/src/MillerColumns/useMillerColumnsSelection.ts +0 -31
- package/src/MillerColumns/utils.ts +0 -141
- package/src/Modal/Modal.tsx +0 -515
- package/src/Modal/ModalContext.ts +0 -20
- package/src/Modal/README.md +0 -222
- package/src/Modal/__tests__/Modal.accessibility.test.tsx +0 -167
- package/src/Modal/__tests__/Modal.asChild.test.tsx +0 -162
- package/src/Modal/__tests__/Modal.click-outside.test.tsx +0 -115
- package/src/Modal/__tests__/Modal.content.test.tsx +0 -193
- package/src/Modal/__tests__/Modal.controlled-state.test.tsx +0 -120
- package/src/Modal/__tests__/Modal.error-handling.test.tsx +0 -30
- package/src/Modal/__tests__/Modal.escape-hatches.test.tsx +0 -99
- package/src/Modal/__tests__/Modal.focus-trap.test.tsx +0 -162
- package/src/Modal/__tests__/Modal.imperative-api.test.tsx +0 -119
- package/src/Modal/__tests__/Modal.nested.test.tsx +0 -106
- package/src/Modal/__tests__/Modal.overlay.test.tsx +0 -99
- package/src/Modal/__tests__/Modal.portal.test.tsx +0 -90
- package/src/Modal/__tests__/Modal.presence.test.tsx +0 -111
- package/src/Modal/__tests__/Modal.trigger.test.tsx +0 -70
- package/src/Modal/__tests__/Modal.uncontrolled-state.test.tsx +0 -72
- package/src/Modal/__tests__/dialog-polyfill.ts +0 -40
- package/src/Modal/hooks/index.ts +0 -4
- package/src/Modal/hooks/useModalContent.ts +0 -94
- package/src/Modal/hooks/useModalContext.ts +0 -1
- package/src/Modal/hooks/useModalRoot.ts +0 -81
- package/src/Modal/hooks/useModalTrigger.ts +0 -25
- package/src/Modal/index.ts +0 -3
- package/src/Modal/types.ts +0 -206
- package/src/NavigationMenu/NavigationMenu.tsx +0 -890
- package/src/NavigationMenu/NavigationMenuContext.ts +0 -67
- package/src/NavigationMenu/README.md +0 -355
- package/src/NavigationMenu/__tests__/NavigationMenu.anchor-positioning.test.tsx +0 -132
- package/src/NavigationMenu/__tests__/NavigationMenu.asChild.test.tsx +0 -73
- package/src/NavigationMenu/__tests__/NavigationMenu.basic-rendering.test.tsx +0 -92
- package/src/NavigationMenu/__tests__/NavigationMenu.contract.test.tsx +0 -45
- package/src/NavigationMenu/__tests__/NavigationMenu.controlled-state.test.tsx +0 -134
- package/src/NavigationMenu/__tests__/NavigationMenu.error-handling.test.tsx +0 -62
- package/src/NavigationMenu/__tests__/NavigationMenu.fixtures.tsx +0 -79
- package/src/NavigationMenu/__tests__/NavigationMenu.forceMount.test.tsx +0 -52
- package/src/NavigationMenu/__tests__/NavigationMenu.hover-interaction.test.tsx +0 -254
- package/src/NavigationMenu/__tests__/NavigationMenu.indicator.test.tsx +0 -252
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-interaction.test.tsx +0 -294
- package/src/NavigationMenu/__tests__/NavigationMenu.keyboard-navigation.test.tsx +0 -126
- package/src/NavigationMenu/__tests__/NavigationMenu.link.test.tsx +0 -139
- package/src/NavigationMenu/__tests__/NavigationMenu.motion.test.tsx +0 -568
- package/src/NavigationMenu/__tests__/NavigationMenu.mouse-interaction.test.tsx +0 -76
- package/src/NavigationMenu/__tests__/NavigationMenu.uncontrolled-state.test.tsx +0 -30
- package/src/NavigationMenu/__tests__/NavigationMenu.viewport.test.tsx +0 -113
- package/src/NavigationMenu/constants.ts +0 -5
- package/src/NavigationMenu/hooks/index.ts +0 -7
- package/src/NavigationMenu/hooks/useNavigationMenuEntry.ts +0 -33
- package/src/NavigationMenu/hooks/useNavigationMenuIndicator.ts +0 -70
- package/src/NavigationMenu/hooks/useNavigationMenuLink.ts +0 -72
- package/src/NavigationMenu/hooks/useNavigationMenuRoot.ts +0 -301
- package/src/NavigationMenu/hooks/useNavigationMenuTopLevelEntry.ts +0 -65
- package/src/NavigationMenu/hooks/useNavigationMenuTrigger.ts +0 -158
- package/src/NavigationMenu/hooks/useNavigationMenuViewport.ts +0 -101
- package/src/NavigationMenu/index.ts +0 -3
- package/src/NavigationMenu/types.ts +0 -259
- package/src/NavigationMenu/utils.ts +0 -89
- package/src/Popover/Popover.tsx +0 -427
- package/src/Popover/PopoverContext.ts +0 -13
- package/src/Popover/README.md +0 -106
- package/src/Popover/__tests__/Popover.anchor.test.tsx +0 -38
- package/src/Popover/__tests__/Popover.asChild.test.tsx +0 -160
- package/src/Popover/__tests__/Popover.basic-rendering.test.tsx +0 -106
- package/src/Popover/__tests__/Popover.click-outside.test.tsx +0 -149
- package/src/Popover/__tests__/Popover.close.test.tsx +0 -70
- package/src/Popover/__tests__/Popover.content.test.tsx +0 -58
- package/src/Popover/__tests__/Popover.controlled-state.test.tsx +0 -45
- package/src/Popover/__tests__/Popover.error-handling.test.tsx +0 -51
- package/src/Popover/__tests__/Popover.focus.test.tsx +0 -43
- package/src/Popover/__tests__/Popover.keyboard-interaction.test.tsx +0 -71
- package/src/Popover/__tests__/Popover.mouse-interaction.test.tsx +0 -69
- package/src/Popover/__tests__/Popover.uncontrolled-state.test.tsx +0 -44
- package/src/Popover/hooks/index.ts +0 -3
- package/src/Popover/hooks/usePopoverContent.ts +0 -98
- package/src/Popover/hooks/usePopoverRoot.ts +0 -84
- package/src/Popover/hooks/usePopoverTrigger.ts +0 -33
- package/src/Popover/index.ts +0 -2
- package/src/Popover/types.ts +0 -197
- package/src/Portal/Portal.tsx +0 -70
- package/src/Portal/README.md +0 -70
- package/src/Portal/__tests__/Portal.basic-rendering.test.tsx +0 -22
- package/src/Portal/index.ts +0 -2
- package/src/Portal/types.ts +0 -15
- package/src/Progress/Progress.tsx +0 -215
- package/src/Progress/ProgressContext.ts +0 -27
- package/src/Progress/README.md +0 -112
- package/src/Progress/__tests__/Progress.asChild.test.tsx +0 -37
- package/src/Progress/__tests__/Progress.basic-rendering.test.tsx +0 -75
- package/src/Progress/__tests__/Progress.error-handling.test.tsx +0 -40
- package/src/Progress/__tests__/Progress.fixtures.ts +0 -7
- package/src/Progress/__tests__/Progress.value.test.tsx +0 -104
- package/src/Progress/hooks/index.ts +0 -2
- package/src/Progress/hooks/useProgressContext.ts +0 -1
- package/src/Progress/hooks/useProgressRoot.ts +0 -45
- package/src/Progress/index.ts +0 -3
- package/src/Progress/types.ts +0 -59
- package/src/Radio/README.md +0 -160
- package/src/Radio/Radio.tsx +0 -210
- package/src/Radio/RadioContext.ts +0 -19
- package/src/Radio/__tests__/Radio.basic-rendering.test.tsx +0 -80
- package/src/Radio/__tests__/Radio.contract.test.tsx +0 -106
- package/src/Radio/__tests__/Radio.controlled-state.test.tsx +0 -79
- package/src/Radio/__tests__/Radio.disabled.test.tsx +0 -48
- package/src/Radio/__tests__/Radio.native-grouping.test.tsx +0 -77
- package/src/Radio/__tests__/Radio.parts.test.tsx +0 -76
- package/src/Radio/__tests__/Radio.uncontrolled-state.test.tsx +0 -96
- package/src/Radio/hooks/index.ts +0 -2
- package/src/Radio/hooks/useRadioContext.ts +0 -1
- package/src/Radio/hooks/useRadioRoot.ts +0 -51
- package/src/Radio/index.ts +0 -2
- package/src/Radio/types.ts +0 -90
- package/src/RadioCard/README.md +0 -134
- package/src/RadioCard/RadioCard.tsx +0 -354
- package/src/RadioCard/RadioCardContext.ts +0 -35
- package/src/RadioCard/RadioCardItemContext.ts +0 -23
- package/src/RadioCard/__tests__/RadioCard.asChild.test.tsx +0 -76
- package/src/RadioCard/__tests__/RadioCard.basic-rendering.test.tsx +0 -95
- package/src/RadioCard/__tests__/RadioCard.controlled-state.test.tsx +0 -107
- package/src/RadioCard/__tests__/RadioCard.disabled-items.test.tsx +0 -111
- package/src/RadioCard/__tests__/RadioCard.error-handling.test.tsx +0 -35
- package/src/RadioCard/__tests__/RadioCard.indicator.test.tsx +0 -119
- package/src/RadioCard/__tests__/RadioCard.keyboard-interaction.test.tsx +0 -211
- package/src/RadioCard/__tests__/RadioCard.orientation.test.tsx +0 -90
- package/src/RadioCard/__tests__/RadioCard.reading-direction.test.tsx +0 -65
- package/src/RadioCard/__tests__/RadioCard.ref-forwarding.test.tsx +0 -54
- package/src/RadioCard/__tests__/RadioCard.uncontrolled-state.test.tsx +0 -129
- package/src/RadioCard/hooks/index.ts +0 -3
- package/src/RadioCard/hooks/useRadioCardContext.ts +0 -1
- package/src/RadioCard/hooks/useRadioCardItemContext.ts +0 -1
- package/src/RadioCard/hooks/useRadioCardRoot.ts +0 -88
- package/src/RadioCard/index.ts +0 -4
- package/src/RadioCard/types.ts +0 -145
- package/src/RadioGroup/README.md +0 -185
- package/src/RadioGroup/RadioGroup.tsx +0 -370
- package/src/RadioGroup/RadioGroupContext.ts +0 -23
- package/src/RadioGroup/RadioGroupItemContext.ts +0 -10
- package/src/RadioGroup/__tests__/RadioGroup.asChild.test.tsx +0 -105
- package/src/RadioGroup/__tests__/RadioGroup.basic-rendering.test.tsx +0 -80
- package/src/RadioGroup/__tests__/RadioGroup.controlled-state.test.tsx +0 -109
- package/src/RadioGroup/__tests__/RadioGroup.disabled-keydown-guards.test.tsx +0 -68
- package/src/RadioGroup/__tests__/RadioGroup.disabled.test.tsx +0 -106
- package/src/RadioGroup/__tests__/RadioGroup.error-handling.test.tsx +0 -33
- package/src/RadioGroup/__tests__/RadioGroup.indicator.test.tsx +0 -85
- package/src/RadioGroup/__tests__/RadioGroup.keyboard-interaction.test.tsx +0 -135
- package/src/RadioGroup/__tests__/RadioGroup.orientation.test.tsx +0 -90
- package/src/RadioGroup/__tests__/RadioGroup.reading-direction.test.tsx +0 -65
- package/src/RadioGroup/__tests__/RadioGroup.ref-forwarding.test.tsx +0 -74
- package/src/RadioGroup/__tests__/RadioGroup.roving-tabindex.test.tsx +0 -136
- package/src/RadioGroup/__tests__/RadioGroup.uncontrolled-state.test.tsx +0 -96
- package/src/RadioGroup/hooks/index.ts +0 -3
- package/src/RadioGroup/hooks/useRadioGroupContext.ts +0 -1
- package/src/RadioGroup/hooks/useRadioGroupItemContext.ts +0 -1
- package/src/RadioGroup/hooks/useRadioGroupRoot.ts +0 -98
- package/src/RadioGroup/index.ts +0 -2
- package/src/RadioGroup/types.ts +0 -146
- package/src/SegmentedControl/README.md +0 -154
- package/src/SegmentedControl/SegmentedControl.tsx +0 -309
- package/src/SegmentedControl/SegmentedControlContext.ts +0 -28
- package/src/SegmentedControl/__tests__/SegmentedControl.asChild.test.tsx +0 -50
- package/src/SegmentedControl/__tests__/SegmentedControl.basic-rendering.test.tsx +0 -100
- package/src/SegmentedControl/__tests__/SegmentedControl.controlled-state.test.tsx +0 -107
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled-keydown-guards.test.tsx +0 -62
- package/src/SegmentedControl/__tests__/SegmentedControl.disabled.test.tsx +0 -151
- package/src/SegmentedControl/__tests__/SegmentedControl.error-handling.test.tsx +0 -17
- package/src/SegmentedControl/__tests__/SegmentedControl.keyboard-interaction.test.tsx +0 -117
- package/src/SegmentedControl/__tests__/SegmentedControl.orientation.test.tsx +0 -54
- package/src/SegmentedControl/__tests__/SegmentedControl.reading-direction.test.tsx +0 -56
- package/src/SegmentedControl/__tests__/SegmentedControl.ref-forwarding.test.tsx +0 -45
- package/src/SegmentedControl/__tests__/SegmentedControl.roving-tabindex.test.tsx +0 -104
- package/src/SegmentedControl/__tests__/SegmentedControl.uncontrolled-state.test.tsx +0 -94
- package/src/SegmentedControl/hooks/index.ts +0 -2
- package/src/SegmentedControl/hooks/useSegmentedControlContext.ts +0 -1
- package/src/SegmentedControl/hooks/useSegmentedControlRoot.ts +0 -87
- package/src/SegmentedControl/index.ts +0 -2
- package/src/SegmentedControl/types.ts +0 -138
- package/src/Select/README.md +0 -168
- package/src/Select/Select.tsx +0 -746
- package/src/Select/SelectContext.ts +0 -38
- package/src/Select/SelectItemIndicatorContext.ts +0 -29
- package/src/Select/__tests__/Select.asChild.test.tsx +0 -36
- package/src/Select/__tests__/Select.basic-rendering.test.tsx +0 -36
- package/src/Select/__tests__/Select.controlled-state.test.tsx +0 -69
- package/src/Select/__tests__/Select.data-attributes.test.tsx +0 -29
- package/src/Select/__tests__/Select.field-integration.test.tsx +0 -150
- package/src/Select/__tests__/Select.form.test.tsx +0 -38
- package/src/Select/__tests__/Select.group.test.tsx +0 -42
- package/src/Select/__tests__/Select.keyboard-edge.test.tsx +0 -95
- package/src/Select/__tests__/Select.keyboard.test.tsx +0 -124
- package/src/Select/__tests__/Select.mutation-hardening.test.tsx +0 -317
- package/src/Select/__tests__/Select.native-item.test.tsx +0 -30
- package/src/Select/__tests__/Select.open-close.test.tsx +0 -57
- package/src/Select/__tests__/Select.placeholder.test.tsx +0 -50
- package/src/Select/__tests__/Select.rich-asChild.test.tsx +0 -60
- package/src/Select/__tests__/Select.rich-mode.test.tsx +0 -16
- package/src/Select/__tests__/Select.selection.test.tsx +0 -104
- package/src/Select/__tests__/Select.separator.test.tsx +0 -71
- package/src/Select/__tests__/Select.strict-context.test.tsx +0 -36
- package/src/Select/__tests__/Select.typeahead.test.tsx +0 -156
- package/src/Select/__tests__/Select.value-mirror.test.tsx +0 -240
- package/src/Select/constants.ts +0 -8
- package/src/Select/hooks/index.ts +0 -2
- package/src/Select/hooks/useSelectContent.ts +0 -149
- package/src/Select/hooks/useSelectRoot.ts +0 -149
- package/src/Select/index.ts +0 -2
- package/src/Select/types.ts +0 -272
- package/src/SkipNav/README.md +0 -87
- package/src/SkipNav/SkipNav.tsx +0 -161
- package/src/SkipNav/__tests__/SkipNav.basic-rendering.test.tsx +0 -29
- package/src/SkipNav/__tests__/SkipNav.ids.test.tsx +0 -19
- package/src/SkipNav/index.ts +0 -1
- package/src/SkipNav/types.ts +0 -34
- package/src/Slider/README.md +0 -245
- package/src/Slider/Slider.tsx +0 -361
- package/src/Slider/SliderContext.ts +0 -58
- package/src/Slider/__tests__/Slider.asChild.test.tsx +0 -119
- package/src/Slider/__tests__/Slider.basic-rendering.test.tsx +0 -157
- package/src/Slider/__tests__/Slider.controlled-state.test.tsx +0 -78
- package/src/Slider/__tests__/Slider.disabled.test.tsx +0 -82
- package/src/Slider/__tests__/Slider.error-handling.test.tsx +0 -45
- package/src/Slider/__tests__/Slider.fixtures.ts +0 -53
- package/src/Slider/__tests__/Slider.form.test.tsx +0 -67
- package/src/Slider/__tests__/Slider.inverted.test.tsx +0 -112
- package/src/Slider/__tests__/Slider.keyboard-interaction.test.tsx +0 -118
- package/src/Slider/__tests__/Slider.multiple-thumbs.test.tsx +0 -84
- package/src/Slider/__tests__/Slider.orientation.test.tsx +0 -101
- package/src/Slider/__tests__/Slider.pointer-interaction.test.tsx +0 -205
- package/src/Slider/__tests__/Slider.reading-direction.test.tsx +0 -99
- package/src/Slider/__tests__/Slider.uncontrolled-state.test.tsx +0 -69
- package/src/Slider/__tests__/Slider.value-commit.test.tsx +0 -103
- package/src/Slider/hooks/index.ts +0 -3
- package/src/Slider/hooks/useSliderContext.ts +0 -1
- package/src/Slider/hooks/useSliderRoot.ts +0 -197
- package/src/Slider/hooks/useSliderThumb.ts +0 -77
- package/src/Slider/index.ts +0 -3
- package/src/Slider/types.ts +0 -205
- package/src/Slider/utils.ts +0 -155
- package/src/Slot/Slot.tsx +0 -238
- package/src/Slot/__tests__/Slot.test.tsx +0 -273
- package/src/Slot/__tests__/composeEventHandlers.test.ts +0 -74
- package/src/Slot/composeEventHandlers.ts +0 -62
- package/src/Slot/index.ts +0 -3
- package/src/Slot/types.ts +0 -21
- package/src/SplitButton/README.md +0 -225
- package/src/SplitButton/SplitButton.tsx +0 -457
- package/src/SplitButton/SplitButtonContext.ts +0 -26
- package/src/SplitButton/__tests__/SplitButton.accessibility.test.tsx +0 -55
- package/src/SplitButton/__tests__/SplitButton.asChild.test.tsx +0 -51
- package/src/SplitButton/__tests__/SplitButton.basic-rendering.test.tsx +0 -57
- package/src/SplitButton/__tests__/SplitButton.data-attributes.test.tsx +0 -28
- package/src/SplitButton/__tests__/SplitButton.disabled.test.tsx +0 -79
- package/src/SplitButton/__tests__/SplitButton.error-handling.test.tsx +0 -29
- package/src/SplitButton/__tests__/SplitButton.keyboard-interaction.test.tsx +0 -56
- package/src/SplitButton/__tests__/SplitButton.state-modes.test.tsx +0 -68
- package/src/SplitButton/index.ts +0 -2
- package/src/SplitButton/types.ts +0 -186
- package/src/Status/README.md +0 -50
- package/src/Status/Status.tsx +0 -72
- package/src/Status/__tests__/Status.test.tsx +0 -33
- package/src/Status/index.ts +0 -2
- package/src/Status/types.ts +0 -20
- package/src/Switch/README.md +0 -126
- package/src/Switch/Switch.tsx +0 -203
- package/src/Switch/SwitchContext.ts +0 -20
- package/src/Switch/__tests__/Switch.asChild.test.tsx +0 -38
- package/src/Switch/__tests__/Switch.basic-rendering.test.tsx +0 -102
- package/src/Switch/__tests__/Switch.contract.test.tsx +0 -114
- package/src/Switch/__tests__/Switch.controlled-state.test.tsx +0 -77
- package/src/Switch/__tests__/Switch.disabled.test.tsx +0 -55
- package/src/Switch/__tests__/Switch.error-handling.test.tsx +0 -20
- package/src/Switch/__tests__/Switch.form.test.tsx +0 -55
- package/src/Switch/__tests__/Switch.keyboard-interaction.test.tsx +0 -56
- package/src/Switch/__tests__/Switch.recipe.test.ts +0 -19
- package/src/Switch/__tests__/Switch.thumb.test.tsx +0 -84
- package/src/Switch/__tests__/Switch.uncontrolled-state.test.tsx +0 -118
- package/src/Switch/hooks/index.ts +0 -2
- package/src/Switch/hooks/useSwitchContext.ts +0 -1
- package/src/Switch/hooks/useSwitchRoot.ts +0 -49
- package/src/Switch/index.ts +0 -3
- package/src/Switch/types.ts +0 -95
- package/src/Table/README.md +0 -307
- package/src/Table/Table.tsx +0 -636
- package/src/Table/TableExpandableContext.ts +0 -7
- package/src/Table/__tests__/Table.Body.test.tsx +0 -61
- package/src/Table/__tests__/Table.Caption.test.tsx +0 -70
- package/src/Table/__tests__/Table.Cell.test.tsx +0 -73
- package/src/Table/__tests__/Table.DetailRow.test.tsx +0 -83
- package/src/Table/__tests__/Table.ExpandTrigger.test.tsx +0 -102
- package/src/Table/__tests__/Table.Expandable.test.tsx +0 -121
- package/src/Table/__tests__/Table.Footer.test.tsx +0 -61
- package/src/Table/__tests__/Table.Head.test.tsx +0 -61
- package/src/Table/__tests__/Table.Header.test.tsx +0 -73
- package/src/Table/__tests__/Table.Root.test.tsx +0 -49
- package/src/Table/__tests__/Table.Row.test.tsx +0 -67
- package/src/Table/__tests__/Table.ScrollArea.test.tsx +0 -83
- package/src/Table/__tests__/Table.contract.test.tsx +0 -80
- package/src/Table/index.ts +0 -2
- package/src/Table/types.ts +0 -237
- package/src/Tabs/README.md +0 -111
- package/src/Tabs/Tabs.tsx +0 -465
- package/src/Tabs/TabsContext.ts +0 -21
- package/src/Tabs/__tests__/Tabs.activation-mode.test.tsx +0 -172
- package/src/Tabs/__tests__/Tabs.asChild.test.tsx +0 -91
- package/src/Tabs/__tests__/Tabs.basic-rendering.test.tsx +0 -498
- package/src/Tabs/__tests__/Tabs.change-event-callbacks.test.tsx +0 -157
- package/src/Tabs/__tests__/Tabs.contract.test.tsx +0 -153
- package/src/Tabs/__tests__/Tabs.controlled-state.test.tsx +0 -152
- package/src/Tabs/__tests__/Tabs.disabled-tabs.test.tsx +0 -239
- package/src/Tabs/__tests__/Tabs.error-handling.test.tsx +0 -82
- package/src/Tabs/__tests__/Tabs.fixtures.ts +0 -171
- package/src/Tabs/__tests__/Tabs.imperative-api.test.tsx +0 -118
- package/src/Tabs/__tests__/Tabs.keyboard-interaction.test.tsx +0 -192
- package/src/Tabs/__tests__/Tabs.lazy-mount.test.tsx +0 -78
- package/src/Tabs/__tests__/Tabs.mouse-interaction.test.tsx +0 -216
- package/src/Tabs/__tests__/Tabs.reading-direction.test.tsx +0 -58
- package/src/Tabs/__tests__/Tabs.uncontrolled-state.test.tsx +0 -197
- package/src/Tabs/hooks/index.ts +0 -4
- package/src/Tabs/hooks/useTabsContent.ts +0 -32
- package/src/Tabs/hooks/useTabsContext.ts +0 -1
- package/src/Tabs/hooks/useTabsRoot.ts +0 -172
- package/src/Tabs/hooks/useTabsTrigger.ts +0 -116
- package/src/Tabs/index.ts +0 -3
- package/src/Tabs/types.ts +0 -166
- package/src/Tabs/utils.ts +0 -8
- package/src/Textarea/README.md +0 -98
- package/src/Textarea/Textarea.tsx +0 -104
- package/src/Textarea/__tests__/Textarea.asChild.test.tsx +0 -85
- package/src/Textarea/__tests__/Textarea.basic-rendering.test.tsx +0 -112
- package/src/Textarea/__tests__/Textarea.disabled.test.tsx +0 -49
- package/src/Textarea/__tests__/Textarea.field-integration.test.tsx +0 -134
- package/src/Textarea/index.ts +0 -2
- package/src/Textarea/types.ts +0 -28
- package/src/Toggle/README.md +0 -97
- package/src/Toggle/Toggle.tsx +0 -126
- package/src/Toggle/__tests__/Toggle.asChild.test.tsx +0 -42
- package/src/Toggle/__tests__/Toggle.basic-rendering.test.tsx +0 -33
- package/src/Toggle/__tests__/Toggle.controlled-state.test.tsx +0 -60
- package/src/Toggle/__tests__/Toggle.disabled.test.tsx +0 -34
- package/src/Toggle/__tests__/Toggle.keyboard-interaction.test.tsx +0 -42
- package/src/Toggle/__tests__/Toggle.uncontrolled-state.test.tsx +0 -40
- package/src/Toggle/index.ts +0 -2
- package/src/Toggle/types.ts +0 -77
- package/src/ToggleGroup/README.md +0 -137
- package/src/ToggleGroup/ToggleGroup.tsx +0 -321
- package/src/ToggleGroup/ToggleGroupContext.ts +0 -9
- package/src/ToggleGroup/__tests__/ToggleGroup.asChild.test.tsx +0 -85
- package/src/ToggleGroup/__tests__/ToggleGroup.basic-rendering.test.tsx +0 -59
- package/src/ToggleGroup/__tests__/ToggleGroup.disabled.test.tsx +0 -54
- package/src/ToggleGroup/__tests__/ToggleGroup.dynamic-items.test.tsx +0 -70
- package/src/ToggleGroup/__tests__/ToggleGroup.error-handling.test.tsx +0 -23
- package/src/ToggleGroup/__tests__/ToggleGroup.keyboard-interaction.test.tsx +0 -173
- package/src/ToggleGroup/__tests__/ToggleGroup.multiple-mode.test.tsx +0 -144
- package/src/ToggleGroup/__tests__/ToggleGroup.reading-direction.test.tsx +0 -28
- package/src/ToggleGroup/__tests__/ToggleGroup.ref-forwarding.test.tsx +0 -58
- package/src/ToggleGroup/__tests__/ToggleGroup.single-mode.test.tsx +0 -139
- package/src/ToggleGroup/hooks/index.ts +0 -2
- package/src/ToggleGroup/hooks/useToggleGroupContext.ts +0 -1
- package/src/ToggleGroup/hooks/useToggleGroupRoot.ts +0 -130
- package/src/ToggleGroup/index.ts +0 -2
- package/src/ToggleGroup/types.ts +0 -165
- package/src/Tooltip/README.md +0 -214
- package/src/Tooltip/Tooltip.tsx +0 -369
- package/src/Tooltip/TooltipContext.ts +0 -20
- package/src/Tooltip/__tests__/Tooltip.asChild.test.tsx +0 -77
- package/src/Tooltip/__tests__/Tooltip.basic-rendering.test.tsx +0 -230
- package/src/Tooltip/__tests__/Tooltip.controlled-state.test.tsx +0 -128
- package/src/Tooltip/__tests__/Tooltip.error-handling.test.tsx +0 -37
- package/src/Tooltip/__tests__/Tooltip.escape-hatches.test.tsx +0 -146
- package/src/Tooltip/__tests__/Tooltip.focus-interaction.test.tsx +0 -88
- package/src/Tooltip/__tests__/Tooltip.hover-interaction.test.tsx +0 -179
- package/src/Tooltip/__tests__/Tooltip.keyboard-interaction.test.tsx +0 -219
- package/src/Tooltip/__tests__/Tooltip.skip-delay.test.tsx +0 -232
- package/src/Tooltip/__tests__/Tooltip.timer-coordination.test.tsx +0 -223
- package/src/Tooltip/__tests__/Tooltip.uncontrolled-state.test.tsx +0 -67
- package/src/Tooltip/hooks/__tests__/useTooltipProvider.test.tsx +0 -40
- package/src/Tooltip/hooks/index.ts +0 -4
- package/src/Tooltip/hooks/useTooltipContent.ts +0 -56
- package/src/Tooltip/hooks/useTooltipProvider.ts +0 -79
- package/src/Tooltip/hooks/useTooltipRoot.ts +0 -130
- package/src/Tooltip/hooks/useTooltipTrigger.ts +0 -44
- package/src/Tooltip/index.ts +0 -2
- package/src/Tooltip/types.ts +0 -193
- package/src/Tree/README.md +0 -403
- package/src/Tree/Tree.tsx +0 -771
- package/src/Tree/TreeContext.ts +0 -24
- package/src/Tree/__tests__/Tree.aria.test.tsx +0 -53
- package/src/Tree/__tests__/Tree.asChild.test.tsx +0 -134
- package/src/Tree/__tests__/Tree.basic-rendering.test.tsx +0 -111
- package/src/Tree/__tests__/Tree.branch-behaviour.test.tsx +0 -87
- package/src/Tree/__tests__/Tree.controlled-expansion.test.tsx +0 -92
- package/src/Tree/__tests__/Tree.data-attributes.test.tsx +0 -88
- package/src/Tree/__tests__/Tree.disabled-items.test.tsx +0 -196
- package/src/Tree/__tests__/Tree.error-handling.test.tsx +0 -71
- package/src/Tree/__tests__/Tree.forceMount.test.tsx +0 -72
- package/src/Tree/__tests__/Tree.keyboard-interaction.test.tsx +0 -150
- package/src/Tree/__tests__/Tree.multiple-selection.test.tsx +0 -151
- package/src/Tree/__tests__/Tree.range-selection.test.tsx +0 -200
- package/src/Tree/__tests__/Tree.recursion-depth.test.tsx +0 -73
- package/src/Tree/__tests__/Tree.roving-tabindex.test.tsx +0 -117
- package/src/Tree/__tests__/Tree.selection-path.test.tsx +0 -404
- package/src/Tree/__tests__/Tree.single-selection.test.tsx +0 -108
- package/src/Tree/__tests__/Tree.styled-wrapper.test.tsx +0 -159
- package/src/Tree/__tests__/Tree.uncontrolled-expansion.test.tsx +0 -69
- package/src/Tree/hooks/index.ts +0 -3
- package/src/Tree/hooks/useTreeItemKeyboard.ts +0 -86
- package/src/Tree/hooks/useTreePath.ts +0 -100
- package/src/Tree/hooks/useTreeRoot.ts +0 -279
- package/src/Tree/index.ts +0 -8
- package/src/Tree/types.ts +0 -298
- package/src/Tree/utils.ts +0 -101
- package/src/VisuallyHidden/README.md +0 -58
- package/src/VisuallyHidden/VisuallyHidden.tsx +0 -94
- package/src/VisuallyHidden/__tests__/VisuallyHidden.test.tsx +0 -73
- package/src/VisuallyHidden/index.ts +0 -2
- package/src/VisuallyHidden/types.ts +0 -19
- package/src/hooks/index.ts +0 -4
- package/src/hooks/useCollection.ts +0 -74
- package/src/hooks/useControllableState.ts +0 -81
- package/src/hooks/useRovingTabindex.ts +0 -178
- package/src/hooks/useTypeahead.ts +0 -95
- package/src/index.ts +0 -52
- package/src/test/intersectionObserverPolyfill.ts +0 -90
- package/src/test/popoverPolyfill.ts +0 -86
- package/src/test/resizeObserverPolyfill.ts +0 -80
- package/src/test/scrollPolyfill.ts +0 -23
- package/src/types.ts +0 -14
- package/src/useLocalStorage/__tests__/useLocalStorage.reading.test.tsx +0 -31
- package/src/useLocalStorage/__tests__/useLocalStorage.resilience.test.tsx +0 -97
- package/src/useLocalStorage/__tests__/useLocalStorage.ssr.test.tsx +0 -20
- package/src/useLocalStorage/__tests__/useLocalStorage.writing.test.tsx +0 -72
- package/src/useLocalStorage/index.ts +0 -1
- package/src/useLocalStorage/useLocalStorage.ts +0 -140
- package/src/useMediaQuery/README.md +0 -66
- package/src/useMediaQuery/__tests__/useMediaQuery.matching.test.tsx +0 -42
- package/src/useMediaQuery/__tests__/useMediaQuery.ssr.test.tsx +0 -19
- package/src/useMediaQuery/__tests__/useMediaQuery.subscription.test.tsx +0 -89
- package/src/useMediaQuery/index.ts +0 -1
- package/src/useMediaQuery/useMediaQuery.ts +0 -49
- package/src/usePagination/README.md +0 -170
- package/src/usePagination/__tests__/usePagination.navigation.test.tsx +0 -109
- package/src/usePagination/__tests__/usePagination.page-count.test.tsx +0 -56
- package/src/usePagination/__tests__/usePagination.page-state.test.tsx +0 -87
- package/src/usePagination/__tests__/usePagination.range.test.tsx +0 -82
- package/src/usePagination/__tests__/usePagination.slice.test.tsx +0 -59
- package/src/usePagination/__tests__/usePagination.windowing.test.tsx +0 -68
- package/src/usePagination/index.ts +0 -1
- package/src/usePagination/usePagination.ts +0 -292
- package/src/utils/__tests__/createStrictContext.test.tsx +0 -69
- package/src/utils/__tests__/deriveId.test.ts +0 -28
- package/src/utils/__tests__/getKeyToActionMap.test.ts +0 -106
- package/src/utils/createStrictContext.ts +0 -53
- package/src/utils/deriveId.ts +0 -31
- package/src/utils/focusable.ts +0 -15
- package/src/utils/getKeyToActionMap.ts +0 -95
- package/src/utils/index.ts +0 -4
package/src/Carousel/README.md
DELETED
|
@@ -1,1447 +0,0 @@
|
|
|
1
|
-
# Carousel
|
|
2
|
-
|
|
3
|
-
Headless, accessible **Carousel** built on native CSS scroll-snap. Implements
|
|
4
|
-
the [WAI-ARIA Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/),
|
|
5
|
-
ships zero styles, and is fully composable.
|
|
6
|
-
|
|
7
|
-
The component is built incrementally under strict TDD. This README
|
|
8
|
-
documents the surface that exists today.
|
|
9
|
-
|
|
10
|
-
## Status
|
|
11
|
-
|
|
12
|
-
Currently exposes:
|
|
13
|
-
|
|
14
|
-
- **`Carousel.Root`** — labelled `<section>` wrapper with
|
|
15
|
-
`aria-roledescription="carousel"`.
|
|
16
|
-
- **`Carousel.Viewport`** — slide container, rendered as a `<div>` with
|
|
17
|
-
a `data-carousel-viewport` attribute the recommended scroll-snap CSS
|
|
18
|
-
targets. Must be rendered as a descendant of `Carousel.Root`; rendering
|
|
19
|
-
it elsewhere throws a descriptive error. Also owns mouse click-and-drag
|
|
20
|
-
scrolling — pointerdown/pointermove track the pointer into
|
|
21
|
-
`scrollLeft`/`scrollTop` (amplified by a sensitivity multiplier) once
|
|
22
|
-
past a small movement threshold (so a link/button inside a slide still
|
|
23
|
-
receives a plain click), flipping a `data-dragging` styling hook for
|
|
24
|
-
the duration; release lets the
|
|
25
|
-
existing `scroll-snap-type` settle to the nearest slide, and a
|
|
26
|
-
horizontal (non-`Shift`) mouse-wheel notch translates to horizontal
|
|
27
|
-
scroll — see "JS vs CSS responsibilities" below for both.
|
|
28
|
-
- **`Carousel.Slide`** — an individual slide. Renders a `<div role="group"
|
|
29
|
-
aria-roledescription="slide">` and self-registers with the Root so each
|
|
30
|
-
slide knows its zero-based `data-index` and the live `data-total`
|
|
31
|
-
count, even as slides mount and unmount. Each slide is auto-labelled
|
|
32
|
-
`"N of M"` (e.g. `"1 of 3"`); pass `ariaLabel` to override with a more
|
|
33
|
-
meaningful description (e.g. `"Hand-picked for you"`). Emits
|
|
34
|
-
`data-state="active" | "inactive"` tracking the active page, plus a
|
|
35
|
-
`data-carousel-slide` CSS hook. Also emits
|
|
36
|
-
`data-snap-align="start" | "center" | "end"` on a page's leading slide
|
|
37
|
-
only (every slide, when `slidesPerPage` is 1), valued from its own
|
|
38
|
-
`snapAlign` prop if set, else the root's resolved `snapAlign` — the hook
|
|
39
|
-
consumer CSS should scope `scroll-snap-align` to, so an interior slide of
|
|
40
|
-
a multi-slide page is never a valid scroll-snap resting position, and the
|
|
41
|
-
native resting position agrees with `snapAlign` (see "Multi-slide snap
|
|
42
|
-
targeting" below). Pass `snapAlign` directly on a `Carousel.Slide` to
|
|
43
|
-
override the root default for that one slide (e.g. a variable-width
|
|
44
|
-
layout where only some slides should centre — matches Ark UI's per-`Item`
|
|
45
|
-
`snapAlign`).
|
|
46
|
-
- **`Carousel.NextTrigger`** — `<button>` that advances the active page
|
|
47
|
-
by one. `disabled` at the last page, and whenever zero or one slides
|
|
48
|
-
are registered. Consumer `onClick` runs before the navigation;
|
|
49
|
-
consumer-supplied `disabled={true}` is honoured alongside the boundary
|
|
50
|
-
check.
|
|
51
|
-
- **`Carousel.PreviousTrigger`** — `<button>` that retreats the active
|
|
52
|
-
page by one. `disabled` at the first page, with the same zero/one-slide
|
|
53
|
-
and consumer-`disabled` semantics as `NextTrigger`.
|
|
54
|
-
- **`Carousel.IndicatorGroup`** — labelled `<div role="group">`
|
|
55
|
-
wrapping consumer-mapped indicator dots. Pass `label` (becomes
|
|
56
|
-
`aria-label`) or `ariaLabelledBy`; the discriminated union rejects
|
|
57
|
-
both-or-neither at compile time.
|
|
58
|
-
- **`Carousel.Indicator`** — individual `<button>` dot. `index` prop
|
|
59
|
-
targets a zero-based page; clicking jumps to it. Auto-labelled
|
|
60
|
-
`"Slide N"`. The dot at the current page carries
|
|
61
|
-
`aria-disabled="true"` (a soft disable per the WAI-ARIA Carousel
|
|
62
|
-
APG); all dots emit `data-state="active" | "inactive"` and a
|
|
63
|
-
`data-carousel-indicator` CSS hook so consumer styles can paint the
|
|
64
|
-
active dot.
|
|
65
|
-
- **`Carousel.Indicators`** — convenience wrapper that auto-renders
|
|
66
|
-
one `Carousel.Indicator` per registered slide. Reuses the same
|
|
67
|
-
discriminated `label` / `ariaLabelledBy` shape as `IndicatorGroup`.
|
|
68
|
-
For custom indicator content, drop down to `IndicatorGroup` +
|
|
69
|
-
`Indicator`.
|
|
70
|
-
- **`Carousel.PlayPauseTrigger`** — `<button>` that toggles the
|
|
71
|
-
`playing` flag on Root. Auto-labels itself `"Start automatic slide
|
|
72
|
-
show"` / `"Stop automatic slide show"` per the WAI-ARIA Carousel
|
|
73
|
-
APG, exposes a `data-state="playing" | "paused"` styling hook, and
|
|
74
|
-
passes `{ playing }` to a function `children` render prop so
|
|
75
|
-
consumers can swap icons or labels per state.
|
|
76
|
-
|
|
77
|
-
Pass `autoplay` on `Carousel.Root` to advance the active page on a
|
|
78
|
-
timer while `playing` is `true`. Hover, focus, and active-touch
|
|
79
|
-
suspend the timer per the WAI-ARIA APG (with a user-initiated play
|
|
80
|
-
override), and the viewport's `aria-live` region flips between
|
|
81
|
-
`"polite"` and `"off"` so assistive tech doesn't announce every
|
|
82
|
-
auto-rotation tick.
|
|
83
|
-
|
|
84
|
-
## JS vs CSS responsibilities
|
|
85
|
-
|
|
86
|
-
The component ships zero styles, but a few features sit on the line
|
|
87
|
-
between JS and CSS. This table is the contract — the rule of thumb
|
|
88
|
-
is that JS owns _what is the active page_ and _scrolls the viewport_
|
|
89
|
-
(`viewport.scrollTo`, then the browser's CSS snap engine makes the final
|
|
90
|
-
correction), and CSS owns _what the user sees_:
|
|
91
|
-
|
|
92
|
-
| Feature | JS owns | CSS owns |
|
|
93
|
-
| ---------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
94
|
-
| Active page state | `page` / `defaultPage`, `onPageChange`, `goTo` | — |
|
|
95
|
-
| Boundary clamping | `canGoNext` / `canGoPrevious`, trigger `disabled` | — |
|
|
96
|
-
| Crossfade / scale / dissolve | `data-state="active"` flip on slides | `position: absolute`, `opacity` + `transition` |
|
|
97
|
-
| Slide layout & widths | — | `flex-basis` / `inline-size`, `gap`, `aspect-ratio` |
|
|
98
|
-
| Peek of adjacent slides | `snapAlign` → viewport `scrollTo` alignment | Viewport `padding-inline`, slide `flex-basis`, `scroll-snap-align` |
|
|
99
|
-
| Gap between slides | — | `gap` on the viewport (no `spacing` prop — pure CSS) |
|
|
100
|
-
| Variable-size slides | viewport `scrollTo` the target slide's offset | Per-slide width / `aspect-ratio`, `scroll-snap-align` |
|
|
101
|
-
| Snap targeting | `snapAlign: "start" \| "center" \| "end"` (Root default, overridable per-`Slide`) | `scroll-snap-type` on viewport, `scroll-snap-align` scoped to `[data-snap-align="start" \| "center" \| "end"]` |
|
|
102
|
-
| Snap strictness | `snapType: "mandatory" \| "proximity"` (Root only) | `scroll-snap-type` strictness scoped to `[data-snap-type="mandatory" \| "proximity"]` on the viewport |
|
|
103
|
-
| Reduced motion | `behavior: "instant"` | Optional `@media (prefers-reduced-motion: reduce)` on consumer animations |
|
|
104
|
-
| Keyboard navigation | Arrow / Home / End on focused viewport | `:focus-visible` on viewport |
|
|
105
|
-
| Touch / swipe | Native scroll + `scrollsnapchange` to sync state | `overscroll-behavior-x: contain`, `scrollbar-width: none` |
|
|
106
|
-
| Mouse click-and-drag (`allowMouseDrag`, off by default) | `scrollLeft`/`scrollTop` set from the pointer delta × sensitivity | `cursor: grab`, `cursor: grabbing` on `[data-dragging]` |
|
|
107
|
-
| Mouse-wheel scroll (horizontal) | `deltaY` → `scrollLeft` when `deltaX` is negligible | — |
|
|
108
|
-
| Overscroll (keyboard / wheel / drag) | `onOverscrollStatusChange`, `isOverscrolling()` (drag only) | Optional resistance visual on `[data-overscroll="start" \| "end"]` (drag only) |
|
|
109
|
-
| Indicator state | `data-state` on `[data-carousel-indicator]` | Visual: dot, bar, thumbnail, etc. |
|
|
110
|
-
| Continuous scroll progress | `getScrollProgress()` / `getSlideProgress(index)`, rAF-batched | Reads `--carousel-progress` / `--slide-progress` for real-time effects, no re-render |
|
|
111
|
-
|
|
112
|
-
The only JS prop on the visual side is `snapAlign`, and only because it
|
|
113
|
-
picks whether the viewport `scrollTo` aligns the target slide's leading
|
|
114
|
-
edge (`"start"`) or centres it (`"center"`) so the programmatic scroll
|
|
115
|
-
lands where the browser's CSS snap engine will settle. Everything else is
|
|
116
|
-
either a state knob (JS) or a visual rule (CSS), with no overlap.
|
|
117
|
-
|
|
118
|
-
The scroll is issued on the **viewport element itself** (`viewport.scrollTo`),
|
|
119
|
-
never `element.scrollIntoView()` — the latter walks every scrollable
|
|
120
|
-
ancestor (including the page/window) and would scroll the whole document
|
|
121
|
-
when a carousel is off-screen.
|
|
122
|
-
|
|
123
|
-
The `apps/workbench` workbench at `/carousel` ships worked recipes for
|
|
124
|
-
each cell of the matrix (single / multi / multi-step × slide / fade)
|
|
125
|
-
plus peek, variable-size, and programmatic-control examples.
|
|
126
|
-
|
|
127
|
-
## Usage
|
|
128
|
-
|
|
129
|
-
Every carousel must have an accessible name. Pass exactly one of `ariaLabel`
|
|
130
|
-
or `ariaLabelledBy`:
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
import { Carousel } from "@primitiv-ui/react";
|
|
134
|
-
|
|
135
|
-
<Carousel.Root ariaLabel="Featured products">
|
|
136
|
-
<Carousel.Viewport>
|
|
137
|
-
<Carousel.Slide>
|
|
138
|
-
<img src="/cube.png" alt="Cube" />
|
|
139
|
-
</Carousel.Slide>
|
|
140
|
-
<Carousel.Slide>
|
|
141
|
-
<img src="/sphere.png" alt="Sphere" />
|
|
142
|
-
</Carousel.Slide>
|
|
143
|
-
</Carousel.Viewport>
|
|
144
|
-
<Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
|
|
145
|
-
<Carousel.Indicators label="Choose slide" />
|
|
146
|
-
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
|
|
147
|
-
</Carousel.Root>;
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
<h2 id="promos">Promotions</h2>
|
|
152
|
-
<Carousel.Root ariaLabelledBy="promos">...</Carousel.Root>
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
The discriminated union on the props type rejects shapes that supply both
|
|
156
|
-
or neither at compile time.
|
|
157
|
-
|
|
158
|
-
### Wrapping the slide container
|
|
159
|
-
|
|
160
|
-
Slides go inside `Carousel.Viewport`:
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
<Carousel.Root ariaLabel="Featured products">
|
|
164
|
-
<Carousel.Viewport>
|
|
165
|
-
<Carousel.Slide>First slide</Carousel.Slide>
|
|
166
|
-
<Carousel.Slide>Second slide</Carousel.Slide>
|
|
167
|
-
<Carousel.Slide>Third slide</Carousel.Slide>
|
|
168
|
-
</Carousel.Viewport>
|
|
169
|
-
</Carousel.Root>
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Each `Carousel.Slide` self-registers with the Root, so every slide
|
|
173
|
-
exposes its own `data-index="0"`, `data-index="1"`, ... and a live
|
|
174
|
-
`data-total` reflecting the current slide count. Add or remove slides at
|
|
175
|
-
runtime and the indices and totals update automatically.
|
|
176
|
-
|
|
177
|
-
Slides are also auto-labelled `"N of M"` (e.g. `"1 of 3"`) — the format
|
|
178
|
-
the WAI-ARIA Carousel APG example uses. To override the auto-label with
|
|
179
|
-
a more meaningful description, pass `ariaLabel`:
|
|
180
|
-
|
|
181
|
-
```tsx
|
|
182
|
-
<Carousel.Slide ariaLabel="Hand-picked for you">...</Carousel.Slide>
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
The override remains stable as siblings mount and unmount around it.
|
|
186
|
-
|
|
187
|
-
### Navigating between slides
|
|
188
|
-
|
|
189
|
-
`Carousel.NextTrigger` and `Carousel.PreviousTrigger` advance and retreat
|
|
190
|
-
the active page. Each slide's `data-state` flips between `"active"` and
|
|
191
|
-
`"inactive"` so consumer CSS can paint the current slide differently.
|
|
192
|
-
|
|
193
|
-
#### Uncontrolled
|
|
194
|
-
|
|
195
|
-
Pass `defaultPage` (or omit it for `0`); the Root owns the active page
|
|
196
|
-
internally:
|
|
197
|
-
|
|
198
|
-
```tsx
|
|
199
|
-
<Carousel.Root ariaLabel="Featured products" defaultPage={0}>
|
|
200
|
-
<Carousel.Viewport>
|
|
201
|
-
<Carousel.Slide>First</Carousel.Slide>
|
|
202
|
-
<Carousel.Slide>Second</Carousel.Slide>
|
|
203
|
-
<Carousel.Slide>Third</Carousel.Slide>
|
|
204
|
-
</Carousel.Viewport>
|
|
205
|
-
<Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
|
|
206
|
-
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
|
|
207
|
-
</Carousel.Root>
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
#### Controlled
|
|
211
|
-
|
|
212
|
-
Pass `page` and `onPageChange` together to lift state into the parent.
|
|
213
|
-
The Root defers every state change back through the callback — clicks
|
|
214
|
-
on `NextTrigger` / `PreviousTrigger` invoke `onPageChange` with the
|
|
215
|
-
proposed page; the visual reflects whatever `page` value the parent
|
|
216
|
-
re-renders with. Useful for syncing two carousels (e.g. a thumbnail
|
|
217
|
-
strip), persisting the active page to a URL, or reacting to deep links.
|
|
218
|
-
|
|
219
|
-
```tsx
|
|
220
|
-
const [page, setPage] = useState(0);
|
|
221
|
-
|
|
222
|
-
<Carousel.Root ariaLabel="Featured products" page={page} onPageChange={setPage}>
|
|
223
|
-
...
|
|
224
|
-
</Carousel.Root>;
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
The discriminated union on the props type rejects mixed shapes (e.g.
|
|
228
|
-
both `defaultPage` and `page`, or `page` without `onPageChange`) at
|
|
229
|
-
compile time.
|
|
230
|
-
|
|
231
|
-
### Runtime validation
|
|
232
|
-
|
|
233
|
-
`Carousel.PlayPauseTrigger` rendered under a Root with `autoplay`
|
|
234
|
-
disabled (omitted, or `autoplay={false}`) throws on mount —
|
|
235
|
-
toggling `playing` is meaningless when no autoplay timer is wired,
|
|
236
|
-
and the throw surfaces the misuse during development rather than
|
|
237
|
-
shipping a no-op control to users.
|
|
238
|
-
|
|
239
|
-
`Carousel.Root` also throws once slides have registered if the
|
|
240
|
-
active `page` (controlled or `defaultPage`-seeded) is negative or
|
|
241
|
-
greater than or equal to the live `totalPages` —
|
|
242
|
-
otherwise the carousel would render with no active slide. The throw
|
|
243
|
-
is gated on `totalPages > 0` so transient zero-slide initial-render
|
|
244
|
-
states don't false-alarm.
|
|
245
|
-
|
|
246
|
-
### Lightbox composition (with `Modal`)
|
|
247
|
-
|
|
248
|
-
Two `Carousel.Root`s sharing a controlled `page` stay in sync — pair
|
|
249
|
-
a thumbnail strip with a fullscreen viewer mounted inside the
|
|
250
|
-
in-tree `Modal`. Gate the inner carousel's `playing` flag on the
|
|
251
|
-
modal's `open` so autoplay only runs while the modal is visible:
|
|
252
|
-
|
|
253
|
-
```tsx
|
|
254
|
-
const [page, setPage] = useState(0);
|
|
255
|
-
const [open, setOpen] = useState(false);
|
|
256
|
-
|
|
257
|
-
<>
|
|
258
|
-
<Carousel.Root
|
|
259
|
-
ariaLabel="Featured products — thumbnails"
|
|
260
|
-
page={page}
|
|
261
|
-
onPageChange={setPage}
|
|
262
|
-
slidesPerPage={3}
|
|
263
|
-
>
|
|
264
|
-
<Carousel.Viewport>
|
|
265
|
-
<Carousel.Slide>...</Carousel.Slide>...
|
|
266
|
-
</Carousel.Viewport>
|
|
267
|
-
</Carousel.Root>
|
|
268
|
-
|
|
269
|
-
<Modal.Root open={open} onOpenChange={setOpen}>
|
|
270
|
-
<Modal.Trigger>Open lightbox</Modal.Trigger>
|
|
271
|
-
<Modal.Portal>
|
|
272
|
-
<Modal.Content>
|
|
273
|
-
<Carousel.Root
|
|
274
|
-
ariaLabel="Featured products — fullscreen"
|
|
275
|
-
page={page}
|
|
276
|
-
onPageChange={setPage}
|
|
277
|
-
autoplay
|
|
278
|
-
playing={open}
|
|
279
|
-
onPlayingChange={() => {}}
|
|
280
|
-
>
|
|
281
|
-
<Carousel.Viewport>
|
|
282
|
-
<Carousel.Slide>...</Carousel.Slide>...
|
|
283
|
-
</Carousel.Viewport>
|
|
284
|
-
<Carousel.Indicators label="Choose slide" />
|
|
285
|
-
</Carousel.Root>
|
|
286
|
-
</Modal.Content>
|
|
287
|
-
</Modal.Portal>
|
|
288
|
-
</Modal.Root>
|
|
289
|
-
</>;
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
`Carousel.Root` doesn't focus anything on mount, so the `Modal`'s
|
|
293
|
-
focus management isn't disturbed when the inner carousel mounts.
|
|
294
|
-
|
|
295
|
-
### Imperative API
|
|
296
|
-
|
|
297
|
-
For programmatic control from outside the component (e.g. a global
|
|
298
|
-
keyboard shortcut, a "skip to last slide" button elsewhere on the
|
|
299
|
-
page, or restoring a remembered position on mount), `Carousel.Root`
|
|
300
|
-
exposes an imperative handle via `ref`:
|
|
301
|
-
|
|
302
|
-
```tsx
|
|
303
|
-
const carouselRef = useRef<CarouselImperativeApi>(null);
|
|
304
|
-
|
|
305
|
-
<Carousel.Root ref={carouselRef} ariaLabel="Featured products">
|
|
306
|
-
...
|
|
307
|
-
</Carousel.Root>;
|
|
308
|
-
|
|
309
|
-
carouselRef.current?.next();
|
|
310
|
-
carouselRef.current?.previous();
|
|
311
|
-
carouselRef.current?.goTo(2);
|
|
312
|
-
carouselRef.current?.scrollToIndex(5);
|
|
313
|
-
carouselRef.current?.play();
|
|
314
|
-
carouselRef.current?.pause();
|
|
315
|
-
carouselRef.current?.refresh();
|
|
316
|
-
const { page, totalPages, value } = carouselRef.current!.getProgress();
|
|
317
|
-
const pageSnapPoints = carouselRef.current!.getPageSnapPoints();
|
|
318
|
-
const isDragging = carouselRef.current!.isDragging();
|
|
319
|
-
const scrollProgress = carouselRef.current!.getScrollProgress(); // 0..1, continuous
|
|
320
|
-
const slideProgress = carouselRef.current!.getSlideProgress(0); // -1..1, continuous
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
`next()`, `previous()`, and `goTo()` each take an optional trailing
|
|
324
|
-
`instant` boolean (default `false`) that bypasses the resolved
|
|
325
|
-
smooth/reduced-motion scroll for **just that one call** — matching Ark
|
|
326
|
-
UI's `scrollNext(instant?)` / `scrollPrev(instant?)` /
|
|
327
|
-
`scrollTo(page, instant?)`. Useful for e.g. an instant jump when
|
|
328
|
-
restoring a remembered position on mount, followed by ordinary smooth
|
|
329
|
-
navigation from then on:
|
|
330
|
-
|
|
331
|
-
```tsx
|
|
332
|
-
carouselRef.current?.goTo(rememberedPage, true); // instant, no animation
|
|
333
|
-
carouselRef.current?.next(); // smooth, as usual
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
The override never outlives the single call it's passed to — a plain
|
|
337
|
-
`next()` / `previous()` / `goTo()` right after always falls back to
|
|
338
|
-
the normal resolved behavior (`prefers-reduced-motion`-aware smooth
|
|
339
|
-
scrolling by default).
|
|
340
|
-
|
|
341
|
-
`scrollToIndex(slideIndex, instant?)` is the slide-granularity
|
|
342
|
-
counterpart to `goTo`'s page granularity — matching Ark UI's
|
|
343
|
-
`scrollToIndex(index, instant?)`. In a plain single-slide-per-page
|
|
344
|
-
carousel the two are equivalent; the distinction matters once
|
|
345
|
-
`slidesPerPage > 1`, where an interior slide of a page isn't itself a
|
|
346
|
-
scroll-snap position — `scrollToIndex` maps the given slide index to
|
|
347
|
-
its *containing* page (the same mapping `Carousel.Indicator` uses
|
|
348
|
-
internally) rather than requiring you to compute the page yourself.
|
|
349
|
-
It takes the same optional `instant` override as `next` / `previous` /
|
|
350
|
-
`goTo`.
|
|
351
|
-
|
|
352
|
-
`refresh()` re-issues the viewport's `scrollTo` for the current
|
|
353
|
-
page — useful when external layout changes (window resize, container
|
|
354
|
-
reflow, dynamic content) leave the scroll position misaligned with
|
|
355
|
-
React state. `getProgress()` returns a normalised
|
|
356
|
-
`value` in `[0, 1]` (`0` when there's at most one page) plus the
|
|
357
|
-
live `page` and `totalPages`, intended for custom progress bars.
|
|
358
|
-
`getPageSnapPoints()` returns the leading slide index each page snaps
|
|
359
|
-
to (one entry per page, length `totalPages`) — the same offset
|
|
360
|
-
formula the carousel uses internally, including the end-aligned last
|
|
361
|
-
page for multi-slide layouts whose total isn't a whole number of
|
|
362
|
-
pages (see "Multi-slide pages and partial page advance" below).
|
|
363
|
-
Useful for a custom progress bar or indicator built from the raw
|
|
364
|
-
offsets instead of just the page count. `isDragging()` is a live
|
|
365
|
-
snapshot of whether a mouse drag is in progress (always `false`
|
|
366
|
-
unless `allowMouseDrag` is set) — see "Drag status" below for the
|
|
367
|
-
matching `onDragStatusChange` callback. For a ready-made rendered
|
|
368
|
-
progress announcement instead of building one from `getProgress()`
|
|
369
|
-
yourself, see "Progress text" below. `getScrollProgress()` and
|
|
370
|
-
`getSlideProgress(slideIndex)` are a *continuous* complement to
|
|
371
|
-
`getProgress()`'s page-granular step function — see "Continuous scroll
|
|
372
|
-
progress" below.
|
|
373
|
-
|
|
374
|
-
Every method routes through the same internal state machine the
|
|
375
|
-
trigger components use, so controlled-mode `onPageChange` /
|
|
376
|
-
`onPlayingChange` callbacks fire just as if the user had clicked.
|
|
377
|
-
`play()` also dismisses the hover/focus pause for the lifetime of
|
|
378
|
-
that playing session, matching the WAI-ARIA APG semantics for
|
|
379
|
-
user-initiated play.
|
|
380
|
-
|
|
381
|
-
### `asChild` composition
|
|
382
|
-
|
|
383
|
-
`Carousel.NextTrigger`, `Carousel.PreviousTrigger`,
|
|
384
|
-
`Carousel.PlayPauseTrigger`, and `Carousel.Indicator` all accept an
|
|
385
|
-
`asChild` prop. When set, the trigger renders the consumer's child
|
|
386
|
-
element via the in-tree `Slot` (instead of its default `<button>`)
|
|
387
|
-
and merges every trigger prop — `onClick`, `aria-label`,
|
|
388
|
-
`aria-disabled`, `data-state`, custom `id`, etc. — onto it. Useful
|
|
389
|
-
for routing links and other elements that need trigger semantics:
|
|
390
|
-
|
|
391
|
-
```tsx
|
|
392
|
-
<Carousel.NextTrigger asChild>
|
|
393
|
-
<a href="/products?page=2">Next</a>
|
|
394
|
-
</Carousel.NextTrigger>
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
Because `<a>` and other non-button elements don't honour the HTML
|
|
398
|
-
`disabled` attribute, the prev/next triggers also short-circuit
|
|
399
|
-
their click handler when boundary clamping says "no further" — so
|
|
400
|
-
asChild on a non-button still respects the boundary clamp.
|
|
401
|
-
|
|
402
|
-
### Snap alignment
|
|
403
|
-
|
|
404
|
-
By default the Viewport scrolls so the target slide **centres** in the
|
|
405
|
-
scroll container — matching `scroll-snap-align: center` in consumer CSS.
|
|
406
|
-
For layouts where the leading (or trailing) edge should align instead —
|
|
407
|
-
e.g. a classic edge-to-edge gallery — set `snapAlign="start"` (or
|
|
408
|
-
`"end"`) so programmatic navigation lands on that position without the
|
|
409
|
-
browser snap-correcting after the scroll:
|
|
410
|
-
|
|
411
|
-
```tsx
|
|
412
|
-
<Carousel.Root ariaLabel="Gallery" snapAlign="start">
|
|
413
|
-
...
|
|
414
|
-
</Carousel.Root>
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
`Carousel.Slide` publishes the resolved value as
|
|
418
|
-
`data-snap-align="start" | "center" | "end"` (on each valid resting slide —
|
|
419
|
-
see "Multi-slide snap targeting" below), so pair it with
|
|
420
|
-
`[data-snap-align="start"] { scroll-snap-align: start }` in your CSS
|
|
421
|
-
rather than hardcoding `scroll-snap-align: start` — that way the
|
|
422
|
-
native snap the user's own scroll settles into always agrees with
|
|
423
|
-
`snapAlign`, not just the programmatic `scrollTo`. The default is
|
|
424
|
-
`"center"`; `snapAlign` picks whether the viewport `scrollTo` aligns the
|
|
425
|
-
target slide's leading edge (`"start"`), centres it (`"center"`), or
|
|
426
|
-
aligns its trailing edge (`"end"`), and the browser's CSS snap engine
|
|
427
|
-
makes the final correction.
|
|
428
|
-
|
|
429
|
-
**Per-slide override.** `Carousel.Slide` also accepts its own `snapAlign`,
|
|
430
|
-
overriding the root default for just that slide — useful for a
|
|
431
|
-
variable-width layout where only some slides should start- or end-align
|
|
432
|
-
(matches Ark UI's per-`Item` `snapAlign`, which is where the `"end"` value
|
|
433
|
-
comes from too — the root-level prop above has no Ark equivalent):
|
|
434
|
-
|
|
435
|
-
```tsx
|
|
436
|
-
<Carousel.Root ariaLabel="Gallery">
|
|
437
|
-
<Carousel.Viewport>
|
|
438
|
-
<Carousel.Slide>Regular, centre-aligned</Carousel.Slide>
|
|
439
|
-
<Carousel.Slide snapAlign="start">This one aligns to its leading edge</Carousel.Slide>
|
|
440
|
-
</Carousel.Viewport>
|
|
441
|
-
</Carousel.Root>
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
The override only takes effect on a slide that's actually a valid
|
|
445
|
-
scroll-snap resting position (a page's leading slide) — an interior slide
|
|
446
|
-
of a multi-slide page never snaps, regardless of this prop (see "Multi-slide
|
|
447
|
-
snap targeting" below).
|
|
448
|
-
|
|
449
|
-
### Snap strictness
|
|
450
|
-
|
|
451
|
-
`snapType` (default `"mandatory"`) is the raw `scroll-snap-type`
|
|
452
|
-
strictness — pass `"proximity"` for a looser, free-scrolling feel where
|
|
453
|
-
the browser only nudges toward a snap point near where the scroll
|
|
454
|
-
ends, rather than always forcing a rest on one:
|
|
455
|
-
|
|
456
|
-
```tsx
|
|
457
|
-
<Carousel.Root ariaLabel="Gallery" snapType="proximity">
|
|
458
|
-
...
|
|
459
|
-
</Carousel.Root>
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
`Carousel.Viewport` publishes the resolved value as
|
|
463
|
-
`data-snap-type="mandatory" | "proximity"`; pair it with
|
|
464
|
-
`[data-snap-type="proximity"] { scroll-snap-type: x proximity }` (`y`
|
|
465
|
-
when `orientation="vertical"`) in your CSS. Matches Ark UI's `snapType`.
|
|
466
|
-
|
|
467
|
-
### Orientation
|
|
468
|
-
|
|
469
|
-
By default the carousel pages along the **inline (horizontal) axis**.
|
|
470
|
-
Pass `orientation="vertical"` to page along the **block (vertical)
|
|
471
|
-
axis** instead:
|
|
472
|
-
|
|
473
|
-
```tsx
|
|
474
|
-
<Carousel.Root ariaLabel="Featured products" orientation="vertical">
|
|
475
|
-
...
|
|
476
|
-
</Carousel.Root>
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
`orientation` is behavioural, not cosmetic — the primitive ships no
|
|
480
|
-
layout. It changes three things:
|
|
481
|
-
|
|
482
|
-
- **Scroll axis.** Programmatic paging scrolls the viewport on the
|
|
483
|
-
`top` (block) axis instead of `left` (inline), leaving the cross axis
|
|
484
|
-
untouched,
|
|
485
|
-
and the user-swipe sync reads `snapTargetBlock` off `scrollsnapchange`
|
|
486
|
-
instead of `snapTargetInline`.
|
|
487
|
-
- **Keyboard.** The viewport pages on `ArrowDown` / `ArrowUp` (the
|
|
488
|
-
horizontal arrows go inert). See [Keyboard navigation](#keyboard-navigation).
|
|
489
|
-
- **Styling hook.** The resolved value is published as
|
|
490
|
-
`data-orientation="horizontal" | "vertical"` on the rendered
|
|
491
|
-
`<section>`, so a single selector can switch your layout to a column
|
|
492
|
-
viewport with `scroll-snap-type: y mandatory`:
|
|
493
|
-
|
|
494
|
-
```css
|
|
495
|
-
[data-orientation="vertical"] [data-carousel-viewport] {
|
|
496
|
-
flex-direction: column;
|
|
497
|
-
overflow-block: auto;
|
|
498
|
-
overflow-inline: hidden;
|
|
499
|
-
scroll-snap-type: y mandatory;
|
|
500
|
-
}
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
The vertical viewport needs a bounded block-size (a height) for the
|
|
504
|
-
scroll axis to exist — give the root or viewport an explicit
|
|
505
|
-
`block-size` / `aspect-ratio`.
|
|
506
|
-
|
|
507
|
-
### Transition modes
|
|
508
|
-
|
|
509
|
-
`Carousel.Root` accepts a `transition` prop that controls how the
|
|
510
|
-
viewport handles slide changes visually. The resolved value is
|
|
511
|
-
published on the Root as `data-transition` so consumer CSS can switch
|
|
512
|
-
the visual off a single hook (mirroring `data-orientation`).
|
|
513
|
-
|
|
514
|
-
- `transition="slide"` (default) — relies on native CSS scroll-snap.
|
|
515
|
-
The Viewport scrolls programmatically when the page changes and
|
|
516
|
-
listens for `scrollsnapchange` so user swipes update React state.
|
|
517
|
-
- `transition="fade"` — installs no scroll wiring (like `"none"`), but
|
|
518
|
-
names the intent so a styled surface can ship a crossfade by default.
|
|
519
|
-
Native swipe/drag and peek don't apply (there's no scroll to swipe);
|
|
520
|
-
controls, indicators, and keyboard paging still work.
|
|
521
|
-
- `transition="none"` — the Viewport installs no scroll wiring at
|
|
522
|
-
all and no default visual is implied. Consumer CSS owns the visual
|
|
523
|
-
via the `data-state="active" | "inactive"` hook on each slide, which
|
|
524
|
-
still flips with the active page.
|
|
525
|
-
|
|
526
|
-
Both `"fade"` and `"none"` are the entry point for crossfade, dissolve,
|
|
527
|
-
zoom, or any CSS-only transition pattern — stack the slides and drive
|
|
528
|
-
opacity/transform off `data-state`, keyed off the `data-transition`
|
|
529
|
-
hook so the scroll-snap layout isn't affected:
|
|
530
|
-
|
|
531
|
-
```css
|
|
532
|
-
[data-transition="fade"] [data-carousel-slide] {
|
|
533
|
-
grid-area: 1 / 1; /* stack every slide in one cell */
|
|
534
|
-
opacity: 0;
|
|
535
|
-
transition: opacity 400ms;
|
|
536
|
-
}
|
|
537
|
-
[data-transition="fade"] [data-carousel-slide][data-state="active"] {
|
|
538
|
-
opacity: 1;
|
|
539
|
-
}
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
### Reduced motion
|
|
543
|
-
|
|
544
|
-
The Viewport's programmatic `scrollTo` reads
|
|
545
|
-
`window.matchMedia("(prefers-reduced-motion: reduce)")` once on
|
|
546
|
-
mount. When the user has reduced motion enabled at the OS level,
|
|
547
|
-
page changes use `behavior: "instant"` instead of `"smooth"` so the
|
|
548
|
-
carousel doesn't fight that preference. Touch-driven scrolling is
|
|
549
|
-
unaffected — the browser owns that animation. The imperative API's
|
|
550
|
-
per-call `instant` override (see "Imperative API" above) composes
|
|
551
|
-
with this — it forces `"instant"` for one call regardless of the
|
|
552
|
-
resolved preference, while every other call still follows it.
|
|
553
|
-
|
|
554
|
-
### Programmatic scroll sync
|
|
555
|
-
|
|
556
|
-
When the active page changes for any reason (`Carousel.NextTrigger` /
|
|
557
|
-
`Carousel.PreviousTrigger` click, indicator click, autoplay tick),
|
|
558
|
-
the viewport `scrollTo`s to the first slide of the new page (by its
|
|
559
|
-
measured offset — not `element.scrollIntoView()`, which would scroll the
|
|
560
|
-
whole document when the carousel is off-screen) so the visual surface
|
|
561
|
-
tracks React state. Consumer CSS owns slide width and gap, and
|
|
562
|
-
`scroll-snap-align` makes the final correction. Default `behavior` is
|
|
563
|
-
`"smooth"`.
|
|
564
|
-
|
|
565
|
-
The reverse path is also wired: when the user swipes the viewport,
|
|
566
|
-
the browser fires `scrollsnapchange` with the snapped slide as the
|
|
567
|
-
target. The Viewport listens for that event, maps the snapped slide
|
|
568
|
-
back to its page (grouping by `slidesPerPage` in `"auto"` mode, or
|
|
569
|
-
rounding to the nearest window start in numeric `slidesPerMove` mode,
|
|
570
|
-
clamped so an end-aligned tail slide lands on the last page), and calls
|
|
571
|
-
`goTo` so React state follows the user's scroll. `onPageChange` is only
|
|
572
|
-
invoked when the page genuinely changes, so a snap that lands back on
|
|
573
|
-
the active page doesn't dispatch a spurious callback.
|
|
574
|
-
|
|
575
|
-
For browsers without `scrollsnapchange`, the same path runs against
|
|
576
|
-
an `IntersectionObserver` (threshold `0.6` by default — see
|
|
577
|
-
`inViewThreshold` below) on each slide — when the observer fires, the
|
|
578
|
-
lowest-index visible slide derives the active page via the same
|
|
579
|
-
slide-index-to-page mapping. This page-drive is **only** a fallback:
|
|
580
|
-
when `scrollsnapchange` is supported it is authoritative (it reports
|
|
581
|
-
the precisely-snapped slide), so the observer stands down and does
|
|
582
|
-
not also drive the page. That matters for `snapAlign="center"`
|
|
583
|
-
carousels with several slides visible at once (e.g. a cover flow) —
|
|
584
|
-
the lowest-index-visible heuristic would otherwise track the
|
|
585
|
-
*leftmost* visible slide rather than the centred one and fight
|
|
586
|
-
`scrollsnapchange`. The observer still always feeds `Carousel.Root`'s
|
|
587
|
-
imperative `isInView(slideIndex)` so consumers can lazy-load slide
|
|
588
|
-
content based on actual visibility, not just the active-page index.
|
|
589
|
-
|
|
590
|
-
**`inViewThreshold`.** Pass a number or an array of numbers on
|
|
591
|
-
`Carousel.Root` to override the default `0.6`:
|
|
592
|
-
|
|
593
|
-
```tsx
|
|
594
|
-
<Carousel.Root ariaLabel="Featured products" inViewThreshold={0.3}>
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
The value is passed straight through as the `IntersectionObserver`'s
|
|
598
|
-
own `threshold` option. For the single "is this slide in view"
|
|
599
|
-
boolean that `isInView` reports (and that the page-drive fallback
|
|
600
|
-
above reads), a plain number is used directly as the cutoff; an array
|
|
601
|
-
uses its **highest** value — the strictest crossing counts as
|
|
602
|
-
genuinely in view, since multiple thresholds otherwise only exist to
|
|
603
|
-
fire the observer's callback more often, not to change what "in view"
|
|
604
|
-
means.
|
|
605
|
-
|
|
606
|
-
### Custom DOM ids
|
|
607
|
-
|
|
608
|
-
For SSR / hydration stability or external `aria-controls` linkage,
|
|
609
|
-
pin DOM `id`s on the rendered sub-components via the `ids` bag on
|
|
610
|
-
`Carousel.Root`:
|
|
611
|
-
|
|
612
|
-
```tsx
|
|
613
|
-
<Carousel.Root
|
|
614
|
-
ariaLabel="Featured products"
|
|
615
|
-
ids={{
|
|
616
|
-
root: "promo-carousel",
|
|
617
|
-
viewport: "promo-viewport",
|
|
618
|
-
previousTrigger: "promo-prev",
|
|
619
|
-
nextTrigger: "promo-next",
|
|
620
|
-
playPauseTrigger: "promo-play-pause",
|
|
621
|
-
indicatorGroup: "promo-indicators",
|
|
622
|
-
}}
|
|
623
|
-
>
|
|
624
|
-
...
|
|
625
|
-
</Carousel.Root>
|
|
626
|
-
```
|
|
627
|
-
|
|
628
|
-
Any keys you omit leave the corresponding element unidentified. A
|
|
629
|
-
direct `id` prop on a sub-component (e.g.
|
|
630
|
-
`<Carousel.NextTrigger id="...">`) wins over `ids.*` because it spreads
|
|
631
|
-
last.
|
|
632
|
-
|
|
633
|
-
### Internationalisation
|
|
634
|
-
|
|
635
|
-
The component owns four user-visible strings: each slide's auto-
|
|
636
|
-
generated `aria-label` (`"N of M"`), each indicator's auto-generated
|
|
637
|
-
`aria-label` (`"Slide N"`), and the two `Carousel.PlayPauseTrigger`
|
|
638
|
-
accessible names (`"Start automatic slide show"` and
|
|
639
|
-
`"Stop automatic slide show"`). Override any subset of them via the
|
|
640
|
-
`translations` prop on `Carousel.Root`:
|
|
641
|
-
|
|
642
|
-
```tsx
|
|
643
|
-
<Carousel.Root
|
|
644
|
-
ariaLabel="Produits en vedette"
|
|
645
|
-
translations={{
|
|
646
|
-
slideLabel: ({ index, total }) => `${index} sur ${total}`,
|
|
647
|
-
indicatorLabel: ({ index }) => `Diapositive ${index}`,
|
|
648
|
-
startSlideshow: "Démarrer le diaporama",
|
|
649
|
-
stopSlideshow: "Arrêter le diaporama",
|
|
650
|
-
}}
|
|
651
|
-
>
|
|
652
|
-
...
|
|
653
|
-
</Carousel.Root>
|
|
654
|
-
```
|
|
655
|
-
|
|
656
|
-
`slideLabel` and `indicatorLabel` are functions (they receive
|
|
657
|
-
position info), the slideshow names are plain strings. Any keys you
|
|
658
|
-
omit fall back to the English defaults. Per-slide `ariaLabel`
|
|
659
|
-
overrides on `Carousel.Slide` still take precedence over
|
|
660
|
-
`translations.slideLabel`, so a single slide can carry a
|
|
661
|
-
domain-meaningful label (e.g. `"Hand-picked for you"`) without
|
|
662
|
-
losing the localised `"N of M"` format on the others.
|
|
663
|
-
|
|
664
|
-
### Multi-slide pages and partial page advance
|
|
665
|
-
|
|
666
|
-
Pass `slidesPerPage` (default `1`) to make several slides visible per
|
|
667
|
-
page — the "image carousel" / "property cards" pattern. By default,
|
|
668
|
-
`Carousel.NextTrigger` / `Carousel.PreviousTrigger` advance one
|
|
669
|
-
full page at a time (`slidesPerMove="auto"`):
|
|
670
|
-
|
|
671
|
-
```tsx
|
|
672
|
-
<Carousel.Root ariaLabel="Featured products" slidesPerPage={3}>
|
|
673
|
-
<Carousel.Viewport>
|
|
674
|
-
<Carousel.Slide>1</Carousel.Slide>
|
|
675
|
-
<Carousel.Slide>2</Carousel.Slide>
|
|
676
|
-
<Carousel.Slide>3</Carousel.Slide>
|
|
677
|
-
<Carousel.Slide>4</Carousel.Slide>
|
|
678
|
-
<Carousel.Slide>5</Carousel.Slide>
|
|
679
|
-
</Carousel.Viewport>
|
|
680
|
-
<Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
|
|
681
|
-
<Carousel.Indicators label="Choose page" />
|
|
682
|
-
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
|
|
683
|
-
</Carousel.Root>
|
|
684
|
-
```
|
|
685
|
-
|
|
686
|
-
With `slidesPerPage={3}` and 5 slides:
|
|
687
|
-
|
|
688
|
-
- Total pages = `ceil(5 / 3) === 2`. `Carousel.Indicators` renders 2
|
|
689
|
-
dots.
|
|
690
|
-
- Page 0 contains slides 0–2; page 1 **end-aligns** to slides 2–4 (a
|
|
691
|
-
full window flush with the track end, not a partial `[3,4]`). A
|
|
692
|
-
partial last page's leading slide can't align to the viewport start,
|
|
693
|
-
so it would snap to the previous slide and desync the active page —
|
|
694
|
-
end-aligning keeps every page a full, cleanly-snapping window (7
|
|
695
|
-
slides at `slidesPerPage={3}` → `[0,1,2] [3,4,5] [4,5,6]`).
|
|
696
|
-
- Each slide on the active page emits `data-state="active"`; slides
|
|
697
|
-
on other pages emit `"inactive"`.
|
|
698
|
-
- `Carousel.NextTrigger` advances one page per click; the boundary
|
|
699
|
-
clamp is at the last page (so Next is disabled while page 1 is
|
|
700
|
-
active).
|
|
701
|
-
|
|
702
|
-
The slide-level `aria-label="N of M"` continues to count individual
|
|
703
|
-
slides (so a 5-slide carousel announces "1 of 5", "2 of 5", ... even
|
|
704
|
-
when grouped into 3-per-page).
|
|
705
|
-
|
|
706
|
-
Pass a numeric `slidesPerMove` to advance the visible window by an
|
|
707
|
-
arbitrary slide count per click instead of a full page:
|
|
708
|
-
|
|
709
|
-
```tsx
|
|
710
|
-
<Carousel.Root
|
|
711
|
-
ariaLabel="Featured products"
|
|
712
|
-
slidesPerPage={3}
|
|
713
|
-
slidesPerMove={1}
|
|
714
|
-
>
|
|
715
|
-
...
|
|
716
|
-
</Carousel.Root>
|
|
717
|
-
```
|
|
718
|
-
|
|
719
|
-
With `slidesPerPage=3`, `slidesPerMove=1`, and 5 slides, the active
|
|
720
|
-
window slides one slide at a time — pages show `[0,1,2]`, `[1,2,3]`,
|
|
721
|
-
`[2,3,4]`, so `Carousel.Indicators` renders 3 dots and the boundary
|
|
722
|
-
clamp respects the last full window. The indicator count formula is
|
|
723
|
-
`ceil((total - slidesPerPage) / slidesPerMove) + 1` (vs.
|
|
724
|
-
`ceil(total / slidesPerPage)` for `"auto"`), so the visible window
|
|
725
|
-
always stays full in numeric mode.
|
|
726
|
-
|
|
727
|
-
**The last window is end-aligned.** When the move doesn't divide the
|
|
728
|
-
track evenly, the final page snaps to the track end rather than dropping
|
|
729
|
-
the remainder — so every slide is always reachable. With
|
|
730
|
-
`slidesPerPage={3}`, `slidesPerMove={2}`, and 6 slides the pages are
|
|
731
|
-
`[0,1,2]`, `[2,3,4]`, `[3,4,5]` (the last shifts back by one to include
|
|
732
|
-
slide 5) — never `[0,1,2]`, `[2,3,4]` with slide 5 orphaned.
|
|
733
|
-
|
|
734
|
-
**Bounds are guarded.** `slidesPerPage` is coerced to an integer ≥ 1 and
|
|
735
|
-
a numeric `slidesPerMove` to an integer in `[1, slidesPerPage]`, so a
|
|
736
|
-
consumer passing `0`, a negative, a fraction, `NaN`, or a move larger
|
|
737
|
-
than a page can never divide by zero, skip past a page (orphaning the
|
|
738
|
-
slides in the gap), or make the carousel inert — it degrades to the
|
|
739
|
-
nearest sane layout.
|
|
740
|
-
|
|
741
|
-
### Boundary behaviour
|
|
742
|
-
|
|
743
|
-
The prev/next triggers clamp at the ends: `Carousel.PreviousTrigger` is
|
|
744
|
-
`disabled` at the first slide, `Carousel.NextTrigger` at the last. Both
|
|
745
|
-
are also `disabled` when zero or one slides are registered, since
|
|
746
|
-
there's nowhere to navigate.
|
|
747
|
-
|
|
748
|
-
### Loop (wrap-around navigation)
|
|
749
|
-
|
|
750
|
-
Pass `loop` to make navigation wrap around instead of clamping. `loop`
|
|
751
|
-
is a **mode selector** — a boolean for ergonomics, or a named mode:
|
|
752
|
-
|
|
753
|
-
```tsx
|
|
754
|
-
<Carousel.Root ariaLabel="Featured products" loop> {/* = "wrap" */}
|
|
755
|
-
<Carousel.Root ariaLabel="Featured products" loop="wrap"> {/* semantic wrap */}
|
|
756
|
-
<Carousel.Root ariaLabel="Featured products" loop="infinite"> {/* continuous infinite */}
|
|
757
|
-
```
|
|
758
|
-
|
|
759
|
-
| `loop` | Resolved `data-loop` | Behaviour |
|
|
760
|
-
| ------------------------- | -------------------- | ------------------------------------------ |
|
|
761
|
-
| omitted / `false` | `"none"` | Clamp at the ends (triggers disable). |
|
|
762
|
-
| `true` / `"wrap"` | `"wrap"` | Semantic wrap (visible rewind). |
|
|
763
|
-
| `"infinite"` | `"infinite"` | Continuous infinite (no rewind). |
|
|
764
|
-
|
|
765
|
-
In every wrapping mode:
|
|
766
|
-
|
|
767
|
-
- `Carousel.NextTrigger` on the last page advances to the first;
|
|
768
|
-
`Carousel.PreviousTrigger` on the first page retreats to the last.
|
|
769
|
-
- Neither trigger `disabled`s at a boundary (the arrow keys wrap too,
|
|
770
|
-
since they route through the same `next` / `previous`).
|
|
771
|
-
- **Autoplay keeps rotating past the last page** rather than stopping —
|
|
772
|
-
the natural pairing for an auto-rotating hero.
|
|
773
|
-
|
|
774
|
-
A single page has no wrap target, so the triggers stay `disabled`
|
|
775
|
-
regardless of `loop`. The resolved mode is published as
|
|
776
|
-
`data-loop="none" | "wrap" | "infinite"` on the Root (mirroring
|
|
777
|
-
`data-orientation` / `data-transition`) for consumer CSS.
|
|
778
|
-
|
|
779
|
-
**`"wrap"` vs `"infinite"`.** Both share the same page model (the wrap
|
|
780
|
-
arithmetic and never-disable boundaries). They differ only in the visual:
|
|
781
|
-
`"wrap"` smooth-scrolls the whole track back on a last→first wrap (a visible
|
|
782
|
-
rewind, the same path `Home` takes), while `"infinite"` glides one step on
|
|
783
|
-
with no rewind.
|
|
784
|
-
|
|
785
|
-
Under `loop="infinite"` the Viewport is **not** a scroll container. It clips
|
|
786
|
-
a **JS transform track** (`data-carousel-track`) laid out as one contiguous,
|
|
787
|
-
periodic strip: the real slides are flanked by a full period of `aria-hidden`,
|
|
788
|
-
`inert` **clones** each side (`[clones] [real slides] [clones]`), so every seam
|
|
789
|
-
is already-painted DOM. Navigation only ever translates the **whole track** — no
|
|
790
|
-
slide moves relative to it — and when a glide carries past the last real slide
|
|
791
|
-
onto a clone, the settle **re-bases** the track by exactly one period so the
|
|
792
|
-
identical real slide sits at the same pixels. Because the strip is periodic, the
|
|
793
|
-
re-base reveals nothing unrasterised and moves nothing (RFC 0018, clone-strip
|
|
794
|
-
revision), which is what structurally removes the iOS seam flash a per-slide fill
|
|
795
|
-
could never avoid. Every page change glides the track via a GPU-composited CSS
|
|
796
|
-
`transform` transition, but the **path differs by kind**: a *relative* step
|
|
797
|
-
(Prev / Next, the arrow keys, autoplay) always takes the **short way** —
|
|
798
|
-
continuing forward off the last slide onto the clone rather than rewinding
|
|
799
|
-
across the whole strip — while a *direct jump to a specific page* (an
|
|
800
|
-
indicator/thumbnail click, or `goTo()` / `scrollToIndex()`) takes the
|
|
801
|
-
**literal** distance between the two slides instead, even when the ring's
|
|
802
|
-
wrap would be shorter: picking the last indicator from the first visibly
|
|
803
|
-
travels forward through every slide in between, matching the indicators' own
|
|
804
|
-
reading order, rather than silently rewinding one step the other way around
|
|
805
|
-
the ring. The first positioning is instant (no glide on load).
|
|
806
|
-
`prefers-reduced-motion` sets the offset instantly with no transition.
|
|
807
|
-
|
|
808
|
-
The glide's **duration and easing** are read off the track from the
|
|
809
|
-
`--primitiv-carousel-glide-duration` and `--primitiv-carousel-glide-easing` custom
|
|
810
|
-
properties, so a consumer retunes the feel purely in CSS (the registry stylesheet
|
|
811
|
-
defaults them to motion tokens and ships `--glide-fast/medium/slow` presets). With
|
|
812
|
-
no stylesheet the engine falls back to a built-in `500ms` ease-out. Every slide is
|
|
813
|
-
also promoted to its own compositor layer (`transform: translateZ(0)` in the
|
|
814
|
-
registry sheet) so its rounded, clipped bitmap is painted before it scrolls in — no
|
|
815
|
-
iOS entering-edge white — while the engine windows the painted set (far slides are
|
|
816
|
-
`visibility: hidden`) to keep that layer count bounded.
|
|
817
|
-
|
|
818
|
-
The engine **re-measures on a `ResizeObserver`** (watching the track and the
|
|
819
|
-
slides), so it self-heals when the container resizes or a size-affecting knob
|
|
820
|
-
changes at runtime — `peek`, the slide `ratio`, ambient density, a multi-slide
|
|
821
|
-
`gap` — re-homing the track to the current page and re-running the paint window
|
|
822
|
-
against the fresh geometry. (A change that resizes *no* box — e.g. a single-slide
|
|
823
|
-
`gap`, which only alters the between-slide spacing — isn't observable; call the
|
|
824
|
-
imperative `refresh()` after one of those, or it self-corrects on the next
|
|
825
|
-
navigation.)
|
|
826
|
-
|
|
827
|
-
**Touch / mouse drag.** The track follows the pointer 1:1 (transition off), and
|
|
828
|
-
on release a velocity-projected **fling** snaps to the nearest **page** boundary
|
|
829
|
-
with the same glide, updating the active page from where it lands. With
|
|
830
|
-
`slidesPerPage > 1` the snap is a whole page, so a multi-slide fling advances (or
|
|
831
|
-
holds) a full page rather than settling mid-page and being jerked to the page
|
|
832
|
-
lead. Touch drag is always
|
|
833
|
-
on (there's no native scroll to fall back to); mouse drag stays opt-in via
|
|
834
|
-
`allowMouseDrag`. A tap under a small threshold still reaches a link / button
|
|
835
|
-
inside a slide.
|
|
836
|
-
|
|
837
|
-
**Direction, peek and multi-slide.** The engine is axis- and direction-generic:
|
|
838
|
-
it reads the sign of the measured stride as the axis direction, so an **RTL**
|
|
839
|
-
loop mirrors every move (no rewind) — including `snapAlign`, whose `start` / `end`
|
|
840
|
-
swap so the reading start stays the right edge — and it cancels the track's own
|
|
841
|
-
inset so **peek** / viewport padding stays centred. **Multi-slide**
|
|
842
|
-
(`slidesPerPage > 1`)
|
|
843
|
-
glides to each page's leading slide, so Prev / Next advance a whole page and wrap
|
|
844
|
-
cleanly; the inter-slide gap returns between the on-screen pair (single-slide
|
|
845
|
-
stays gapless so the gap never flashes through the viewport mid-glide). The gap
|
|
846
|
-
is scoped by the `data-slides-per-page` hook the engine sets on the track.
|
|
847
|
-
|
|
848
|
-
No slide is ever individually transformed — the strip only ever slides as a unit,
|
|
849
|
-
so there are no per-slide layers to flash. The track is **not** force-promoted to
|
|
850
|
-
one permanent GPU layer either (2D `translate`, no `backface-visibility`): the
|
|
851
|
-
clone strip is several viewports wide, and iOS Safari rasterises a large permanent
|
|
852
|
-
layer in tiles on demand, blanking slides at rest until they fill in. Letting the
|
|
853
|
-
browser composite the transition on the GPU but rasterise the visible region
|
|
854
|
-
normally at rest — like native scroll — sidesteps that.
|
|
855
|
-
|
|
856
|
-
This is the same transform + clone approach Embla and Swiper use. It replaced two
|
|
857
|
-
earlier attempts that each flashed on iOS: a native-scroll-snap **clone buffer**
|
|
858
|
-
(the native snap fought the teleport) and a clone-free per-slide `wrapShift` fill
|
|
859
|
-
(individual slides teleported, which iOS can't pre-rasterise). Keeping the clones
|
|
860
|
-
but driving them purely in JS — no native snap, no per-slide moves — removes both
|
|
861
|
-
failure modes at once.
|
|
862
|
-
|
|
863
|
-
> The track geometry is browser-only (jsdom reports no layout), so it ships
|
|
864
|
-
> unit-tested with mocked geometry, and real-browser tested in Playwright.
|
|
865
|
-
|
|
866
|
-
### Keyboard navigation
|
|
867
|
-
|
|
868
|
-
`Carousel.Viewport` is in the tab order so keyboard users can reach the
|
|
869
|
-
rotation control without first tabbing through every slide's
|
|
870
|
-
interactive content. With the Viewport focused:
|
|
871
|
-
|
|
872
|
-
| Key | Action |
|
|
873
|
-
| --------------------- | ----------------------------------------------- |
|
|
874
|
-
| `ArrowRight` / `ArrowDown` | Advance by one page (same as `NextTrigger`) |
|
|
875
|
-
| `ArrowLeft` / `ArrowUp` | Retreat by one page (same as `PreviousTrigger`) |
|
|
876
|
-
| `Home` | Jump to the first page |
|
|
877
|
-
| `End` | Jump to the last page |
|
|
878
|
-
|
|
879
|
-
The paging arrows follow the [orientation](#orientation): `ArrowRight` /
|
|
880
|
-
`ArrowLeft` for the default horizontal axis, `ArrowDown` / `ArrowUp` when
|
|
881
|
-
`orientation="vertical"` (the off-axis arrows go inert). `Home` / `End`
|
|
882
|
-
work in both. Arrow keys clamp at the boundaries, mirroring the trigger
|
|
883
|
-
buttons — or wrap around when [`loop`](#loop-wrap-around-navigation) is
|
|
884
|
-
set. Keypresses are only intercepted when the Viewport itself is the
|
|
885
|
-
focus target — focus inside a slide (e.g. on a link or form control)
|
|
886
|
-
keeps its native arrow-key semantics.
|
|
887
|
-
|
|
888
|
-
```tsx
|
|
889
|
-
<Carousel.Root ariaLabel="Featured products">
|
|
890
|
-
<Carousel.Viewport>
|
|
891
|
-
<Carousel.Slide>First</Carousel.Slide>
|
|
892
|
-
<Carousel.Slide>Second</Carousel.Slide>
|
|
893
|
-
<Carousel.Slide>Third</Carousel.Slide>
|
|
894
|
-
</Carousel.Viewport>
|
|
895
|
-
<Carousel.PreviousTrigger>Previous</Carousel.PreviousTrigger>
|
|
896
|
-
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
|
|
897
|
-
</Carousel.Root>
|
|
898
|
-
```
|
|
899
|
-
|
|
900
|
-
Consumer-supplied `disabled={true}` on either trigger is honoured
|
|
901
|
-
regardless of boundary state — useful for momentarily freezing
|
|
902
|
-
navigation while another part of the UI takes over.
|
|
903
|
-
|
|
904
|
-
### Mouse input
|
|
905
|
-
|
|
906
|
-
Two mouse interactions ship on `Carousel.Viewport` alongside the native
|
|
907
|
-
touch/trackpad scroll that already worked with zero custom code (the
|
|
908
|
-
scroll-driven `scrollsnapchange` sync doesn't care how the viewport got
|
|
909
|
-
scrolled):
|
|
910
|
-
|
|
911
|
-
- **Click-and-drag** — **opt-in** via `allowMouseDrag` on `Carousel.Root`
|
|
912
|
-
(default `false`; an unconditionally-on drag could conflict with a
|
|
913
|
-
consumer's own drag-sensitive slide content — a nested carousel, a
|
|
914
|
-
draggable card, a canvas). When enabled: click and hold on the viewport,
|
|
915
|
-
drag, and it scrolls like a swipe — `scrollLeft`/`scrollTop` track the
|
|
916
|
-
pointer, amplified by a 2× sensitivity multiplier so a full-slide
|
|
917
|
-
transition doesn't require dragging the slide's full on-screen width
|
|
918
|
-
(still no momentum/flick — the multiplier only scales the tracked
|
|
919
|
-
delta, motion stops dead on release) once the drag clears a small
|
|
920
|
-
(3px) movement threshold — below the threshold nothing happens, so a
|
|
921
|
-
plain click on a
|
|
922
|
-
link or button inside a slide still reaches it. Releasing the pointer
|
|
923
|
-
lets the existing `scroll-snap-type` settle to the nearest slide, exactly
|
|
924
|
-
like a touch swipe — no extra "scroll → state" wiring needed, the
|
|
925
|
-
`scrollsnapchange` sync already covers it. A `data-dragging` attribute is
|
|
926
|
-
set on the viewport for the duration of an active drag (see "Recommended
|
|
927
|
-
CSS" for the `cursor: grab` / `grabbing` pairing). Ignores non-mouse
|
|
928
|
-
pointer types (`touch`, `pen`) even when enabled — native scroll already
|
|
929
|
-
handles those. Also suppresses the browser's own native image/link drag
|
|
930
|
-
(the semi-transparent ghost that follows the cursor) on the viewport via
|
|
931
|
-
`preventDefault()` on `dragstart` — real `<img>`/`<a>` slide content is
|
|
932
|
-
natively draggable, and without this its native HTML5 drag would visually
|
|
933
|
-
compete with the custom pointer-drag above. Only active while
|
|
934
|
-
`allowMouseDrag` is on; native drag is left untouched otherwise.
|
|
935
|
-
- **Mouse-wheel scroll.** A physical wheel's vertical notches
|
|
936
|
-
(`deltaY`) already natively scroll a `orientation="vertical"`
|
|
937
|
-
carousel — nothing needed there. But browsers only auto-translate a
|
|
938
|
-
plain vertical wheel to horizontal scroll when `Shift` is held, so the
|
|
939
|
-
default horizontal orientation gets no scroll at all from a plain
|
|
940
|
-
wheel without help: the Viewport translates `deltaY` into `scrollLeft`
|
|
941
|
-
whenever `deltaX` is negligible. A trackpad or Magic Mouse horizontal
|
|
942
|
-
swipe already produces real `deltaX` and already scrolls a horizontal
|
|
943
|
-
viewport natively (the same mechanism as touch) — the translation
|
|
944
|
-
stands down whenever `deltaX` is non-negligible so it never fights
|
|
945
|
-
that. `deltaY` is normalized from `DOM_DELTA_LINE` / `DOM_DELTA_PAGE`
|
|
946
|
-
units to pixels first, so a physical wheel's larger, fewer ticks feel
|
|
947
|
-
proportional to a trackpad's many small pixel-mode ones.
|
|
948
|
-
|
|
949
|
-
Both stand down when `transition` isn't `"slide"` (the viewport isn't a
|
|
950
|
-
scrolling track in `"fade"` / `"none"` mode).
|
|
951
|
-
|
|
952
|
-
### Drag status
|
|
953
|
-
|
|
954
|
-
The `data-dragging` DOM hook above is enough for CSS, but a consumer
|
|
955
|
-
reacting in JS — e.g. pausing a video in the active slide while the
|
|
956
|
-
user drags — needs the imperative `isDragging()` and/or the
|
|
957
|
-
`onDragStatusChange` callback (both only ever reachable when
|
|
958
|
-
`allowMouseDrag` is `true`; matches Ark UI's `api.isDragging` /
|
|
959
|
-
`onDragStatusChange`):
|
|
960
|
-
|
|
961
|
-
```tsx
|
|
962
|
-
const carouselRef = useRef<CarouselImperativeApi>(null);
|
|
963
|
-
|
|
964
|
-
<Carousel.Root
|
|
965
|
-
ref={carouselRef}
|
|
966
|
-
ariaLabel="Featured products"
|
|
967
|
-
allowMouseDrag
|
|
968
|
-
onDragStatusChange={({ type, page, isDragging }) => {
|
|
969
|
-
// type: "dragging.start" | "dragging" | "dragging.end"
|
|
970
|
-
}}
|
|
971
|
-
>
|
|
972
|
-
...
|
|
973
|
-
</Carousel.Root>;
|
|
974
|
-
|
|
975
|
-
carouselRef.current?.isDragging(); // live snapshot, read on demand
|
|
976
|
-
```
|
|
977
|
-
|
|
978
|
-
`onDragStatusChange` fires `"dragging.start"` the moment a drag crosses
|
|
979
|
-
the click-vs-drag movement threshold, `"dragging"` on every subsequent
|
|
980
|
-
pointer move while it's still active, and `"dragging.end"` on release
|
|
981
|
-
(`pointerup` or `pointercancel`) — never for a plain click that never
|
|
982
|
-
crossed the threshold. `page` is the live active page at that moment.
|
|
983
|
-
|
|
984
|
-
### Overscroll
|
|
985
|
-
|
|
986
|
-
Pushing against a boundary with nowhere further to go — via the
|
|
987
|
-
keyboard, the wheel, or a mouse drag — fires `Carousel.Root`'s
|
|
988
|
-
`onOverscrollStatusChange`:
|
|
989
|
-
|
|
990
|
-
```tsx
|
|
991
|
-
<Carousel.Root
|
|
992
|
-
ariaLabel="Featured products"
|
|
993
|
-
allowMouseDrag
|
|
994
|
-
onOverscrollStatusChange={({ type, edge, source, amount, page }) => {
|
|
995
|
-
// type: "overscroll.start" | "overscroll" | "overscroll.end"
|
|
996
|
-
// edge: "start" | "end"
|
|
997
|
-
// source: "keyboard" | "wheel" | "drag"
|
|
998
|
-
}}
|
|
999
|
-
>
|
|
1000
|
-
...
|
|
1001
|
-
</Carousel.Root>;
|
|
1002
|
-
```
|
|
1003
|
-
|
|
1004
|
-
Detection is driven by the same page-boundary truth
|
|
1005
|
-
(`canGoNext`/`canGoPrevious`) as everything else in the primitive, from
|
|
1006
|
-
three input sources the carousel already owns the physics for:
|
|
1007
|
-
|
|
1008
|
-
- **Keyboard** — the forward/backward arrow key pressed while already
|
|
1009
|
-
at that boundary. `Home`/`End` are absolute jumps, not directional
|
|
1010
|
-
pushes, so they never fire this.
|
|
1011
|
-
- **Wheel** — the horizontal-desktop wheel-to-scroll translation (see
|
|
1012
|
-
"Mouse input" above), blocked at a boundary.
|
|
1013
|
-
- **Mouse drag** — a drag (`allowMouseDrag`) pushing past a boundary.
|
|
1014
|
-
|
|
1015
|
-
Keyboard and wheel are instantaneous taps with no meaningful distance —
|
|
1016
|
-
they always fire a single bare `"overscroll"` with `amount: 0`. Drag is
|
|
1017
|
-
the one continuous, physically real case: it fires `"overscroll.start"`
|
|
1018
|
-
the moment the drag starts pushing past the boundary, `"overscroll"` on
|
|
1019
|
-
every subsequent move while still pushing (with the live `amount`, the
|
|
1020
|
-
drag delta past the boundary), and `"overscroll.end"` when the drag
|
|
1021
|
-
stops pushing past it — either a reversal back within bounds mid-drag,
|
|
1022
|
-
or the drag ending — mirroring `onDragStatusChange`'s shape. A drag
|
|
1023
|
-
overscroll also sets a persistent `data-overscroll="start" | "end"`
|
|
1024
|
-
attribute on the Viewport for the same duration — a CSS hook for a
|
|
1025
|
-
rubber-band resistance visual, with no JS required. For the live
|
|
1026
|
-
imperative equivalent of `isDragging()`, `isOverscrolling()` reports
|
|
1027
|
-
whether a drag is currently pushing past a boundary (always `false` for
|
|
1028
|
-
a keyboard/wheel tap, which is instantaneous rather than a sustained
|
|
1029
|
-
state).
|
|
1030
|
-
|
|
1031
|
-
**Native touch/swipe overscroll is out of scope.** OS-level rubber-
|
|
1032
|
-
banding when a touch swipe is dragged past a boundary is browser-owned
|
|
1033
|
-
scroll physics with no JS hook to observe it from — consistent with
|
|
1034
|
-
this primitive's "native scroll is the source of truth" approach
|
|
1035
|
-
elsewhere (see "Mouse input" above, and "Reduced motion").
|
|
1036
|
-
|
|
1037
|
-
### Continuous scroll progress
|
|
1038
|
-
|
|
1039
|
-
`getProgress()` and `isInView()` are both coarse — a page-granular step
|
|
1040
|
-
function and a threshold boolean, respectively. For a continuous signal
|
|
1041
|
-
(a parallax effect, a cover-flow-style scale/rotate, a custom progress
|
|
1042
|
-
bar that fills smoothly instead of stepping), `Carousel.Root` exposes
|
|
1043
|
-
two additional getters, each mirrored live onto a CSS custom property so
|
|
1044
|
-
a consumer's stylesheet can read them directly without touching
|
|
1045
|
-
JavaScript at all:
|
|
1046
|
-
|
|
1047
|
-
```tsx
|
|
1048
|
-
carouselRef.current!.getScrollProgress(); // 0 (start) .. 1 (end)
|
|
1049
|
-
carouselRef.current!.getSlideProgress(0); // -1 .. 0 (centered) .. 1
|
|
1050
|
-
```
|
|
1051
|
-
|
|
1052
|
-
```css
|
|
1053
|
-
/* on the Viewport */
|
|
1054
|
-
.my-progress-bar {
|
|
1055
|
-
transform: scaleX(var(--carousel-progress));
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
/* on each Slide */
|
|
1059
|
-
.my-slide {
|
|
1060
|
-
opacity: calc(1 - abs(var(--slide-progress)));
|
|
1061
|
-
}
|
|
1062
|
-
```
|
|
1063
|
-
|
|
1064
|
-
`--carousel-progress` (on the Viewport) mirrors `getScrollProgress()` —
|
|
1065
|
-
how far the viewport has scrolled along its main axis, `0` at the start
|
|
1066
|
-
and `1` at the end (`0` when there's no overflow to scroll at all).
|
|
1067
|
-
`--slide-progress` (on each Slide) mirrors `getSlideProgress(index)` —
|
|
1068
|
-
`0` when that slide's center coincides with the viewport's center, `±1`
|
|
1069
|
-
when the slide's center has reached the viewport edge (clamped beyond
|
|
1070
|
-
that). Both recompute on every scroll tick and on viewport/slide resize,
|
|
1071
|
-
coalesced to at most once per animation frame so a fast native scroll
|
|
1072
|
-
never forces more than one layout read per frame.
|
|
1073
|
-
|
|
1074
|
-
`getSlideProgress` is normalised by the **viewport's** half-extent, not
|
|
1075
|
-
the slide's own — at `slidesPerPage > 1` a page's outer members can
|
|
1076
|
-
already read a large magnitude (e.g. ~±0.67 at three-per-page) while
|
|
1077
|
-
still fully on-screen and settled. This is *not* the same signal as
|
|
1078
|
-
`isInView` flipping to `false`: `isInView` is an IntersectionObserver
|
|
1079
|
-
threshold crossing, while `getSlideProgress` is raw geometry — a slide
|
|
1080
|
-
can read a large `getSlideProgress` magnitude and still be fully
|
|
1081
|
-
`isInView`, or vice versa near a partial-visibility threshold.
|
|
1082
|
-
|
|
1083
|
-
`getScrollProgress()` is robust under RTL with no `dir` check: modern
|
|
1084
|
-
browsers standardize RTL `scrollLeft` on the "negative" convention (`0`
|
|
1085
|
-
at the start, down to the negative of the max scroll at the end), so the
|
|
1086
|
-
implementation takes the absolute value before normalising — the same
|
|
1087
|
-
reasoning that lets the mouse-drag handler skip RTL special-casing (see
|
|
1088
|
-
"Mouse input" above).
|
|
1089
|
-
|
|
1090
|
-
**Under `loop="infinite"`**, this effect stands down (nothing ever
|
|
1091
|
-
scrolls — the engine translates the track via a JS transform instead),
|
|
1092
|
-
so `--slide-progress` is driven by the infinite engine itself: analytically
|
|
1093
|
-
on every discrete paint (an instant move, or any of a drag's many calls),
|
|
1094
|
-
plus a live-reading rAF ticker for the duration of an animated glide so
|
|
1095
|
-
the drift keeps pace with the track's own CSS transition rather than
|
|
1096
|
-
snapping to the settled value once it ends. This covers every CSS
|
|
1097
|
-
consumer of `--slide-progress` (parallax included) — the imperative
|
|
1098
|
-
**`getSlideProgress()` / `getScrollProgress()` getters are not** (they
|
|
1099
|
-
still only read what the native-scroll effect last wrote, so they read
|
|
1100
|
-
frozen under infinite); reach for the CSS custom property there instead.
|
|
1101
|
-
There is also no infinite equivalent of `--carousel-progress` — a
|
|
1102
|
-
0 (start) .. 1 (end) reading has no natural definition for a loop with
|
|
1103
|
-
no start or end.
|
|
1104
|
-
|
|
1105
|
-
### Indicator dots (manual)
|
|
1106
|
-
|
|
1107
|
-
For full control over indicator content, map them yourself with
|
|
1108
|
-
`Carousel.IndicatorGroup` + `Carousel.Indicator`. Each dot's `index`
|
|
1109
|
-
prop targets a zero-based page; clicking jumps to it.
|
|
1110
|
-
|
|
1111
|
-
```tsx
|
|
1112
|
-
<Carousel.IndicatorGroup label="Choose slide">
|
|
1113
|
-
<Carousel.Indicator index={0} />
|
|
1114
|
-
<Carousel.Indicator index={1} />
|
|
1115
|
-
<Carousel.Indicator index={2} />
|
|
1116
|
-
</Carousel.IndicatorGroup>
|
|
1117
|
-
```
|
|
1118
|
-
|
|
1119
|
-
Indicators are auto-labelled `"Slide N"` (1-indexed). The dot at the
|
|
1120
|
-
current page carries `aria-disabled="true"` per the WAI-ARIA APG and
|
|
1121
|
-
`data-state="active"`; non-active dots carry `aria-disabled="false"`
|
|
1122
|
-
and `data-state="inactive"`. Style them via the
|
|
1123
|
-
`data-carousel-indicator` attribute and the `data-state` hook:
|
|
1124
|
-
|
|
1125
|
-
```css
|
|
1126
|
-
[data-carousel-indicator][data-state="active"] {
|
|
1127
|
-
background: black;
|
|
1128
|
-
}
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
### Play / pause control
|
|
1132
|
-
|
|
1133
|
-
`Carousel.PlayPauseTrigger` toggles a `playing` flag on the Root. The
|
|
1134
|
-
flag has the same controlled / uncontrolled split as `page`:
|
|
1135
|
-
|
|
1136
|
-
```tsx
|
|
1137
|
-
// Uncontrolled
|
|
1138
|
-
<Carousel.Root ariaLabel="Featured products" defaultPlaying={false}>
|
|
1139
|
-
<Carousel.PlayPauseTrigger />
|
|
1140
|
-
</Carousel.Root>;
|
|
1141
|
-
|
|
1142
|
-
// Controlled
|
|
1143
|
-
const [playing, setPlaying] = useState(false);
|
|
1144
|
-
<Carousel.Root
|
|
1145
|
-
ariaLabel="Featured products"
|
|
1146
|
-
playing={playing}
|
|
1147
|
-
onPlayingChange={setPlaying}
|
|
1148
|
-
>
|
|
1149
|
-
<Carousel.PlayPauseTrigger />
|
|
1150
|
-
</Carousel.Root>;
|
|
1151
|
-
```
|
|
1152
|
-
|
|
1153
|
-
The discriminated union rejects mixed shapes (e.g. `defaultPlaying` +
|
|
1154
|
-
`playing`, or `playing` without `onPlayingChange`) at compile time.
|
|
1155
|
-
|
|
1156
|
-
Pass a function as `children` to swap icons or labels per state:
|
|
1157
|
-
|
|
1158
|
-
```tsx
|
|
1159
|
-
<Carousel.PlayPauseTrigger>
|
|
1160
|
-
{({ playing }) => (playing ? <PauseIcon /> : <PlayIcon />)}
|
|
1161
|
-
</Carousel.PlayPauseTrigger>
|
|
1162
|
-
```
|
|
1163
|
-
|
|
1164
|
-
The trigger is auto-labelled `"Start automatic slide show"` (paused)
|
|
1165
|
-
or `"Stop automatic slide show"` (playing) for assistive tech, and
|
|
1166
|
-
emits `data-state="playing" | "paused"` for consumer CSS.
|
|
1167
|
-
|
|
1168
|
-
### Autoplay timer
|
|
1169
|
-
|
|
1170
|
-
Pass `autoplay` on `Carousel.Root` to advance the active page on a
|
|
1171
|
-
timer while `playing` is `true`:
|
|
1172
|
-
|
|
1173
|
-
```tsx
|
|
1174
|
-
// Default 4000ms cadence
|
|
1175
|
-
<Carousel.Root ariaLabel="Featured products" autoplay defaultPlaying>
|
|
1176
|
-
...
|
|
1177
|
-
</Carousel.Root>
|
|
1178
|
-
|
|
1179
|
-
// Custom delay
|
|
1180
|
-
<Carousel.Root
|
|
1181
|
-
ariaLabel="Featured products"
|
|
1182
|
-
autoplay={{ delay: 6000 }}
|
|
1183
|
-
defaultPlaying
|
|
1184
|
-
>
|
|
1185
|
-
...
|
|
1186
|
-
</Carousel.Root>
|
|
1187
|
-
```
|
|
1188
|
-
|
|
1189
|
-
The timer reads from the live `playing` flag and the active page —
|
|
1190
|
-
toggling pause via `Carousel.PlayPauseTrigger` (or via the controlled
|
|
1191
|
-
`onPlayingChange`) cancels the next tick. The timer stops once the
|
|
1192
|
-
active page reaches the last slide.
|
|
1193
|
-
|
|
1194
|
-
The timer also pauses automatically while the user is hovering the
|
|
1195
|
-
Root or has focus on a descendant element, per WCAG 2.2.2 (Pause,
|
|
1196
|
-
Stop, Hide). Focus moving between descendants of the Root (e.g.
|
|
1197
|
-
tabbing from `Previous` to `Next`) keeps the pause active; the timer
|
|
1198
|
-
only resumes once the pointer leaves and focus has moved out of the
|
|
1199
|
-
carousel entirely. The `playing` flag is unaffected — it stays
|
|
1200
|
-
`true` while suspended, so toggling pause-resume via
|
|
1201
|
-
`PlayPauseTrigger` continues to behave as the consumer expects.
|
|
1202
|
-
|
|
1203
|
-
Touch gestures pause the timer too: `pointerdown` with
|
|
1204
|
-
`pointerType === "touch"` sets the suspension flag, and any
|
|
1205
|
-
`pointerup` or `pointercancel` releases it. Mouse / pen
|
|
1206
|
-
`pointerdown` is filtered out so the existing hover/focus path
|
|
1207
|
-
keeps owning non-touch interaction without double-suspension.
|
|
1208
|
-
|
|
1209
|
-
**User-initiated play overrides the hover/focus pause.** Per the
|
|
1210
|
-
WAI-ARIA Carousel APG example, when the user explicitly clicks
|
|
1211
|
-
`PlayPauseTrigger` to start the slideshow, the hover/focus pause is
|
|
1212
|
-
suspended for the lifetime of that playing session — otherwise the
|
|
1213
|
-
user would fight a pause every time their pointer was already over
|
|
1214
|
-
the carousel when they pressed play. The override resets when
|
|
1215
|
-
`playing` flips back to `false` (via another click, or via an
|
|
1216
|
-
external state change), so a subsequent play that's _not_ user-
|
|
1217
|
-
initiated falls back to the standard WCAG pause.
|
|
1218
|
-
|
|
1219
|
-
**Viewport live region.** `Carousel.Viewport` is also the live region
|
|
1220
|
-
for slide changes. Its `aria-live` defaults to `"polite"` so paged
|
|
1221
|
-
manual navigation is announced to assistive tech, and flips to
|
|
1222
|
-
`"off"` while autoplay is actively rotating (`autoplay` enabled and
|
|
1223
|
-
`playing=true`) so screen readers aren't spammed with every tick.
|
|
1224
|
-
The flip is reactive — pausing via `PlayPauseTrigger` returns the
|
|
1225
|
-
viewport to `"polite"` for the duration of the pause.
|
|
1226
|
-
|
|
1227
|
-
### Autoplay status
|
|
1228
|
-
|
|
1229
|
-
The `playing` flag and `data-state` on `PlayPauseTrigger` cover
|
|
1230
|
-
play/pause toggles, but a consumer reacting to the timer itself in JS
|
|
1231
|
-
— e.g. logging analytics on every autoplay rotation — needs the
|
|
1232
|
-
`onAutoplayStatusChange` callback (only ever reachable when
|
|
1233
|
-
`autoplay` is enabled; matches Ark UI's `onAutoplayStatusChange`):
|
|
1234
|
-
|
|
1235
|
-
```tsx
|
|
1236
|
-
<Carousel.Root
|
|
1237
|
-
ariaLabel="Featured products"
|
|
1238
|
-
autoplay
|
|
1239
|
-
defaultPlaying
|
|
1240
|
-
onAutoplayStatusChange={({ type, page, isPlaying }) => {
|
|
1241
|
-
// type: "autoplay.start" | "autoplay" | "autoplay.stop"
|
|
1242
|
-
}}
|
|
1243
|
-
>
|
|
1244
|
-
...
|
|
1245
|
-
</Carousel.Root>
|
|
1246
|
-
```
|
|
1247
|
-
|
|
1248
|
-
`onAutoplayStatusChange` fires `"autoplay.start"` the moment the timer
|
|
1249
|
-
becomes active (autoplay enabled, `playing` true, another page
|
|
1250
|
-
remains, not suspended by hover/focus/touch), `"autoplay"` on every
|
|
1251
|
-
tick while it stays active, and `"autoplay.stop"` when the timer stops
|
|
1252
|
-
running — whether because `playing` flipped `false`, the last page was
|
|
1253
|
-
reached, or hover/focus/touch suspended it. `page` is the active page
|
|
1254
|
-
at that moment.
|
|
1255
|
-
|
|
1256
|
-
### Progress text
|
|
1257
|
-
|
|
1258
|
-
`getProgress()` on the imperative API gives you the raw
|
|
1259
|
-
`{ page, totalPages, value }` data, but wiring an actual rendered
|
|
1260
|
-
announcement (`"1 of 3"`) yourself every time is boilerplate.
|
|
1261
|
-
`Carousel.ProgressText` renders it for you, formatted by
|
|
1262
|
-
`translations.progressText` (matches Ark UI's `Carousel.ProgressText`
|
|
1263
|
-
anatomy part):
|
|
1264
|
-
|
|
1265
|
-
```tsx
|
|
1266
|
-
<Carousel.Root ariaLabel="Featured products">
|
|
1267
|
-
<Carousel.Viewport>...</Carousel.Viewport>
|
|
1268
|
-
<Carousel.ProgressText />
|
|
1269
|
-
</Carousel.Root>
|
|
1270
|
-
```
|
|
1271
|
-
|
|
1272
|
-
Renders `"1 of 3"` by default (1-indexed, matching `slideLabel`); pass a
|
|
1273
|
-
`progressText` formatter through `translations` (a
|
|
1274
|
-
`({ page, totalPages }) => ...` function) on the Root to customise the
|
|
1275
|
-
format, or `children` on `Carousel.ProgressText`
|
|
1276
|
-
itself to render something else entirely (an icon alongside the
|
|
1277
|
-
count, say) instead of the computed text. `Carousel.ProgressText`
|
|
1278
|
-
carries no ARIA wiring of its own — compose it inside your own live
|
|
1279
|
-
region if you want page changes announced; this mirrors Ark's
|
|
1280
|
-
unopinionated `progressText` part rather than duplicating the
|
|
1281
|
-
Viewport's own `aria-live` toggling (see "Autoplay timer" above).
|
|
1282
|
-
|
|
1283
|
-
### Indicator dots (auto-rendered)
|
|
1284
|
-
|
|
1285
|
-
For the common case of one dot per slide with auto-generated labels,
|
|
1286
|
-
use `Carousel.Indicators` — it reads the live slide count from
|
|
1287
|
-
context and renders the right number of dots without any mapping
|
|
1288
|
-
boilerplate:
|
|
1289
|
-
|
|
1290
|
-
```tsx
|
|
1291
|
-
<Carousel.Root ariaLabel="Featured products">
|
|
1292
|
-
<Carousel.Viewport>
|
|
1293
|
-
<Carousel.Slide>1</Carousel.Slide>
|
|
1294
|
-
<Carousel.Slide>2</Carousel.Slide>
|
|
1295
|
-
<Carousel.Slide>3</Carousel.Slide>
|
|
1296
|
-
</Carousel.Viewport>
|
|
1297
|
-
<Carousel.Indicators label="Choose slide" />
|
|
1298
|
-
</Carousel.Root>
|
|
1299
|
-
```
|
|
1300
|
-
|
|
1301
|
-
The dot count tracks slide count automatically — add or remove a
|
|
1302
|
-
slide and the indicator row updates on the next render. For custom
|
|
1303
|
-
indicator content (thumbnails, numbers, mixed icons), drop down to
|
|
1304
|
-
the manual `IndicatorGroup` + `Indicator` API above.
|
|
1305
|
-
|
|
1306
|
-
### Read-only (presentational) indicators
|
|
1307
|
-
|
|
1308
|
-
Pass `readOnly` when the dots are a progress display rather than a
|
|
1309
|
-
navigation control — e.g. a carousel driven solely by
|
|
1310
|
-
[`allowMouseDrag`](#mouse-input), where clickable dots would be a
|
|
1311
|
-
redundant, confusing second way to navigate:
|
|
1312
|
-
|
|
1313
|
-
```tsx
|
|
1314
|
-
<Carousel.Indicators label="Progress" readOnly />
|
|
1315
|
-
// or, on a manually-mapped dot:
|
|
1316
|
-
<Carousel.Indicator index={0} readOnly />
|
|
1317
|
-
```
|
|
1318
|
-
|
|
1319
|
-
A `readOnly` indicator renders a `<span>` instead of a `<button>`
|
|
1320
|
-
(no button semantics), carries `aria-hidden="true"` (it's decorative
|
|
1321
|
-
and not announced to assistive tech), and no longer calls `goTo`
|
|
1322
|
-
when clicked. It still tracks `data-state="active" | "inactive"`, so
|
|
1323
|
-
the same CSS that paints a normal indicator keeps working. A
|
|
1324
|
-
consumer's own `onClick` on an individual `Indicator`, if passed,
|
|
1325
|
-
still fires — only the internal navigation is suppressed. On
|
|
1326
|
-
`Carousel.Indicators`, `readOnly` forwards to every generated dot.
|
|
1327
|
-
|
|
1328
|
-
## Recommended CSS
|
|
1329
|
-
|
|
1330
|
-
The component ships zero styles. The recipe below is the minimum
|
|
1331
|
-
needed to get a working horizontal carousel with snap-aligned slides,
|
|
1332
|
-
dot indicators, and sane mobile behaviour. Drop it into your stylesheet
|
|
1333
|
-
and target the `data-carousel-*` attributes:
|
|
1334
|
-
|
|
1335
|
-
```css
|
|
1336
|
-
[data-carousel-viewport] {
|
|
1337
|
-
display: flex;
|
|
1338
|
-
overflow-x: auto;
|
|
1339
|
-
scroll-snap-type: x mandatory;
|
|
1340
|
-
scroll-behavior: smooth;
|
|
1341
|
-
/* Prevent vertical page scroll from "rubber-banding" into the
|
|
1342
|
-
carousel and vice-versa on iOS. */
|
|
1343
|
-
overscroll-behavior-x: contain;
|
|
1344
|
-
/* Hide native scrollbars on mobile while keeping scroll behaviour. */
|
|
1345
|
-
scrollbar-width: none;
|
|
1346
|
-
}
|
|
1347
|
-
[data-carousel-viewport]::-webkit-scrollbar {
|
|
1348
|
-
display: none;
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
[data-carousel-slide] {
|
|
1352
|
-
flex: 0 0 100%;
|
|
1353
|
-
scroll-snap-align: start;
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
/* Stop the OS picking up an image for drag/save during a swipe. Repeated on
|
|
1357
|
-
the media element itself, not just the slide wrapper — -webkit-user-drag
|
|
1358
|
-
isn't inherited, so a real <img>'s own native drag-source eligibility is
|
|
1359
|
-
unaffected by an ancestor's value. WebKit-only (no Firefox equivalent);
|
|
1360
|
-
pair with `allowMouseDrag`, which also `preventDefault()`s the drag start
|
|
1361
|
-
in JS for full cross-browser coverage. */
|
|
1362
|
-
[data-carousel-slide],
|
|
1363
|
-
[data-carousel-slide] > img,
|
|
1364
|
-
[data-carousel-slide] > video,
|
|
1365
|
-
[data-carousel-slide] > picture,
|
|
1366
|
-
[data-carousel-slide] > picture > img {
|
|
1367
|
-
-webkit-user-drag: none;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
/* WCAG 2.5.8: 24×24 minimum hit area; 44×44 recommended for comfort
|
|
1371
|
-
on phones. The visible dot stays small via ::before so the button's
|
|
1372
|
-
hit area can be larger than its visual footprint. */
|
|
1373
|
-
[data-carousel-indicator] {
|
|
1374
|
-
min-width: 44px;
|
|
1375
|
-
min-height: 44px;
|
|
1376
|
-
display: inline-grid;
|
|
1377
|
-
place-items: center;
|
|
1378
|
-
}
|
|
1379
|
-
[data-carousel-indicator]::before {
|
|
1380
|
-
content: "";
|
|
1381
|
-
width: 0.5rem;
|
|
1382
|
-
height: 0.5rem;
|
|
1383
|
-
border-radius: 50%;
|
|
1384
|
-
background: lightgray;
|
|
1385
|
-
}
|
|
1386
|
-
[data-carousel-indicator][data-state="active"]::before {
|
|
1387
|
-
background: black;
|
|
1388
|
-
}
|
|
1389
|
-
```
|
|
1390
|
-
|
|
1391
|
-
For multi-slide pages (`slidesPerPage={3}`, etc.), tune the slide's
|
|
1392
|
-
`flex-basis` to share the viewport — e.g. `calc(100% / 3)` for three
|
|
1393
|
-
slides per page, plus a `gap` on the viewport for the inter-slide
|
|
1394
|
-
spacing. **Scope `scroll-snap-align` to `[data-snap-align]` instead of
|
|
1395
|
-
every `[data-carousel-slide]`** once `slidesPerPage > 1` — see
|
|
1396
|
-
"Multi-slide snap targeting" below; the recipe above is correct as-is
|
|
1397
|
-
for the single-slide-per-page default, where every slide carries the
|
|
1398
|
-
hook. For a crossfade transition, use `transition="none"` on
|
|
1399
|
-
`Carousel.Root` and style the slides absolute-positioned with an
|
|
1400
|
-
opacity transition keyed off `[data-carousel-slide][data-state="active"]`.
|
|
1401
|
-
|
|
1402
|
-
### Multi-slide snap targeting
|
|
1403
|
-
|
|
1404
|
-
When `slidesPerPage > 1`, only a page's *leading* slide is a valid
|
|
1405
|
-
scroll-snap resting position — an interior slide has no page of its
|
|
1406
|
-
own, so letting the browser's mandatory snap stop there leaves the
|
|
1407
|
-
viewport showing a straddled mix of two pages while `currentPage` (and
|
|
1408
|
-
any indicators driven from it) still claim a single clean page is
|
|
1409
|
-
active. This is easy to hit with incremental input — a mouse wheel
|
|
1410
|
-
notch or a drag release — that lands mid-page rather than jumping a
|
|
1411
|
-
full page at once. Scope `scroll-snap-align` to the `data-snap-align`
|
|
1412
|
-
hook (present only on each page's leading slide, and on every slide
|
|
1413
|
-
when `slidesPerPage` is 1) rather than applying it to every slide. Its
|
|
1414
|
-
*value* mirrors the root's resolved `snapAlign` — or the individual
|
|
1415
|
-
slide's own override (`Carousel.Slide`'s `snapAlign` prop), if it set
|
|
1416
|
-
one — so a user's own scroll (wheel/touch/drag) settles wherever the
|
|
1417
|
-
programmatic scroll already targets. Style all three values, not just
|
|
1418
|
-
`"start"`, if the consumer might set `snapAlign="center"` / `"end"` on
|
|
1419
|
-
the root or on individual slides:
|
|
1420
|
-
|
|
1421
|
-
```css
|
|
1422
|
-
[data-carousel-slide] {
|
|
1423
|
-
flex: 0 0 calc(100% / 3); /* three slides per page, for example */
|
|
1424
|
-
}
|
|
1425
|
-
[data-carousel-slide][data-snap-align="start"] {
|
|
1426
|
-
scroll-snap-align: start;
|
|
1427
|
-
}
|
|
1428
|
-
[data-carousel-slide][data-snap-align="center"] {
|
|
1429
|
-
scroll-snap-align: center;
|
|
1430
|
-
}
|
|
1431
|
-
[data-carousel-slide][data-snap-align="end"] {
|
|
1432
|
-
scroll-snap-align: end;
|
|
1433
|
-
}
|
|
1434
|
-
```
|
|
1435
|
-
|
|
1436
|
-
**Centering/ending a multi-slide page, not just its leading slide.** A
|
|
1437
|
-
`scroll-snap-align` on a single element only ever aligns *that* element's
|
|
1438
|
-
own box — `scroll-snap-align: center` on the leading slide would centre
|
|
1439
|
-
just the leading slide, leaving the rest of a `slidesPerPage > 1` page
|
|
1440
|
-
clipped off the trailing edge, if that were the whole story. It isn't:
|
|
1441
|
-
the Viewport also sets `scroll-margin-inline-end` (`-block-end` when
|
|
1442
|
-
vertical) on each page's leading slide, extending its native snap area —
|
|
1443
|
-
invisibly, with no layout effect — out to the page's actual last member.
|
|
1444
|
-
So `scroll-snap-align: center`/`"end"` end up centering/ending the whole
|
|
1445
|
-
page, matching what the programmatic `scrollTo` already does. This is
|
|
1446
|
-
automatic and needs no consumer CSS; it's a no-op when `slidesPerPage` is
|
|
1447
|
-
1 (the leading slide already *is* the whole page).
|