@base-ui/react 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +125 -8
- package/README.md +1 -1
- package/accordion/item/AccordionItem.d.ts +4 -0
- package/accordion/item/AccordionItem.js +5 -4
- package/accordion/panel/AccordionPanel.js +29 -51
- package/accordion/root/AccordionRoot.js +5 -6
- package/accordion/trigger/AccordionTrigger.js +3 -4
- package/alert-dialog/handle.d.ts +14 -1
- package/alert-dialog/handle.js +22 -5
- package/alert-dialog/index.d.ts +1 -1
- package/alert-dialog/index.parts.d.ts +2 -3
- package/alert-dialog/index.parts.js +4 -5
- package/alert-dialog/root/AlertDialogRoot.d.ts +7 -7
- package/alert-dialog/root/AlertDialogRoot.js +2 -56
- package/alert-dialog/trigger/AlertDialogTrigger.d.ts +25 -0
- package/alert-dialog/trigger/AlertDialogTrigger.js +15 -0
- package/alert-dialog/trigger/AlertDialogTriggerDataAttributes.d.ts +10 -0
- package/alert-dialog/trigger/AlertDialogTriggerDataAttributes.js +18 -0
- package/autocomplete/root/AutocompleteRoot.js +9 -10
- package/avatar/image/AvatarImage.js +4 -4
- package/checkbox/indicator/CheckboxIndicator.js +2 -2
- package/checkbox/root/CheckboxRoot.js +49 -11
- package/checkbox-group/CheckboxGroup.js +1 -5
- package/collapsible/panel/CollapsiblePanel.js +29 -51
- package/collapsible/panel/useCollapsiblePanel.d.ts +9 -23
- package/collapsible/panel/useCollapsiblePanel.js +308 -268
- package/collapsible/root/CollapsibleRoot.d.ts +1 -1
- package/collapsible/root/CollapsibleRootContext.d.ts +0 -2
- package/collapsible/root/useCollapsibleRoot.d.ts +0 -27
- package/collapsible/root/useCollapsibleRoot.js +2 -64
- package/collapsible/trigger/CollapsibleTrigger.js +5 -6
- package/combobox/arrow/ComboboxArrow.js +1 -1
- package/combobox/backdrop/ComboboxBackdrop.js +1 -1
- package/combobox/chip/ComboboxChip.js +7 -2
- package/combobox/clear/ComboboxClear.d.ts +4 -0
- package/combobox/clear/ComboboxClear.js +1 -0
- package/combobox/clear/ComboboxClearDataAttributes.d.ts +4 -0
- package/combobox/clear/ComboboxClearDataAttributes.js +4 -0
- package/combobox/icon/ComboboxIcon.js +1 -1
- package/combobox/input/ComboboxInput.js +15 -6
- package/combobox/item/ComboboxItem.js +8 -14
- package/combobox/item-indicator/ComboboxItemIndicator.js +1 -2
- package/combobox/root/AriaCombobox.js +61 -28
- package/combobox/store.d.ts +4 -8
- package/combobox/store.js +2 -1
- package/combobox/utils/ComboboxInternalDismissButton.js +2 -3
- package/csp-provider/CSPProvider.js +1 -1
- package/dialog/close/DialogClose.js +6 -6
- package/dialog/popup/DialogPopup.js +9 -4
- package/dialog/root/DialogRoot.d.ts +1 -2
- package/dialog/root/DialogRoot.js +3 -73
- package/dialog/root/DialogRootContext.d.ts +1 -0
- package/dialog/root/DialogRootContext.js +3 -1
- package/dialog/root/useDialogRoot.d.ts +12 -4
- package/dialog/root/useDialogRoot.js +27 -25
- package/dialog/root/useRenderDialogRoot.d.ts +4 -0
- package/dialog/root/useRenderDialogRoot.js +96 -0
- package/dialog/store/DialogHandle.d.ts +1 -1
- package/dialog/store/DialogHandle.js +2 -2
- package/dialog/store/DialogStore.d.ts +88 -1
- package/dialog/store/DialogStore.js +12 -17
- package/dialog/trigger/DialogTrigger.d.ts +1 -1
- package/dialog/trigger/DialogTrigger.js +11 -4
- package/dialog/viewport/DialogViewport.js +4 -3
- package/drawer/popup/DrawerPopup.js +13 -9
- package/drawer/root/DrawerRoot.js +11 -11
- package/drawer/root/DrawerRootContext.d.ts +1 -1
- package/drawer/swipe-area/DrawerSwipeArea.js +6 -5
- package/drawer/viewport/DrawerViewport.js +13 -14
- package/esm/accordion/item/AccordionItem.d.ts +4 -0
- package/esm/accordion/item/AccordionItem.js +5 -4
- package/esm/accordion/panel/AccordionPanel.js +29 -51
- package/esm/accordion/root/AccordionRoot.js +5 -6
- package/esm/accordion/trigger/AccordionTrigger.js +4 -5
- package/esm/alert-dialog/handle.d.ts +14 -1
- package/esm/alert-dialog/handle.js +20 -5
- package/esm/alert-dialog/index.d.ts +1 -1
- package/esm/alert-dialog/index.parts.d.ts +2 -3
- package/esm/alert-dialog/index.parts.js +2 -3
- package/esm/alert-dialog/root/AlertDialogRoot.d.ts +7 -7
- package/esm/alert-dialog/root/AlertDialogRoot.js +2 -55
- package/esm/alert-dialog/trigger/AlertDialogTrigger.d.ts +25 -0
- package/esm/alert-dialog/trigger/AlertDialogTrigger.js +10 -0
- package/esm/alert-dialog/trigger/AlertDialogTriggerDataAttributes.d.ts +10 -0
- package/esm/alert-dialog/trigger/AlertDialogTriggerDataAttributes.js +12 -0
- package/esm/autocomplete/root/AutocompleteRoot.js +9 -10
- package/esm/avatar/image/AvatarImage.js +4 -4
- package/esm/checkbox/indicator/CheckboxIndicator.js +2 -2
- package/esm/checkbox/root/CheckboxRoot.js +49 -11
- package/esm/checkbox-group/CheckboxGroup.js +1 -5
- package/esm/collapsible/panel/CollapsiblePanel.js +29 -51
- package/esm/collapsible/panel/useCollapsiblePanel.d.ts +9 -23
- package/esm/collapsible/panel/useCollapsiblePanel.js +309 -269
- package/esm/collapsible/root/CollapsibleRoot.d.ts +1 -1
- package/esm/collapsible/root/CollapsibleRootContext.d.ts +0 -2
- package/esm/collapsible/root/useCollapsibleRoot.d.ts +0 -27
- package/esm/collapsible/root/useCollapsibleRoot.js +2 -64
- package/esm/collapsible/trigger/CollapsibleTrigger.js +5 -6
- package/esm/combobox/arrow/ComboboxArrow.js +1 -1
- package/esm/combobox/backdrop/ComboboxBackdrop.js +1 -1
- package/esm/combobox/chip/ComboboxChip.js +7 -2
- package/esm/combobox/clear/ComboboxClear.d.ts +4 -0
- package/esm/combobox/clear/ComboboxClear.js +1 -0
- package/esm/combobox/clear/ComboboxClearDataAttributes.d.ts +4 -0
- package/esm/combobox/clear/ComboboxClearDataAttributes.js +4 -0
- package/esm/combobox/icon/ComboboxIcon.js +1 -1
- package/esm/combobox/input/ComboboxInput.js +16 -7
- package/esm/combobox/item/ComboboxItem.js +8 -14
- package/esm/combobox/item-indicator/ComboboxItemIndicator.js +1 -2
- package/esm/combobox/root/AriaCombobox.js +62 -29
- package/esm/combobox/store.d.ts +4 -8
- package/esm/combobox/store.js +2 -1
- package/esm/combobox/utils/ComboboxInternalDismissButton.js +2 -3
- package/esm/csp-provider/CSPProvider.js +1 -1
- package/esm/dialog/close/DialogClose.js +6 -6
- package/esm/dialog/popup/DialogPopup.js +9 -4
- package/esm/dialog/root/DialogRoot.d.ts +1 -2
- package/esm/dialog/root/DialogRoot.js +4 -72
- package/esm/dialog/root/DialogRootContext.d.ts +1 -0
- package/esm/dialog/root/DialogRootContext.js +2 -0
- package/esm/dialog/root/useDialogRoot.d.ts +12 -4
- package/esm/dialog/root/useDialogRoot.js +28 -27
- package/esm/dialog/root/useRenderDialogRoot.d.ts +4 -0
- package/esm/dialog/root/useRenderDialogRoot.js +90 -0
- package/esm/dialog/store/DialogHandle.d.ts +1 -1
- package/esm/dialog/store/DialogHandle.js +2 -2
- package/esm/dialog/store/DialogStore.d.ts +88 -1
- package/esm/dialog/store/DialogStore.js +13 -18
- package/esm/dialog/trigger/DialogTrigger.d.ts +1 -1
- package/esm/dialog/trigger/DialogTrigger.js +12 -5
- package/esm/dialog/viewport/DialogViewport.js +4 -3
- package/esm/drawer/popup/DrawerPopup.js +14 -9
- package/esm/drawer/root/DrawerRoot.js +11 -11
- package/esm/drawer/root/DrawerRootContext.d.ts +1 -1
- package/esm/drawer/swipe-area/DrawerSwipeArea.js +6 -5
- package/esm/drawer/viewport/DrawerViewport.js +13 -14
- package/esm/field/control/FieldControl.js +2 -6
- package/esm/field/item/FieldItem.js +1 -4
- package/esm/field/root/FieldRoot.js +11 -3
- package/esm/field/root/useFieldValidation.d.ts +1 -0
- package/esm/field/root/useFieldValidation.js +23 -20
- package/esm/field/utils/getCombinedFieldValidityData.d.ts +1 -1
- package/esm/field/validity/FieldValidity.d.ts +1 -1
- package/esm/floating-ui-react/components/FloatingDelayGroup.js +3 -3
- package/esm/floating-ui-react/components/FloatingFocusManager.d.ts +1 -1
- package/esm/floating-ui-react/components/FloatingFocusManager.js +20 -8
- package/esm/floating-ui-react/components/FloatingPortal.js +3 -3
- package/esm/floating-ui-react/hooks/useClick.js +83 -74
- package/esm/floating-ui-react/hooks/useClientPoint.js +29 -20
- package/esm/floating-ui-react/hooks/useDismiss.d.ts +1 -1
- package/esm/floating-ui-react/hooks/useDismiss.js +82 -93
- package/esm/floating-ui-react/hooks/useFloating.js +37 -32
- package/esm/floating-ui-react/hooks/useFloatingRootContext.d.ts +1 -1
- package/esm/floating-ui-react/hooks/useFloatingRootContext.js +2 -2
- package/esm/floating-ui-react/hooks/useFocus.js +84 -81
- package/esm/floating-ui-react/hooks/useHover.js +72 -76
- package/esm/floating-ui-react/hooks/useHoverFloatingInteraction.js +49 -44
- package/esm/floating-ui-react/hooks/useHoverInteractionSharedState.js +1 -1
- package/esm/floating-ui-react/hooks/useHoverReferenceInteraction.d.ts +7 -2
- package/esm/floating-ui-react/hooks/useHoverReferenceInteraction.js +44 -39
- package/esm/floating-ui-react/hooks/useHoverShared.d.ts +2 -1
- package/esm/floating-ui-react/hooks/useHoverShared.js +4 -0
- package/esm/floating-ui-react/hooks/useListNavigation.d.ts +1 -3
- package/esm/floating-ui-react/hooks/useListNavigation.js +83 -74
- package/esm/floating-ui-react/hooks/useSyncedFloatingRootContext.d.ts +9 -6
- package/esm/floating-ui-react/hooks/useSyncedFloatingRootContext.js +25 -20
- package/esm/floating-ui-react/hooks/useTypeahead.d.ts +2 -2
- package/esm/floating-ui-react/hooks/useTypeahead.js +33 -52
- package/esm/floating-ui-react/index.d.ts +0 -2
- package/esm/floating-ui-react/index.js +0 -2
- package/esm/floating-ui-react/types.d.ts +2 -7
- package/esm/floating-ui-react/utils/composite.js +2 -0
- package/esm/floating-ui-react/utils/enqueueFocus.d.ts +1 -1
- package/esm/floating-ui-react/utils/enqueueFocus.js +10 -7
- package/esm/floating-ui-react/utils/getEmptyRootContext.js +1 -1
- package/esm/form/Form.js +2 -2
- package/esm/index.js +1 -1
- package/esm/internals/composite/composite.d.ts +0 -1
- package/esm/internals/composite/composite.js +1 -2
- package/esm/internals/composite/root/useCompositeRoot.js +2 -2
- package/esm/internals/createBaseUIEventDetails.d.ts +2 -0
- package/esm/internals/csp-context/index.d.ts +2 -0
- package/esm/internals/csp-context/index.js +1 -0
- package/esm/internals/field-register-control/index.d.ts +0 -1
- package/esm/internals/field-register-control/useFieldControlRegistration.d.ts +2 -1
- package/esm/internals/field-register-control/useFieldControlRegistration.js +11 -14
- package/esm/internals/field-register-control/useRegisterFieldControl.d.ts +1 -4
- package/esm/internals/field-register-control/useRegisterFieldControl.js +6 -11
- package/esm/internals/field-root-context/FieldRootContext.d.ts +1 -0
- package/esm/internals/field-root-context/FieldRootContext.js +3 -2
- package/esm/internals/form-context/FormContext.d.ts +5 -1
- package/esm/internals/reason-parts.d.ts +2 -0
- package/esm/internals/reason-parts.js +2 -0
- package/esm/internals/types.d.ts +1 -0
- package/esm/internals/use-button/useButton.js +4 -4
- package/esm/internals/usePressAndHold.js +2 -2
- package/esm/internals/useRenderElement.js +2 -0
- package/esm/menu/arrow/MenuArrow.js +1 -1
- package/esm/menu/backdrop/MenuBackdrop.js +1 -1
- package/esm/menu/checkbox-item/MenuCheckboxItem.js +5 -7
- package/esm/menu/group/MenuGroup.js +1 -4
- package/esm/menu/group/MenuGroupContext.d.ts +1 -3
- package/esm/menu/group/MenuGroupContext.js +1 -1
- package/esm/menu/group-label/MenuGroupLabel.js +4 -6
- package/esm/menu/link-item/MenuLinkItem.js +2 -2
- package/esm/menu/popup/MenuPopup.js +5 -5
- package/esm/menu/radio-group/MenuRadioGroup.js +11 -5
- package/esm/menu/radio-item/MenuRadioItem.js +5 -7
- package/esm/menu/root/MenuRoot.js +63 -68
- package/esm/menu/store/MenuHandle.js +1 -1
- package/esm/menu/store/MenuStore.d.ts +87 -0
- package/esm/menu/submenu-trigger/MenuSubmenuTrigger.js +8 -5
- package/esm/menu/trigger/MenuTrigger.js +13 -10
- package/esm/menu/viewport/MenuViewport.d.ts +2 -2
- package/esm/menu/viewport/MenuViewport.js +2 -2
- package/esm/navigation-menu/arrow/NavigationMenuArrow.js +1 -1
- package/esm/navigation-menu/backdrop/NavigationMenuBackdrop.js +1 -1
- package/esm/navigation-menu/content/NavigationMenuContent.js +8 -5
- package/esm/navigation-menu/icon/NavigationMenuIcon.js +1 -1
- package/esm/navigation-menu/item/NavigationMenuItem.js +2 -2
- package/esm/navigation-menu/list/NavigationMenuList.js +1 -1
- package/esm/navigation-menu/popup/NavigationMenuPopup.js +2 -2
- package/esm/navigation-menu/root/NavigationMenuRoot.js +1 -3
- package/esm/navigation-menu/trigger/NavigationMenuTrigger.js +24 -17
- package/esm/navigation-menu/utils/isOutsideMenuEvent.d.ts +0 -1
- package/esm/navigation-menu/utils/isOutsideMenuEvent.js +1 -5
- package/esm/navigation-menu/viewport/NavigationMenuViewport.js +2 -3
- package/esm/number-field/input/NumberFieldInput.js +3 -5
- package/esm/number-field/root/NumberFieldRoot.js +5 -2
- package/esm/number-field/scrub-area/NumberFieldScrubArea.js +7 -3
- package/esm/otp-field/input/OTPFieldInput.js +43 -29
- package/esm/otp-field/root/OTPFieldRoot.d.ts +17 -8
- package/esm/otp-field/root/OTPFieldRoot.js +33 -33
- package/esm/otp-field/root/OTPFieldRootContext.d.ts +1 -1
- package/esm/otp-field/utils/otp.d.ts +5 -4
- package/esm/otp-field/utils/otp.js +23 -12
- package/esm/popover/arrow/PopoverArrow.js +1 -1
- package/esm/popover/backdrop/PopoverBackdrop.js +1 -1
- package/esm/popover/close/PopoverClose.js +2 -2
- package/esm/popover/description/PopoverDescription.js +1 -7
- package/esm/popover/popup/PopoverPopup.d.ts +1 -1
- package/esm/popover/popup/PopoverPopup.js +16 -10
- package/esm/popover/popup/PopoverPopupDataAttributes.d.ts +1 -1
- package/esm/popover/popup/PopoverPopupDataAttributes.js +1 -1
- package/esm/popover/positioner/PopoverPositioner.js +5 -5
- package/esm/popover/root/PopoverRoot.d.ts +1 -1
- package/esm/popover/root/PopoverRoot.js +42 -47
- package/esm/popover/store/PopoverHandle.js +1 -1
- package/esm/popover/store/PopoverStore.d.ts +91 -4
- package/esm/popover/store/PopoverStore.js +17 -18
- package/esm/popover/title/PopoverTitle.js +1 -7
- package/esm/popover/trigger/PopoverTrigger.js +24 -17
- package/esm/popover/viewport/PopoverViewport.d.ts +3 -3
- package/esm/popover/viewport/PopoverViewport.js +2 -2
- package/esm/popover/viewport/PopoverViewportDataAttributes.d.ts +1 -1
- package/esm/popover/viewport/PopoverViewportDataAttributes.js +1 -1
- package/esm/preview-card/positioner/PreviewCardPositioner.js +11 -1
- package/esm/preview-card/root/PreviewCardRoot.d.ts +1 -1
- package/esm/preview-card/root/PreviewCardRoot.js +32 -22
- package/esm/preview-card/store/PreviewCardHandle.js +1 -1
- package/esm/preview-card/store/PreviewCardStore.d.ts +90 -2
- package/esm/preview-card/store/PreviewCardStore.js +19 -31
- package/esm/preview-card/trigger/PreviewCardTrigger.js +6 -3
- package/esm/preview-card/viewport/PreviewCardViewport.d.ts +2 -2
- package/esm/preview-card/viewport/PreviewCardViewport.js +2 -2
- package/esm/preview-card/viewport/PreviewCardViewportDataAttributes.d.ts +2 -2
- package/esm/preview-card/viewport/PreviewCardViewportDataAttributes.js +2 -2
- package/esm/progress/indicator/ProgressIndicator.js +6 -11
- package/esm/progress/root/ProgressRoot.d.ts +1 -1
- package/esm/radio/root/RadioRoot.js +7 -3
- package/esm/radio-group/RadioGroup.js +4 -11
- package/esm/radio-group/RadioGroupContext.d.ts +0 -1
- package/esm/scroll-area/content/ScrollAreaContent.js +4 -4
- package/esm/scroll-area/root/ScrollAreaRoot.js +1 -1
- package/esm/scroll-area/scrollbar/ScrollAreaScrollbar.js +16 -20
- package/esm/scroll-area/viewport/ScrollAreaViewport.js +6 -10
- package/esm/select/arrow/SelectArrow.js +1 -1
- package/esm/select/backdrop/SelectBackdrop.js +1 -1
- package/esm/select/group/SelectGroup.js +1 -1
- package/esm/select/group-label/SelectGroupLabel.js +2 -2
- package/esm/select/icon/SelectIcon.js +1 -1
- package/esm/select/item/SelectItem.js +46 -32
- package/esm/select/item/SelectItemContext.d.ts +1 -1
- package/esm/select/item-indicator/SelectItemIndicator.js +1 -2
- package/esm/select/item-text/SelectItemText.js +9 -6
- package/esm/select/list/SelectList.js +1 -1
- package/esm/select/popup/SelectPopup.js +8 -3
- package/esm/select/positioner/SelectPositioner.js +3 -0
- package/esm/select/root/SelectRoot.js +46 -40
- package/esm/select/root/SelectRootContext.d.ts +4 -5
- package/esm/select/store.d.ts +3 -0
- package/esm/select/store.js +1 -0
- package/esm/select/trigger/SelectTrigger.d.ts +5 -0
- package/esm/select/trigger/SelectTrigger.js +19 -33
- package/esm/select/trigger/SelectTriggerDataAttributes.d.ts +5 -0
- package/esm/select/trigger/SelectTriggerDataAttributes.js +5 -0
- package/esm/slider/control/SliderControl.js +10 -12
- package/esm/slider/root/SliderRoot.js +1 -4
- package/esm/slider/thumb/SliderThumb.js +32 -30
- package/esm/slider/value/SliderValue.js +7 -15
- package/esm/switch/root/SwitchRoot.js +10 -10
- package/esm/switch/thumb/SwitchThumb.js +1 -9
- package/esm/tabs/indicator/TabsIndicator.js +14 -19
- package/esm/tabs/list/TabsList.js +4 -10
- package/esm/tabs/list/TabsListContext.d.ts +2 -1
- package/esm/tabs/panel/TabsPanel.js +1 -1
- package/esm/tabs/root/TabsRoot.d.ts +16 -1
- package/esm/tabs/root/TabsRoot.js +73 -25
- package/esm/tabs/root/TabsRootContext.d.ts +0 -2
- package/esm/toast/provider/ToastProvider.js +1 -1
- package/esm/toast/root/ToastRoot.d.ts +1 -1
- package/esm/toast/root/ToastRoot.js +108 -131
- package/esm/toast/root/ToastRootDataAttributes.d.ts +1 -1
- package/esm/toast/root/ToastRootDataAttributes.js +1 -1
- package/esm/toast/store.d.ts +9 -1
- package/esm/toast/store.js +19 -13
- package/esm/toast/useToastManager.d.ts +1 -1
- package/esm/toast/viewport/ToastViewport.js +1 -1
- package/esm/toggle/Toggle.js +5 -9
- package/esm/toggle-group/ToggleGroup.d.ts +2 -2
- package/esm/toggle-group/ToggleGroup.js +6 -13
- package/esm/toolbar/link/ToolbarLink.d.ts +1 -1
- package/esm/toolbar/link/ToolbarLink.js +1 -2
- package/esm/tooltip/arrow/TooltipArrow.js +3 -3
- package/esm/tooltip/popup/TooltipPopup.js +5 -4
- package/esm/tooltip/root/TooltipRoot.js +35 -26
- package/esm/tooltip/store/TooltipHandle.js +1 -1
- package/esm/tooltip/store/TooltipStore.d.ts +90 -2
- package/esm/tooltip/store/TooltipStore.js +18 -31
- package/esm/tooltip/trigger/TooltipTrigger.js +151 -20
- package/esm/tooltip/viewport/TooltipViewport.d.ts +2 -2
- package/esm/tooltip/viewport/TooltipViewport.js +2 -2
- package/esm/tooltip/viewport/TooltipViewportDataAttributes.d.ts +1 -1
- package/esm/tooltip/viewport/TooltipViewportDataAttributes.js +1 -1
- package/esm/unstable-use-media-query/index.js +1 -1
- package/esm/utils/popups/index.d.ts +1 -0
- package/esm/utils/popups/index.js +1 -0
- package/esm/utils/popups/inlineRect.d.ts +15 -0
- package/esm/utils/popups/inlineRect.js +191 -0
- package/esm/utils/popups/popupStoreUtils.d.ts +28 -10
- package/esm/utils/popups/popupStoreUtils.js +105 -20
- package/esm/utils/popups/popupTriggerMap.js +2 -0
- package/esm/utils/popups/store.d.ts +15 -2
- package/esm/utils/popups/store.js +38 -2
- package/esm/utils/popups/useTriggerFocusGuards.js +4 -5
- package/esm/utils/useAnchorPositioning.d.ts +5 -0
- package/esm/utils/useAnchorPositioning.js +12 -9
- package/esm/utils/useOpenInteractionType.d.ts +4 -0
- package/esm/utils/useOpenInteractionType.js +23 -18
- package/field/control/FieldControl.js +2 -6
- package/field/item/FieldItem.js +1 -4
- package/field/root/FieldRoot.js +11 -3
- package/field/root/useFieldValidation.d.ts +1 -0
- package/field/root/useFieldValidation.js +23 -20
- package/field/utils/getCombinedFieldValidityData.d.ts +1 -1
- package/field/validity/FieldValidity.d.ts +1 -1
- package/floating-ui-react/components/FloatingDelayGroup.js +3 -3
- package/floating-ui-react/components/FloatingFocusManager.d.ts +1 -1
- package/floating-ui-react/components/FloatingFocusManager.js +20 -8
- package/floating-ui-react/components/FloatingPortal.js +3 -3
- package/floating-ui-react/hooks/useClick.js +82 -73
- package/floating-ui-react/hooks/useClientPoint.js +29 -20
- package/floating-ui-react/hooks/useDismiss.d.ts +1 -1
- package/floating-ui-react/hooks/useDismiss.js +82 -92
- package/floating-ui-react/hooks/useFloating.js +36 -32
- package/floating-ui-react/hooks/useFloatingRootContext.d.ts +1 -1
- package/floating-ui-react/hooks/useFloatingRootContext.js +2 -2
- package/floating-ui-react/hooks/useFocus.js +84 -81
- package/floating-ui-react/hooks/useHover.js +74 -78
- package/floating-ui-react/hooks/useHoverFloatingInteraction.js +48 -43
- package/floating-ui-react/hooks/useHoverInteractionSharedState.js +1 -1
- package/floating-ui-react/hooks/useHoverReferenceInteraction.d.ts +7 -2
- package/floating-ui-react/hooks/useHoverReferenceInteraction.js +43 -38
- package/floating-ui-react/hooks/useHoverShared.d.ts +2 -1
- package/floating-ui-react/hooks/useHoverShared.js +11 -0
- package/floating-ui-react/hooks/useListNavigation.d.ts +1 -3
- package/floating-ui-react/hooks/useListNavigation.js +83 -74
- package/floating-ui-react/hooks/useSyncedFloatingRootContext.d.ts +9 -6
- package/floating-ui-react/hooks/useSyncedFloatingRootContext.js +26 -20
- package/floating-ui-react/hooks/useTypeahead.d.ts +2 -2
- package/floating-ui-react/hooks/useTypeahead.js +33 -52
- package/floating-ui-react/index.d.ts +0 -2
- package/floating-ui-react/index.js +0 -14
- package/floating-ui-react/types.d.ts +2 -7
- package/floating-ui-react/utils/composite.js +2 -0
- package/floating-ui-react/utils/enqueueFocus.d.ts +1 -1
- package/floating-ui-react/utils/enqueueFocus.js +10 -7
- package/floating-ui-react/utils/getEmptyRootContext.js +1 -1
- package/form/Form.js +2 -2
- package/index.js +1 -1
- package/internals/composite/composite.d.ts +0 -1
- package/internals/composite/composite.js +2 -3
- package/internals/composite/root/useCompositeRoot.js +1 -1
- package/internals/createBaseUIEventDetails.d.ts +2 -0
- package/internals/csp-context/index.d.ts +2 -0
- package/internals/csp-context/index.js +18 -0
- package/internals/field-register-control/index.d.ts +0 -1
- package/internals/field-register-control/useFieldControlRegistration.d.ts +2 -1
- package/internals/field-register-control/useFieldControlRegistration.js +11 -14
- package/internals/field-register-control/useRegisterFieldControl.d.ts +1 -4
- package/internals/field-register-control/useRegisterFieldControl.js +6 -11
- package/internals/field-root-context/FieldRootContext.d.ts +1 -0
- package/internals/field-root-context/FieldRootContext.js +4 -3
- package/internals/form-context/FormContext.d.ts +5 -1
- package/internals/reason-parts.d.ts +2 -0
- package/internals/reason-parts.js +3 -1
- package/internals/types.d.ts +1 -0
- package/internals/use-button/useButton.js +4 -4
- package/internals/usePressAndHold.js +2 -2
- package/internals/useRenderElement.js +2 -0
- package/menu/arrow/MenuArrow.js +1 -1
- package/menu/backdrop/MenuBackdrop.js +1 -1
- package/menu/checkbox-item/MenuCheckboxItem.js +5 -7
- package/menu/group/MenuGroup.js +1 -4
- package/menu/group/MenuGroupContext.d.ts +1 -3
- package/menu/group/MenuGroupContext.js +1 -1
- package/menu/group-label/MenuGroupLabel.js +4 -6
- package/menu/link-item/MenuLinkItem.js +2 -2
- package/menu/popup/MenuPopup.js +5 -5
- package/menu/radio-group/MenuRadioGroup.js +11 -5
- package/menu/radio-item/MenuRadioItem.js +5 -7
- package/menu/root/MenuRoot.js +60 -65
- package/menu/store/MenuHandle.js +1 -1
- package/menu/store/MenuStore.d.ts +87 -0
- package/menu/submenu-trigger/MenuSubmenuTrigger.js +7 -4
- package/menu/trigger/MenuTrigger.js +12 -9
- package/menu/viewport/MenuViewport.d.ts +2 -2
- package/menu/viewport/MenuViewport.js +2 -2
- package/navigation-menu/arrow/NavigationMenuArrow.js +1 -1
- package/navigation-menu/backdrop/NavigationMenuBackdrop.js +1 -1
- package/navigation-menu/content/NavigationMenuContent.js +8 -5
- package/navigation-menu/icon/NavigationMenuIcon.js +1 -1
- package/navigation-menu/item/NavigationMenuItem.js +2 -2
- package/navigation-menu/list/NavigationMenuList.js +1 -1
- package/navigation-menu/popup/NavigationMenuPopup.js +2 -2
- package/navigation-menu/root/NavigationMenuRoot.js +1 -3
- package/navigation-menu/trigger/NavigationMenuTrigger.js +23 -16
- package/navigation-menu/utils/isOutsideMenuEvent.d.ts +0 -1
- package/navigation-menu/utils/isOutsideMenuEvent.js +1 -5
- package/navigation-menu/viewport/NavigationMenuViewport.js +2 -3
- package/number-field/input/NumberFieldInput.js +3 -5
- package/number-field/root/NumberFieldRoot.js +5 -2
- package/number-field/scrub-area/NumberFieldScrubArea.js +7 -3
- package/otp-field/input/OTPFieldInput.js +42 -28
- package/otp-field/root/OTPFieldRoot.d.ts +17 -8
- package/otp-field/root/OTPFieldRoot.js +32 -32
- package/otp-field/root/OTPFieldRootContext.d.ts +1 -1
- package/otp-field/utils/otp.d.ts +5 -4
- package/otp-field/utils/otp.js +24 -12
- package/package.json +331 -317
- package/popover/arrow/PopoverArrow.js +1 -1
- package/popover/backdrop/PopoverBackdrop.js +1 -1
- package/popover/close/PopoverClose.js +2 -2
- package/popover/description/PopoverDescription.js +1 -7
- package/popover/popup/PopoverPopup.d.ts +1 -1
- package/popover/popup/PopoverPopup.js +16 -10
- package/popover/popup/PopoverPopupDataAttributes.d.ts +1 -1
- package/popover/popup/PopoverPopupDataAttributes.js +1 -1
- package/popover/positioner/PopoverPositioner.js +5 -5
- package/popover/root/PopoverRoot.d.ts +1 -1
- package/popover/root/PopoverRoot.js +39 -44
- package/popover/store/PopoverHandle.js +1 -1
- package/popover/store/PopoverStore.d.ts +91 -4
- package/popover/store/PopoverStore.js +16 -19
- package/popover/title/PopoverTitle.js +1 -7
- package/popover/trigger/PopoverTrigger.js +23 -16
- package/popover/viewport/PopoverViewport.d.ts +3 -3
- package/popover/viewport/PopoverViewport.js +2 -2
- package/popover/viewport/PopoverViewportDataAttributes.d.ts +1 -1
- package/popover/viewport/PopoverViewportDataAttributes.js +1 -1
- package/preview-card/positioner/PreviewCardPositioner.js +11 -1
- package/preview-card/root/PreviewCardRoot.d.ts +1 -1
- package/preview-card/root/PreviewCardRoot.js +30 -20
- package/preview-card/store/PreviewCardHandle.js +1 -1
- package/preview-card/store/PreviewCardStore.d.ts +90 -2
- package/preview-card/store/PreviewCardStore.js +18 -30
- package/preview-card/trigger/PreviewCardTrigger.js +5 -2
- package/preview-card/viewport/PreviewCardViewport.d.ts +2 -2
- package/preview-card/viewport/PreviewCardViewport.js +2 -2
- package/preview-card/viewport/PreviewCardViewportDataAttributes.d.ts +2 -2
- package/preview-card/viewport/PreviewCardViewportDataAttributes.js +2 -2
- package/progress/indicator/ProgressIndicator.js +6 -11
- package/progress/root/ProgressRoot.d.ts +1 -1
- package/radio/root/RadioRoot.js +7 -3
- package/radio-group/RadioGroup.js +4 -11
- package/radio-group/RadioGroupContext.d.ts +0 -1
- package/scroll-area/content/ScrollAreaContent.js +4 -4
- package/scroll-area/root/ScrollAreaRoot.js +1 -1
- package/scroll-area/scrollbar/ScrollAreaScrollbar.js +16 -20
- package/scroll-area/viewport/ScrollAreaViewport.js +6 -10
- package/select/arrow/SelectArrow.js +1 -1
- package/select/backdrop/SelectBackdrop.js +1 -1
- package/select/group/SelectGroup.js +1 -1
- package/select/group-label/SelectGroupLabel.js +2 -2
- package/select/icon/SelectIcon.js +1 -1
- package/select/item/SelectItem.js +46 -32
- package/select/item/SelectItemContext.d.ts +1 -1
- package/select/item-indicator/SelectItemIndicator.js +1 -2
- package/select/item-text/SelectItemText.js +9 -6
- package/select/list/SelectList.js +1 -1
- package/select/popup/SelectPopup.js +8 -3
- package/select/positioner/SelectPositioner.js +3 -0
- package/select/root/SelectRoot.js +45 -39
- package/select/root/SelectRootContext.d.ts +4 -5
- package/select/store.d.ts +3 -0
- package/select/store.js +1 -0
- package/select/trigger/SelectTrigger.d.ts +5 -0
- package/select/trigger/SelectTrigger.js +19 -33
- package/select/trigger/SelectTriggerDataAttributes.d.ts +5 -0
- package/select/trigger/SelectTriggerDataAttributes.js +5 -0
- package/slider/control/SliderControl.js +9 -11
- package/slider/root/SliderRoot.js +1 -4
- package/slider/thumb/SliderThumb.js +32 -30
- package/slider/value/SliderValue.js +7 -15
- package/switch/root/SwitchRoot.js +10 -10
- package/switch/thumb/SwitchThumb.js +1 -9
- package/tabs/indicator/TabsIndicator.js +14 -19
- package/tabs/list/TabsList.js +4 -10
- package/tabs/list/TabsListContext.d.ts +2 -1
- package/tabs/panel/TabsPanel.js +1 -1
- package/tabs/root/TabsRoot.d.ts +16 -1
- package/tabs/root/TabsRoot.js +71 -24
- package/tabs/root/TabsRootContext.d.ts +0 -2
- package/toast/provider/ToastProvider.js +1 -1
- package/toast/root/ToastRoot.d.ts +1 -1
- package/toast/root/ToastRoot.js +110 -133
- package/toast/root/ToastRootDataAttributes.d.ts +1 -1
- package/toast/root/ToastRootDataAttributes.js +1 -1
- package/toast/store.d.ts +9 -1
- package/toast/store.js +18 -12
- package/toast/useToastManager.d.ts +1 -1
- package/toast/viewport/ToastViewport.js +1 -1
- package/toggle/Toggle.js +5 -9
- package/toggle-group/ToggleGroup.d.ts +2 -2
- package/toggle-group/ToggleGroup.js +6 -13
- package/toolbar/link/ToolbarLink.d.ts +1 -1
- package/toolbar/link/ToolbarLink.js +1 -2
- package/tooltip/arrow/TooltipArrow.js +3 -3
- package/tooltip/popup/TooltipPopup.js +5 -4
- package/tooltip/root/TooltipRoot.js +32 -23
- package/tooltip/store/TooltipHandle.js +1 -1
- package/tooltip/store/TooltipStore.d.ts +90 -2
- package/tooltip/store/TooltipStore.js +17 -30
- package/tooltip/trigger/TooltipTrigger.js +152 -20
- package/tooltip/viewport/TooltipViewport.d.ts +2 -2
- package/tooltip/viewport/TooltipViewport.js +2 -2
- package/tooltip/viewport/TooltipViewportDataAttributes.d.ts +1 -1
- package/tooltip/viewport/TooltipViewportDataAttributes.js +1 -1
- package/unstable-use-media-query/index.js +1 -1
- package/utils/popups/index.d.ts +1 -0
- package/utils/popups/index.js +11 -0
- package/utils/popups/inlineRect.d.ts +15 -0
- package/utils/popups/inlineRect.js +198 -0
- package/utils/popups/popupStoreUtils.d.ts +28 -10
- package/utils/popups/popupStoreUtils.js +110 -20
- package/utils/popups/popupTriggerMap.js +2 -0
- package/utils/popups/store.d.ts +15 -2
- package/utils/popups/store.js +39 -2
- package/utils/popups/useTriggerFocusGuards.js +4 -5
- package/utils/useAnchorPositioning.d.ts +5 -0
- package/utils/useAnchorPositioning.js +12 -9
- package/utils/useOpenInteractionType.d.ts +4 -0
- package/utils/useOpenInteractionType.js +24 -17
- package/checkbox-group/index.parts.d.ts +0 -1
- package/checkbox-group/index.parts.js +0 -12
- package/esm/checkbox-group/index.parts.d.ts +0 -1
- package/esm/checkbox-group/index.parts.js +0 -1
- package/esm/floating-ui-react/hooks/useInteractions.d.ts +0 -20
- package/esm/floating-ui-react/hooks/useInteractions.js +0 -88
- package/esm/floating-ui-react/hooks/useRole.d.ts +0 -17
- package/esm/floating-ui-react/hooks/useRole.js +0 -113
- package/floating-ui-react/hooks/useInteractions.d.ts +0 -20
- package/floating-ui-react/hooks/useInteractions.js +0 -95
- package/floating-ui-react/hooks/useRole.d.ts +0 -17
- package/floating-ui-react/hooks/useRole.js +0 -120
- /package/{csp-provider → esm/internals/csp-context}/CSPContext.d.ts +0 -0
- /package/esm/{csp-provider → internals/csp-context}/CSPContext.js +0 -0
- /package/{esm/csp-provider → internals/csp-context}/CSPContext.d.ts +0 -0
- /package/{csp-provider → internals/csp-context}/CSPContext.js +0 -0
|
@@ -3,340 +3,380 @@
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { addEventListener } from '@base-ui/utils/addEventListener';
|
|
5
5
|
import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
|
|
6
|
-
import { useStableCallback } from '@base-ui/utils/useStableCallback';
|
|
7
6
|
import { useMergedRefs } from '@base-ui/utils/useMergedRefs';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { AnimationFrame } from '@base-ui/utils/useAnimationFrame';
|
|
8
|
+
import { useStableCallback } from '@base-ui/utils/useStableCallback';
|
|
9
|
+
import { useValueAsRef } from '@base-ui/utils/useValueAsRef';
|
|
10
10
|
import { warn } from '@base-ui/utils/warn';
|
|
11
|
+
import { ownerWindow } from '@base-ui/utils/owner';
|
|
11
12
|
import { createChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
|
|
12
13
|
import { REASONS } from "../../internals/reasons.js";
|
|
14
|
+
import { useOpenChangeComplete } from "../../internals/useOpenChangeComplete.js";
|
|
15
|
+
import { useAnimationsFinished } from "../../internals/useAnimationsFinished.js";
|
|
13
16
|
import { CollapsiblePanelDataAttributes } from "./CollapsiblePanelDataAttributes.js";
|
|
14
|
-
|
|
17
|
+
const EMPTY_DIMENSIONS = {
|
|
18
|
+
height: undefined,
|
|
19
|
+
width: undefined
|
|
20
|
+
};
|
|
15
21
|
export function useCollapsiblePanel(parameters) {
|
|
16
22
|
const {
|
|
17
|
-
abortControllerRef,
|
|
18
|
-
animationTypeRef,
|
|
19
23
|
externalRef,
|
|
20
|
-
height,
|
|
21
24
|
hiddenUntilFound,
|
|
22
|
-
keepMounted,
|
|
23
25
|
id: idParam,
|
|
26
|
+
keepMounted,
|
|
24
27
|
mounted,
|
|
25
28
|
onOpenChange,
|
|
26
29
|
open,
|
|
27
|
-
panelRef,
|
|
28
|
-
runOnceAnimationsFinish,
|
|
29
|
-
setDimensions,
|
|
30
30
|
setMounted,
|
|
31
31
|
setOpen,
|
|
32
|
-
|
|
33
|
-
transitionDimensionRef,
|
|
34
|
-
visible,
|
|
35
|
-
width
|
|
32
|
+
transitionStatus
|
|
36
33
|
} = parameters;
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
34
|
+
const panelRef = React.useRef(null);
|
|
35
|
+
const animationTypeRef = React.useRef(null);
|
|
36
|
+
const [dimensions, setDimensionsUnwrapped] = React.useState(EMPTY_DIMENSIONS);
|
|
37
|
+
const lastMeasuredDimensionsRef = React.useRef(EMPTY_DIMENSIONS);
|
|
38
|
+
// `beforematch` should reveal the matched content immediately, so the next
|
|
39
|
+
// open cycle skips author-defined motion once and then returns to normal.
|
|
40
|
+
const shouldSkipNextOpenRef = React.useRef(false);
|
|
41
|
+
// Keyframe mount animations on initially open panels cause a visible layout
|
|
42
|
+
// shift during the server-rendered first paint, so suppress that first open
|
|
43
|
+
// lifecycle until the panel has been closed once.
|
|
44
|
+
const shouldPreventMountAnimationRef = React.useRef(open);
|
|
45
|
+
// React.Activity tears down Effects while preserving state, so revealing an
|
|
46
|
+
// already-open panel would otherwise replay its CSS keyframe open animation.
|
|
47
|
+
const shouldPreventActivityResumeAnimationRef = React.useRef(false);
|
|
48
|
+
// Some open paths intentionally bypass motion, but the shared root transition
|
|
49
|
+
// status still advances asynchronously. Override the panel to idle so its data
|
|
50
|
+
// attributes and dimension cleanup reflect the immediate open state.
|
|
51
|
+
const [forcePanelIdle, setForcePanelIdle] = React.useState(false);
|
|
52
|
+
const pendingTemporaryStyleRestoreRef = React.useRef(null);
|
|
53
|
+
const mergedPanelRef = useMergedRefs(externalRef, panelRef);
|
|
54
|
+
const latestStateRef = useValueAsRef({
|
|
55
|
+
mounted,
|
|
56
|
+
open
|
|
57
|
+
});
|
|
58
|
+
// Only used to handle panel close
|
|
59
|
+
const runOnceCloseAnimationsFinish = useAnimationsFinished(panelRef, false, false);
|
|
60
|
+
const hidden = !open && !mounted;
|
|
61
|
+
const panelTransitionStatus = forcePanelIdle ? 'idle' : transitionStatus;
|
|
62
|
+
const shouldPreventOpenAnimation = open && (
|
|
63
|
+
// These 2 refs are safe to read in render, they are only written from committed
|
|
64
|
+
// layout/effect paths and gate one-shot motion suppression for the next open
|
|
65
|
+
// lifecycle. They intentionally expose the last committed motion snapshot.
|
|
66
|
+
shouldPreventMountAnimationRef.current || shouldPreventActivityResumeAnimationRef.current);
|
|
67
|
+
const renderedDimensions = !open && mounted &&
|
|
68
|
+
// These 2 refs are also safe to read in render, both hold the last committed
|
|
69
|
+
// animation mode and measurement. This fallback only restores a previously
|
|
70
|
+
// measured pixel size after the live dimensions state has been reset back to `auto`.
|
|
71
|
+
animationTypeRef.current === 'css-animation' && dimensions.height === undefined && dimensions.width === undefined ? lastMeasuredDimensionsRef.current : dimensions;
|
|
72
|
+
const shouldPersistHiddenTransitionStyles = hiddenUntilFound && hidden && animationTypeRef.current !== 'css-animation';
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* interrupted and re-opens, this won't run as the panel was not unmounted.
|
|
61
|
-
*/
|
|
62
|
-
const handlePanelRef = useStableCallback(element => {
|
|
63
|
-
if (!element) {
|
|
64
|
-
return undefined;
|
|
74
|
+
// Most measured dimensions are reused later when CSS keyframe closes need a
|
|
75
|
+
// pixel size after the rendered dimensions have been reset back to `auto`.
|
|
76
|
+
// Passing `false` is only for clearing the current dimensions state.
|
|
77
|
+
const setDimensions = useStableCallback((nextDimensions, shouldCacheMeasurement = true) => {
|
|
78
|
+
if (shouldCacheMeasurement) {
|
|
79
|
+
lastMeasuredDimensionsRef.current = nextDimensions;
|
|
65
80
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
} else if (panelStyles.animationName === 'none' && panelStyles.transitionDuration !== '0s') {
|
|
81
|
-
animationTypeRef.current = 'css-transition';
|
|
82
|
-
} else if (panelStyles.animationName !== 'none' && panelStyles.transitionDuration === '0s') {
|
|
83
|
-
animationTypeRef.current = 'css-animation';
|
|
84
|
-
} else {
|
|
85
|
-
animationTypeRef.current = 'none';
|
|
86
|
-
}
|
|
81
|
+
setDimensionsUnwrapped(nextDimensions);
|
|
82
|
+
});
|
|
83
|
+
const restorePendingTemporaryStyle = useStableCallback(() => {
|
|
84
|
+
pendingTemporaryStyleRestoreRef.current?.();
|
|
85
|
+
pendingTemporaryStyleRestoreRef.current = null;
|
|
86
|
+
});
|
|
87
|
+
const setPendingTemporaryStyleRestore = useStableCallback(restore => {
|
|
88
|
+
restorePendingTemporaryStyle();
|
|
89
|
+
pendingTemporaryStyleRestoreRef.current = () => {
|
|
90
|
+
pendingTemporaryStyleRestoreRef.current = null;
|
|
91
|
+
restore();
|
|
92
|
+
};
|
|
93
|
+
});
|
|
87
94
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
transitionDimensionRef.current = 'width';
|
|
95
|
-
} else {
|
|
96
|
-
transitionDimensionRef.current = 'height';
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (animationTypeRef.current !== 'css-transition') {
|
|
100
|
-
return undefined;
|
|
95
|
+
// React.Activity unmounts Effects while preserving component state. If that
|
|
96
|
+
// teardown happens while an already-open keyframe panel is visible, remember
|
|
97
|
+
// to suppress the replayed open animation on the next committed reveal.
|
|
98
|
+
const markActivityResumeAnimationSuppressed = useStableCallback(() => {
|
|
99
|
+
if (open && mounted && animationTypeRef.current === 'css-animation') {
|
|
100
|
+
shouldPreventActivityResumeAnimationRef.current = true;
|
|
101
101
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
102
|
+
});
|
|
103
|
+
useIsoLayoutEffect(() => {
|
|
104
|
+
// `forcePanelIdle` is only a temporary override for open paths that skip
|
|
105
|
+
// motion. Keep it active while the shared root still reports `starting`,
|
|
106
|
+
// then drop it once the root transition state catches up.
|
|
107
|
+
if (!forcePanelIdle || transitionStatus === 'starting') {
|
|
108
|
+
return;
|
|
110
109
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
shouldCancelInitialOpenTransitionRef.current = false;
|
|
115
|
-
nextFrame = AnimationFrame.request(() => {
|
|
116
|
-
/**
|
|
117
|
-
* This is slightly faster than another RAF and is the earliest
|
|
118
|
-
* opportunity to remove the temporary `transition-duration: 0s` that
|
|
119
|
-
* was applied to cancel opening transitions of initially open panels.
|
|
120
|
-
* https://nolanlawson.com/2018/09/25/accurately-measuring-layout-on-the-web/
|
|
121
|
-
*/
|
|
122
|
-
setTimeout(() => {
|
|
123
|
-
element.style.removeProperty('transition-duration');
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
});
|
|
110
|
+
setForcePanelIdle(false);
|
|
111
|
+
}, [forcePanelIdle, transitionStatus]);
|
|
112
|
+
React.useEffect(() => {
|
|
127
113
|
return () => {
|
|
128
|
-
|
|
129
|
-
|
|
114
|
+
markActivityResumeAnimationSuppressed();
|
|
115
|
+
restorePendingTemporaryStyle();
|
|
130
116
|
};
|
|
131
|
-
});
|
|
132
|
-
const mergedPanelRef = useMergedRefs(externalRef, panelRef, handlePanelRef);
|
|
117
|
+
}, [markActivityResumeAnimationSuppressed, restorePendingTemporaryStyle]);
|
|
133
118
|
useIsoLayoutEffect(() => {
|
|
134
|
-
if (animationTypeRef.current !== 'css-transition') {
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
119
|
const panel = panelRef.current;
|
|
138
120
|
if (!panel) {
|
|
139
121
|
return undefined;
|
|
140
122
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
123
|
+
|
|
124
|
+
// `beforematch` can temporarily force a `0s` motion duration so the matched
|
|
125
|
+
// content reveals immediately. Restore the authored duration before detecting
|
|
126
|
+
// the next close animation type, otherwise that first close is misread as
|
|
127
|
+
// "no motion" and the close transition or keyframe gets skipped.
|
|
128
|
+
if (!open && pendingTemporaryStyleRestoreRef.current) {
|
|
129
|
+
restorePendingTemporaryStyle();
|
|
145
130
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
'justify-content': panel.style.justifyContent,
|
|
149
|
-
'align-items': panel.style.alignItems,
|
|
150
|
-
'align-content': panel.style.alignContent,
|
|
151
|
-
'justify-items': panel.style.justifyItems
|
|
152
|
-
};
|
|
131
|
+
const animationType = getAnimationType(panel, shouldPreventOpenAnimation);
|
|
132
|
+
animationTypeRef.current = animationType;
|
|
153
133
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
134
|
+
// Initially open keyframe panels skip their first paint animation to avoid
|
|
135
|
+
// layout shift, but we still need to cache the expanded size so the first
|
|
136
|
+
// close animation can start from pixels instead of `auto`.
|
|
137
|
+
if (open && transitionStatus === 'idle' && shouldPreventMountAnimationRef.current && animationType === 'css-animation') {
|
|
138
|
+
lastMeasuredDimensionsRef.current = getDimensions(panel);
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
158
141
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
panel
|
|
168
|
-
|
|
169
|
-
setDimensions({
|
|
170
|
-
height: panel.scrollHeight,
|
|
171
|
-
width: panel.scrollWidth
|
|
172
|
-
});
|
|
173
|
-
resizeFrame = AnimationFrame.request(() => {
|
|
174
|
-
Object.entries(originalLayoutStyles).forEach(([key, value]) => {
|
|
175
|
-
if (value === '') {
|
|
176
|
-
panel.style.removeProperty(key);
|
|
177
|
-
} else {
|
|
178
|
-
panel.style.setProperty(key, value);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
} else {
|
|
183
|
-
if (panel.scrollHeight === 0 && panel.scrollWidth === 0) {
|
|
142
|
+
// Handle the opening pass: measure the expanded size and, when necessary,
|
|
143
|
+
// neutralize author-defined motion so the panel can open immediately.
|
|
144
|
+
if (open && transitionStatus === 'starting') {
|
|
145
|
+
// `beforematch` opens should reveal the panel immediately so find-in-page
|
|
146
|
+
// does not wait for the author-defined transition or animation to finish.
|
|
147
|
+
const skipNextOpen = shouldSkipNextOpenRef.current;
|
|
148
|
+
shouldSkipNextOpenRef.current = false;
|
|
149
|
+
if (animationType === 'none') {
|
|
150
|
+
setDimensions(getDimensions(panel));
|
|
151
|
+
setForcePanelIdle(true);
|
|
184
152
|
return undefined;
|
|
185
153
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
});
|
|
192
|
-
const abortController = new AbortController();
|
|
193
|
-
abortControllerRef.current = abortController;
|
|
194
|
-
const signal = abortController.signal;
|
|
195
|
-
let attributeObserver = null;
|
|
196
|
-
const endingStyleAttribute = CollapsiblePanelDataAttributes.endingStyle;
|
|
197
|
-
|
|
198
|
-
// Wait for `[data-ending-style]` to be applied.
|
|
199
|
-
attributeObserver = new MutationObserver(mutationList => {
|
|
200
|
-
const hasEndingStyle = mutationList.some(mutation => mutation.type === 'attributes' && mutation.attributeName === endingStyleAttribute);
|
|
201
|
-
if (hasEndingStyle) {
|
|
202
|
-
attributeObserver?.disconnect();
|
|
203
|
-
attributeObserver = null;
|
|
204
|
-
runOnceAnimationsFinish(() => {
|
|
205
|
-
setDimensions({
|
|
206
|
-
height: 0,
|
|
207
|
-
width: 0
|
|
208
|
-
});
|
|
209
|
-
panel.style.removeProperty('content-visibility');
|
|
210
|
-
setMounted(false);
|
|
211
|
-
if (abortControllerRef.current === abortController) {
|
|
212
|
-
abortControllerRef.current = null;
|
|
213
|
-
}
|
|
214
|
-
}, signal);
|
|
154
|
+
if (animationType === 'css-transition') {
|
|
155
|
+
const restoreLayoutStyles = resetLayoutStyles(panel);
|
|
156
|
+
setDimensions(getDimensions(panel));
|
|
157
|
+
if (!skipNextOpen) {
|
|
158
|
+
return restoreLayoutStyles;
|
|
215
159
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
160
|
+
const restoreTransitionDuration = setTemporaryStyle(panel, 'transition-duration', '0s');
|
|
161
|
+
setPendingTemporaryStyleRestore(restoreTransitionDuration);
|
|
162
|
+
setForcePanelIdle(true);
|
|
163
|
+
return restoreLayoutStyles;
|
|
164
|
+
}
|
|
165
|
+
if (animationType === 'css-animation') {
|
|
166
|
+
setDimensions(getDimensions(panel));
|
|
167
|
+
if (!skipNextOpen) {
|
|
168
|
+
const restoreAnimationName = setTemporaryStyle(panel, 'animation-name', 'none');
|
|
169
|
+
restoreAnimationName();
|
|
170
|
+
return undefined;
|
|
227
171
|
}
|
|
228
|
-
|
|
172
|
+
const restoreAnimationName = setTemporaryStyle(panel, 'animation-name', 'none');
|
|
173
|
+
const restoreAnimationDuration = setTemporaryStyle(panel, 'animation-duration', '0s');
|
|
174
|
+
restoreAnimationName();
|
|
175
|
+
setPendingTemporaryStyleRestore(restoreAnimationDuration);
|
|
176
|
+
setForcePanelIdle(true);
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
229
179
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
180
|
+
|
|
181
|
+
// Capture the current size as soon as close is requested, before the
|
|
182
|
+
// deferred ending phase applies closed styles. This keeps close transitions
|
|
183
|
+
// starting from a measured pixel value, including interrupted opens.
|
|
184
|
+
if (!open && mounted && (transitionStatus === 'idle' || transitionStatus === 'starting')) {
|
|
185
|
+
if (animationType === 'none') {
|
|
186
|
+
setDimensions(EMPTY_DIMENSIONS, false);
|
|
187
|
+
setMounted(false);
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
if (animationType === 'css-animation') {
|
|
191
|
+
shouldPreventMountAnimationRef.current = false;
|
|
192
|
+
shouldPreventActivityResumeAnimationRef.current = false;
|
|
193
|
+
}
|
|
194
|
+
setDimensions(getDimensions(panel));
|
|
195
|
+
return undefined;
|
|
237
196
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return;
|
|
197
|
+
if (transitionStatus !== 'ending') {
|
|
198
|
+
return undefined;
|
|
241
199
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!
|
|
249
|
-
|
|
200
|
+
if (animationType === 'none') {
|
|
201
|
+
setMounted(false);
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
const nextDimensions = getDimensions(panel);
|
|
205
|
+
const hasMeasuredSize = (nextDimensions.height ?? 0) > 0 || (nextDimensions.width ?? 0) > 0;
|
|
206
|
+
if (!hasMeasuredSize) {
|
|
207
|
+
setMounted(false);
|
|
208
|
+
return undefined;
|
|
250
209
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
210
|
+
setDimensions(nextDimensions);
|
|
211
|
+
if (animationType === 'css-animation') {
|
|
212
|
+
const restoreAnimationName = setTemporaryStyle(panel, 'animation-name', 'none');
|
|
213
|
+
restoreAnimationName();
|
|
214
|
+
}
|
|
215
|
+
return undefined;
|
|
216
|
+
}, [mounted, open, restorePendingTemporaryStyle, setDimensions, setMounted, setPendingTemporaryStyleRestore, shouldPreventOpenAnimation, transitionStatus]);
|
|
217
|
+
useOpenChangeComplete({
|
|
218
|
+
enabled: open && mounted && panelTransitionStatus === 'idle',
|
|
219
|
+
open: true,
|
|
220
|
+
ref: panelRef,
|
|
221
|
+
onComplete() {
|
|
222
|
+
if (!open) {
|
|
223
|
+
return;
|
|
255
224
|
}
|
|
256
|
-
|
|
257
|
-
setVisible(true);
|
|
258
|
-
} else {
|
|
259
|
-
abortControllerRef.current = new AbortController();
|
|
260
|
-
runOnceAnimationsFinish(() => {
|
|
261
|
-
setMounted(false);
|
|
262
|
-
setVisible(false);
|
|
263
|
-
abortControllerRef.current = null;
|
|
264
|
-
}, abortControllerRef.current.signal);
|
|
225
|
+
setDimensions(EMPTY_DIMENSIONS, false);
|
|
265
226
|
}
|
|
266
|
-
}, [abortControllerRef, animationTypeRef, open, panelRef, runOnceAnimationsFinish, setDimensions, setMounted, setVisible, visible]);
|
|
267
|
-
useOnMount(() => {
|
|
268
|
-
const frame = AnimationFrame.request(() => {
|
|
269
|
-
shouldCancelInitialOpenAnimationRef.current = false;
|
|
270
|
-
});
|
|
271
|
-
return () => AnimationFrame.cancel(frame);
|
|
272
227
|
});
|
|
273
|
-
|
|
274
|
-
|
|
228
|
+
|
|
229
|
+
// Closing panels need extra sequencing beyond `useOpenChangeComplete`.
|
|
230
|
+
// This passive effect runs after the `ending` render has committed, so
|
|
231
|
+
// `[data-ending-style]` is already present. Chrome can still register the
|
|
232
|
+
// exit transition one frame later when an Accordion closes one item while
|
|
233
|
+
// opening another, so wait one frame before watching animations.
|
|
234
|
+
// See https://github.com/mui/base-ui/issues/3099
|
|
235
|
+
React.useEffect(() => {
|
|
236
|
+
if (open || !mounted || panelTransitionStatus !== 'ending') {
|
|
275
237
|
return undefined;
|
|
276
238
|
}
|
|
277
239
|
const panel = panelRef.current;
|
|
278
240
|
if (!panel) {
|
|
279
241
|
return undefined;
|
|
280
242
|
}
|
|
281
|
-
|
|
282
|
-
let
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
frame = AnimationFrame.request(() => {
|
|
290
|
-
isBeforeMatchRef.current = false;
|
|
291
|
-
nextFrame = AnimationFrame.request(() => {
|
|
292
|
-
setTimeout(() => {
|
|
293
|
-
panel.style.removeProperty('transition-duration');
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
});
|
|
243
|
+
const abortController = new AbortController();
|
|
244
|
+
let endingStyleFrame = -1;
|
|
245
|
+
function handleComplete() {
|
|
246
|
+
if (latestStateRef.current.open) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
setMounted(false);
|
|
250
|
+
setDimensions(EMPTY_DIMENSIONS, false);
|
|
297
251
|
}
|
|
252
|
+
endingStyleFrame = AnimationFrame.request(() => {
|
|
253
|
+
if (!abortController.signal.aborted) {
|
|
254
|
+
runOnceCloseAnimationsFinish(handleComplete, abortController.signal);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
298
257
|
return () => {
|
|
299
|
-
AnimationFrame.cancel(
|
|
300
|
-
|
|
258
|
+
AnimationFrame.cancel(endingStyleFrame);
|
|
259
|
+
abortController.abort();
|
|
301
260
|
};
|
|
302
|
-
}, [
|
|
261
|
+
}, [latestStateRef, mounted, open, panelTransitionStatus, runOnceCloseAnimationsFinish, setDimensions, setMounted]);
|
|
303
262
|
useIsoLayoutEffect(() => {
|
|
304
263
|
const panel = panelRef.current;
|
|
305
|
-
if (panel
|
|
306
|
-
|
|
307
|
-
* React only supports a boolean for the `hidden` attribute and forces
|
|
308
|
-
* legit string values to booleans so we have to force it back in the DOM
|
|
309
|
-
* when necessary: https://github.com/facebook/react/issues/24740
|
|
310
|
-
*/
|
|
311
|
-
panel.setAttribute('hidden', 'until-found');
|
|
312
|
-
/**
|
|
313
|
-
* Set data-starting-style here to persist the closed styles, this is to
|
|
314
|
-
* prevent transitions from starting when the `hidden` attribute changes
|
|
315
|
-
* to `'until-found'` as they could have different `display` properties:
|
|
316
|
-
* https://github.com/tailwindlabs/tailwindcss/pull/14625
|
|
317
|
-
*/
|
|
318
|
-
if (animationTypeRef.current === 'css-transition') {
|
|
319
|
-
panel.setAttribute(CollapsiblePanelDataAttributes.startingStyle, '');
|
|
320
|
-
}
|
|
264
|
+
if (!panel || !hiddenUntilFound || !hidden) {
|
|
265
|
+
return;
|
|
321
266
|
}
|
|
322
|
-
|
|
267
|
+
|
|
268
|
+
// React only supports a boolean for the `hidden` attribute and forces
|
|
269
|
+
// legit string values to booleans so we have to force it back in the DOM
|
|
270
|
+
// when necessary: https://github.com/facebook/react/issues/24740
|
|
271
|
+
panel.setAttribute('hidden', 'until-found');
|
|
272
|
+
}, [hidden, hiddenUntilFound]);
|
|
323
273
|
React.useEffect(function registerBeforeMatchListener() {
|
|
324
274
|
const panel = panelRef.current;
|
|
325
275
|
if (!panel) {
|
|
326
276
|
return undefined;
|
|
327
277
|
}
|
|
328
278
|
function handleBeforeMatch(event) {
|
|
329
|
-
|
|
279
|
+
shouldSkipNextOpenRef.current = true;
|
|
330
280
|
setOpen(true);
|
|
331
281
|
onOpenChange(true, createChangeEventDetails(REASONS.none, event));
|
|
332
282
|
}
|
|
333
283
|
return addEventListener(panel, 'beforematch', handleBeforeMatch);
|
|
334
|
-
}, [onOpenChange,
|
|
335
|
-
|
|
284
|
+
}, [onOpenChange, setOpen]);
|
|
285
|
+
const shouldRender = keepMounted || hiddenUntilFound || mounted || open;
|
|
286
|
+
return {
|
|
287
|
+
height: renderedDimensions.height,
|
|
336
288
|
props: {
|
|
289
|
+
...(shouldPersistHiddenTransitionStyles ? {
|
|
290
|
+
[CollapsiblePanelDataAttributes.startingStyle]: ''
|
|
291
|
+
} : undefined),
|
|
337
292
|
hidden,
|
|
338
|
-
id: idParam
|
|
339
|
-
|
|
293
|
+
id: idParam
|
|
294
|
+
},
|
|
295
|
+
ref: mergedPanelRef,
|
|
296
|
+
shouldPreventOpenAnimation,
|
|
297
|
+
shouldRender,
|
|
298
|
+
transitionStatus: panelTransitionStatus,
|
|
299
|
+
width: renderedDimensions.width
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function getDimensions(element) {
|
|
303
|
+
return {
|
|
304
|
+
height: element.scrollHeight,
|
|
305
|
+
width: element.scrollWidth
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function getAnimationType(element, hasSuppressedMountAnimation = false) {
|
|
309
|
+
const panelStyles = ownerWindow(element).getComputedStyle(element);
|
|
310
|
+
const hasAnimation = (panelStyles.animationName.split(',').map(name => name.trim()).some(name => name !== '' && name !== 'none') || hasSuppressedMountAnimation) && hasNonZeroDuration(panelStyles.animationDuration);
|
|
311
|
+
const hasTransition = hasNonZeroDuration(panelStyles.transitionDuration);
|
|
312
|
+
if (hasAnimation && hasTransition) {
|
|
313
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
314
|
+
warn('CSS transitions and CSS animations both detected on Collapsible or Accordion panel.', 'Only one of either animation type should be used.');
|
|
315
|
+
}
|
|
316
|
+
return 'css-transition';
|
|
317
|
+
}
|
|
318
|
+
if (hasTransition) {
|
|
319
|
+
return 'css-transition';
|
|
320
|
+
}
|
|
321
|
+
if (hasAnimation) {
|
|
322
|
+
return 'css-animation';
|
|
323
|
+
}
|
|
324
|
+
return 'none';
|
|
325
|
+
}
|
|
326
|
+
function hasNonZeroDuration(value) {
|
|
327
|
+
return value.split(',').map(part => part.trim()).some(part => part !== '' && Number.parseFloat(part) > 0);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Temporarily overrides an inline style property and returns a cleanup that
|
|
332
|
+
* restores the previous inline value and priority.
|
|
333
|
+
* @param element - The element whose inline style should be updated.
|
|
334
|
+
* @param property - The CSS property name to override.
|
|
335
|
+
* @param value - The temporary value to assign.
|
|
336
|
+
* @returns A cleanup function that restores the original inline style state.
|
|
337
|
+
*/
|
|
338
|
+
function setTemporaryStyle(element, property, value) {
|
|
339
|
+
const previousValue = element.style.getPropertyValue(property);
|
|
340
|
+
const previousPriority = element.style.getPropertyPriority(property);
|
|
341
|
+
element.style.setProperty(property, value);
|
|
342
|
+
return () => {
|
|
343
|
+
if (previousValue === '') {
|
|
344
|
+
element.style.removeProperty(property);
|
|
345
|
+
return;
|
|
340
346
|
}
|
|
341
|
-
|
|
347
|
+
element.style.setProperty(property, previousValue, previousPriority);
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Temporarily resets inline alignment styles that can distort scroll-based
|
|
353
|
+
* size measurements, then restores them on the next animation frame.
|
|
354
|
+
* @param element - The panel element being measured.
|
|
355
|
+
* @returns A cleanup function that cancels the scheduled restore and reapplies
|
|
356
|
+
* the original inline layout styles immediately.
|
|
357
|
+
*/
|
|
358
|
+
function resetLayoutStyles(element) {
|
|
359
|
+
const originalLayoutStyles = {
|
|
360
|
+
'justify-content': element.style.justifyContent,
|
|
361
|
+
'align-items': element.style.alignItems,
|
|
362
|
+
'align-content': element.style.alignContent,
|
|
363
|
+
'justify-items': element.style.justifyItems
|
|
364
|
+
};
|
|
365
|
+
Object.keys(originalLayoutStyles).forEach(key => {
|
|
366
|
+
element.style.setProperty(key, 'initial', 'important');
|
|
367
|
+
});
|
|
368
|
+
function restoreLayoutStyles() {
|
|
369
|
+
Object.entries(originalLayoutStyles).forEach(([key, value]) => {
|
|
370
|
+
if (value === '') {
|
|
371
|
+
element.style.removeProperty(key);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
element.style.setProperty(key, value);
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
const frame = AnimationFrame.request(restoreLayoutStyles);
|
|
378
|
+
return () => {
|
|
379
|
+
AnimationFrame.cancel(frame);
|
|
380
|
+
restoreLayoutStyles();
|
|
381
|
+
};
|
|
342
382
|
}
|