@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.
Files changed (579) hide show
  1. package/CHANGELOG.md +125 -8
  2. package/README.md +1 -1
  3. package/accordion/item/AccordionItem.d.ts +4 -0
  4. package/accordion/item/AccordionItem.js +5 -4
  5. package/accordion/panel/AccordionPanel.js +29 -51
  6. package/accordion/root/AccordionRoot.js +5 -6
  7. package/accordion/trigger/AccordionTrigger.js +3 -4
  8. package/alert-dialog/handle.d.ts +14 -1
  9. package/alert-dialog/handle.js +22 -5
  10. package/alert-dialog/index.d.ts +1 -1
  11. package/alert-dialog/index.parts.d.ts +2 -3
  12. package/alert-dialog/index.parts.js +4 -5
  13. package/alert-dialog/root/AlertDialogRoot.d.ts +7 -7
  14. package/alert-dialog/root/AlertDialogRoot.js +2 -56
  15. package/alert-dialog/trigger/AlertDialogTrigger.d.ts +25 -0
  16. package/alert-dialog/trigger/AlertDialogTrigger.js +15 -0
  17. package/alert-dialog/trigger/AlertDialogTriggerDataAttributes.d.ts +10 -0
  18. package/alert-dialog/trigger/AlertDialogTriggerDataAttributes.js +18 -0
  19. package/autocomplete/root/AutocompleteRoot.js +9 -10
  20. package/avatar/image/AvatarImage.js +4 -4
  21. package/checkbox/indicator/CheckboxIndicator.js +2 -2
  22. package/checkbox/root/CheckboxRoot.js +49 -11
  23. package/checkbox-group/CheckboxGroup.js +1 -5
  24. package/collapsible/panel/CollapsiblePanel.js +29 -51
  25. package/collapsible/panel/useCollapsiblePanel.d.ts +9 -23
  26. package/collapsible/panel/useCollapsiblePanel.js +308 -268
  27. package/collapsible/root/CollapsibleRoot.d.ts +1 -1
  28. package/collapsible/root/CollapsibleRootContext.d.ts +0 -2
  29. package/collapsible/root/useCollapsibleRoot.d.ts +0 -27
  30. package/collapsible/root/useCollapsibleRoot.js +2 -64
  31. package/collapsible/trigger/CollapsibleTrigger.js +5 -6
  32. package/combobox/arrow/ComboboxArrow.js +1 -1
  33. package/combobox/backdrop/ComboboxBackdrop.js +1 -1
  34. package/combobox/chip/ComboboxChip.js +7 -2
  35. package/combobox/clear/ComboboxClear.d.ts +4 -0
  36. package/combobox/clear/ComboboxClear.js +1 -0
  37. package/combobox/clear/ComboboxClearDataAttributes.d.ts +4 -0
  38. package/combobox/clear/ComboboxClearDataAttributes.js +4 -0
  39. package/combobox/icon/ComboboxIcon.js +1 -1
  40. package/combobox/input/ComboboxInput.js +15 -6
  41. package/combobox/item/ComboboxItem.js +8 -14
  42. package/combobox/item-indicator/ComboboxItemIndicator.js +1 -2
  43. package/combobox/root/AriaCombobox.js +61 -28
  44. package/combobox/store.d.ts +4 -8
  45. package/combobox/store.js +2 -1
  46. package/combobox/utils/ComboboxInternalDismissButton.js +2 -3
  47. package/csp-provider/CSPProvider.js +1 -1
  48. package/dialog/close/DialogClose.js +6 -6
  49. package/dialog/popup/DialogPopup.js +9 -4
  50. package/dialog/root/DialogRoot.d.ts +1 -2
  51. package/dialog/root/DialogRoot.js +3 -73
  52. package/dialog/root/DialogRootContext.d.ts +1 -0
  53. package/dialog/root/DialogRootContext.js +3 -1
  54. package/dialog/root/useDialogRoot.d.ts +12 -4
  55. package/dialog/root/useDialogRoot.js +27 -25
  56. package/dialog/root/useRenderDialogRoot.d.ts +4 -0
  57. package/dialog/root/useRenderDialogRoot.js +96 -0
  58. package/dialog/store/DialogHandle.d.ts +1 -1
  59. package/dialog/store/DialogHandle.js +2 -2
  60. package/dialog/store/DialogStore.d.ts +88 -1
  61. package/dialog/store/DialogStore.js +12 -17
  62. package/dialog/trigger/DialogTrigger.d.ts +1 -1
  63. package/dialog/trigger/DialogTrigger.js +11 -4
  64. package/dialog/viewport/DialogViewport.js +4 -3
  65. package/drawer/popup/DrawerPopup.js +13 -9
  66. package/drawer/root/DrawerRoot.js +11 -11
  67. package/drawer/root/DrawerRootContext.d.ts +1 -1
  68. package/drawer/swipe-area/DrawerSwipeArea.js +6 -5
  69. package/drawer/viewport/DrawerViewport.js +13 -14
  70. package/esm/accordion/item/AccordionItem.d.ts +4 -0
  71. package/esm/accordion/item/AccordionItem.js +5 -4
  72. package/esm/accordion/panel/AccordionPanel.js +29 -51
  73. package/esm/accordion/root/AccordionRoot.js +5 -6
  74. package/esm/accordion/trigger/AccordionTrigger.js +4 -5
  75. package/esm/alert-dialog/handle.d.ts +14 -1
  76. package/esm/alert-dialog/handle.js +20 -5
  77. package/esm/alert-dialog/index.d.ts +1 -1
  78. package/esm/alert-dialog/index.parts.d.ts +2 -3
  79. package/esm/alert-dialog/index.parts.js +2 -3
  80. package/esm/alert-dialog/root/AlertDialogRoot.d.ts +7 -7
  81. package/esm/alert-dialog/root/AlertDialogRoot.js +2 -55
  82. package/esm/alert-dialog/trigger/AlertDialogTrigger.d.ts +25 -0
  83. package/esm/alert-dialog/trigger/AlertDialogTrigger.js +10 -0
  84. package/esm/alert-dialog/trigger/AlertDialogTriggerDataAttributes.d.ts +10 -0
  85. package/esm/alert-dialog/trigger/AlertDialogTriggerDataAttributes.js +12 -0
  86. package/esm/autocomplete/root/AutocompleteRoot.js +9 -10
  87. package/esm/avatar/image/AvatarImage.js +4 -4
  88. package/esm/checkbox/indicator/CheckboxIndicator.js +2 -2
  89. package/esm/checkbox/root/CheckboxRoot.js +49 -11
  90. package/esm/checkbox-group/CheckboxGroup.js +1 -5
  91. package/esm/collapsible/panel/CollapsiblePanel.js +29 -51
  92. package/esm/collapsible/panel/useCollapsiblePanel.d.ts +9 -23
  93. package/esm/collapsible/panel/useCollapsiblePanel.js +309 -269
  94. package/esm/collapsible/root/CollapsibleRoot.d.ts +1 -1
  95. package/esm/collapsible/root/CollapsibleRootContext.d.ts +0 -2
  96. package/esm/collapsible/root/useCollapsibleRoot.d.ts +0 -27
  97. package/esm/collapsible/root/useCollapsibleRoot.js +2 -64
  98. package/esm/collapsible/trigger/CollapsibleTrigger.js +5 -6
  99. package/esm/combobox/arrow/ComboboxArrow.js +1 -1
  100. package/esm/combobox/backdrop/ComboboxBackdrop.js +1 -1
  101. package/esm/combobox/chip/ComboboxChip.js +7 -2
  102. package/esm/combobox/clear/ComboboxClear.d.ts +4 -0
  103. package/esm/combobox/clear/ComboboxClear.js +1 -0
  104. package/esm/combobox/clear/ComboboxClearDataAttributes.d.ts +4 -0
  105. package/esm/combobox/clear/ComboboxClearDataAttributes.js +4 -0
  106. package/esm/combobox/icon/ComboboxIcon.js +1 -1
  107. package/esm/combobox/input/ComboboxInput.js +16 -7
  108. package/esm/combobox/item/ComboboxItem.js +8 -14
  109. package/esm/combobox/item-indicator/ComboboxItemIndicator.js +1 -2
  110. package/esm/combobox/root/AriaCombobox.js +62 -29
  111. package/esm/combobox/store.d.ts +4 -8
  112. package/esm/combobox/store.js +2 -1
  113. package/esm/combobox/utils/ComboboxInternalDismissButton.js +2 -3
  114. package/esm/csp-provider/CSPProvider.js +1 -1
  115. package/esm/dialog/close/DialogClose.js +6 -6
  116. package/esm/dialog/popup/DialogPopup.js +9 -4
  117. package/esm/dialog/root/DialogRoot.d.ts +1 -2
  118. package/esm/dialog/root/DialogRoot.js +4 -72
  119. package/esm/dialog/root/DialogRootContext.d.ts +1 -0
  120. package/esm/dialog/root/DialogRootContext.js +2 -0
  121. package/esm/dialog/root/useDialogRoot.d.ts +12 -4
  122. package/esm/dialog/root/useDialogRoot.js +28 -27
  123. package/esm/dialog/root/useRenderDialogRoot.d.ts +4 -0
  124. package/esm/dialog/root/useRenderDialogRoot.js +90 -0
  125. package/esm/dialog/store/DialogHandle.d.ts +1 -1
  126. package/esm/dialog/store/DialogHandle.js +2 -2
  127. package/esm/dialog/store/DialogStore.d.ts +88 -1
  128. package/esm/dialog/store/DialogStore.js +13 -18
  129. package/esm/dialog/trigger/DialogTrigger.d.ts +1 -1
  130. package/esm/dialog/trigger/DialogTrigger.js +12 -5
  131. package/esm/dialog/viewport/DialogViewport.js +4 -3
  132. package/esm/drawer/popup/DrawerPopup.js +14 -9
  133. package/esm/drawer/root/DrawerRoot.js +11 -11
  134. package/esm/drawer/root/DrawerRootContext.d.ts +1 -1
  135. package/esm/drawer/swipe-area/DrawerSwipeArea.js +6 -5
  136. package/esm/drawer/viewport/DrawerViewport.js +13 -14
  137. package/esm/field/control/FieldControl.js +2 -6
  138. package/esm/field/item/FieldItem.js +1 -4
  139. package/esm/field/root/FieldRoot.js +11 -3
  140. package/esm/field/root/useFieldValidation.d.ts +1 -0
  141. package/esm/field/root/useFieldValidation.js +23 -20
  142. package/esm/field/utils/getCombinedFieldValidityData.d.ts +1 -1
  143. package/esm/field/validity/FieldValidity.d.ts +1 -1
  144. package/esm/floating-ui-react/components/FloatingDelayGroup.js +3 -3
  145. package/esm/floating-ui-react/components/FloatingFocusManager.d.ts +1 -1
  146. package/esm/floating-ui-react/components/FloatingFocusManager.js +20 -8
  147. package/esm/floating-ui-react/components/FloatingPortal.js +3 -3
  148. package/esm/floating-ui-react/hooks/useClick.js +83 -74
  149. package/esm/floating-ui-react/hooks/useClientPoint.js +29 -20
  150. package/esm/floating-ui-react/hooks/useDismiss.d.ts +1 -1
  151. package/esm/floating-ui-react/hooks/useDismiss.js +82 -93
  152. package/esm/floating-ui-react/hooks/useFloating.js +37 -32
  153. package/esm/floating-ui-react/hooks/useFloatingRootContext.d.ts +1 -1
  154. package/esm/floating-ui-react/hooks/useFloatingRootContext.js +2 -2
  155. package/esm/floating-ui-react/hooks/useFocus.js +84 -81
  156. package/esm/floating-ui-react/hooks/useHover.js +72 -76
  157. package/esm/floating-ui-react/hooks/useHoverFloatingInteraction.js +49 -44
  158. package/esm/floating-ui-react/hooks/useHoverInteractionSharedState.js +1 -1
  159. package/esm/floating-ui-react/hooks/useHoverReferenceInteraction.d.ts +7 -2
  160. package/esm/floating-ui-react/hooks/useHoverReferenceInteraction.js +44 -39
  161. package/esm/floating-ui-react/hooks/useHoverShared.d.ts +2 -1
  162. package/esm/floating-ui-react/hooks/useHoverShared.js +4 -0
  163. package/esm/floating-ui-react/hooks/useListNavigation.d.ts +1 -3
  164. package/esm/floating-ui-react/hooks/useListNavigation.js +83 -74
  165. package/esm/floating-ui-react/hooks/useSyncedFloatingRootContext.d.ts +9 -6
  166. package/esm/floating-ui-react/hooks/useSyncedFloatingRootContext.js +25 -20
  167. package/esm/floating-ui-react/hooks/useTypeahead.d.ts +2 -2
  168. package/esm/floating-ui-react/hooks/useTypeahead.js +33 -52
  169. package/esm/floating-ui-react/index.d.ts +0 -2
  170. package/esm/floating-ui-react/index.js +0 -2
  171. package/esm/floating-ui-react/types.d.ts +2 -7
  172. package/esm/floating-ui-react/utils/composite.js +2 -0
  173. package/esm/floating-ui-react/utils/enqueueFocus.d.ts +1 -1
  174. package/esm/floating-ui-react/utils/enqueueFocus.js +10 -7
  175. package/esm/floating-ui-react/utils/getEmptyRootContext.js +1 -1
  176. package/esm/form/Form.js +2 -2
  177. package/esm/index.js +1 -1
  178. package/esm/internals/composite/composite.d.ts +0 -1
  179. package/esm/internals/composite/composite.js +1 -2
  180. package/esm/internals/composite/root/useCompositeRoot.js +2 -2
  181. package/esm/internals/createBaseUIEventDetails.d.ts +2 -0
  182. package/esm/internals/csp-context/index.d.ts +2 -0
  183. package/esm/internals/csp-context/index.js +1 -0
  184. package/esm/internals/field-register-control/index.d.ts +0 -1
  185. package/esm/internals/field-register-control/useFieldControlRegistration.d.ts +2 -1
  186. package/esm/internals/field-register-control/useFieldControlRegistration.js +11 -14
  187. package/esm/internals/field-register-control/useRegisterFieldControl.d.ts +1 -4
  188. package/esm/internals/field-register-control/useRegisterFieldControl.js +6 -11
  189. package/esm/internals/field-root-context/FieldRootContext.d.ts +1 -0
  190. package/esm/internals/field-root-context/FieldRootContext.js +3 -2
  191. package/esm/internals/form-context/FormContext.d.ts +5 -1
  192. package/esm/internals/reason-parts.d.ts +2 -0
  193. package/esm/internals/reason-parts.js +2 -0
  194. package/esm/internals/types.d.ts +1 -0
  195. package/esm/internals/use-button/useButton.js +4 -4
  196. package/esm/internals/usePressAndHold.js +2 -2
  197. package/esm/internals/useRenderElement.js +2 -0
  198. package/esm/menu/arrow/MenuArrow.js +1 -1
  199. package/esm/menu/backdrop/MenuBackdrop.js +1 -1
  200. package/esm/menu/checkbox-item/MenuCheckboxItem.js +5 -7
  201. package/esm/menu/group/MenuGroup.js +1 -4
  202. package/esm/menu/group/MenuGroupContext.d.ts +1 -3
  203. package/esm/menu/group/MenuGroupContext.js +1 -1
  204. package/esm/menu/group-label/MenuGroupLabel.js +4 -6
  205. package/esm/menu/link-item/MenuLinkItem.js +2 -2
  206. package/esm/menu/popup/MenuPopup.js +5 -5
  207. package/esm/menu/radio-group/MenuRadioGroup.js +11 -5
  208. package/esm/menu/radio-item/MenuRadioItem.js +5 -7
  209. package/esm/menu/root/MenuRoot.js +63 -68
  210. package/esm/menu/store/MenuHandle.js +1 -1
  211. package/esm/menu/store/MenuStore.d.ts +87 -0
  212. package/esm/menu/submenu-trigger/MenuSubmenuTrigger.js +8 -5
  213. package/esm/menu/trigger/MenuTrigger.js +13 -10
  214. package/esm/menu/viewport/MenuViewport.d.ts +2 -2
  215. package/esm/menu/viewport/MenuViewport.js +2 -2
  216. package/esm/navigation-menu/arrow/NavigationMenuArrow.js +1 -1
  217. package/esm/navigation-menu/backdrop/NavigationMenuBackdrop.js +1 -1
  218. package/esm/navigation-menu/content/NavigationMenuContent.js +8 -5
  219. package/esm/navigation-menu/icon/NavigationMenuIcon.js +1 -1
  220. package/esm/navigation-menu/item/NavigationMenuItem.js +2 -2
  221. package/esm/navigation-menu/list/NavigationMenuList.js +1 -1
  222. package/esm/navigation-menu/popup/NavigationMenuPopup.js +2 -2
  223. package/esm/navigation-menu/root/NavigationMenuRoot.js +1 -3
  224. package/esm/navigation-menu/trigger/NavigationMenuTrigger.js +24 -17
  225. package/esm/navigation-menu/utils/isOutsideMenuEvent.d.ts +0 -1
  226. package/esm/navigation-menu/utils/isOutsideMenuEvent.js +1 -5
  227. package/esm/navigation-menu/viewport/NavigationMenuViewport.js +2 -3
  228. package/esm/number-field/input/NumberFieldInput.js +3 -5
  229. package/esm/number-field/root/NumberFieldRoot.js +5 -2
  230. package/esm/number-field/scrub-area/NumberFieldScrubArea.js +7 -3
  231. package/esm/otp-field/input/OTPFieldInput.js +43 -29
  232. package/esm/otp-field/root/OTPFieldRoot.d.ts +17 -8
  233. package/esm/otp-field/root/OTPFieldRoot.js +33 -33
  234. package/esm/otp-field/root/OTPFieldRootContext.d.ts +1 -1
  235. package/esm/otp-field/utils/otp.d.ts +5 -4
  236. package/esm/otp-field/utils/otp.js +23 -12
  237. package/esm/popover/arrow/PopoverArrow.js +1 -1
  238. package/esm/popover/backdrop/PopoverBackdrop.js +1 -1
  239. package/esm/popover/close/PopoverClose.js +2 -2
  240. package/esm/popover/description/PopoverDescription.js +1 -7
  241. package/esm/popover/popup/PopoverPopup.d.ts +1 -1
  242. package/esm/popover/popup/PopoverPopup.js +16 -10
  243. package/esm/popover/popup/PopoverPopupDataAttributes.d.ts +1 -1
  244. package/esm/popover/popup/PopoverPopupDataAttributes.js +1 -1
  245. package/esm/popover/positioner/PopoverPositioner.js +5 -5
  246. package/esm/popover/root/PopoverRoot.d.ts +1 -1
  247. package/esm/popover/root/PopoverRoot.js +42 -47
  248. package/esm/popover/store/PopoverHandle.js +1 -1
  249. package/esm/popover/store/PopoverStore.d.ts +91 -4
  250. package/esm/popover/store/PopoverStore.js +17 -18
  251. package/esm/popover/title/PopoverTitle.js +1 -7
  252. package/esm/popover/trigger/PopoverTrigger.js +24 -17
  253. package/esm/popover/viewport/PopoverViewport.d.ts +3 -3
  254. package/esm/popover/viewport/PopoverViewport.js +2 -2
  255. package/esm/popover/viewport/PopoverViewportDataAttributes.d.ts +1 -1
  256. package/esm/popover/viewport/PopoverViewportDataAttributes.js +1 -1
  257. package/esm/preview-card/positioner/PreviewCardPositioner.js +11 -1
  258. package/esm/preview-card/root/PreviewCardRoot.d.ts +1 -1
  259. package/esm/preview-card/root/PreviewCardRoot.js +32 -22
  260. package/esm/preview-card/store/PreviewCardHandle.js +1 -1
  261. package/esm/preview-card/store/PreviewCardStore.d.ts +90 -2
  262. package/esm/preview-card/store/PreviewCardStore.js +19 -31
  263. package/esm/preview-card/trigger/PreviewCardTrigger.js +6 -3
  264. package/esm/preview-card/viewport/PreviewCardViewport.d.ts +2 -2
  265. package/esm/preview-card/viewport/PreviewCardViewport.js +2 -2
  266. package/esm/preview-card/viewport/PreviewCardViewportDataAttributes.d.ts +2 -2
  267. package/esm/preview-card/viewport/PreviewCardViewportDataAttributes.js +2 -2
  268. package/esm/progress/indicator/ProgressIndicator.js +6 -11
  269. package/esm/progress/root/ProgressRoot.d.ts +1 -1
  270. package/esm/radio/root/RadioRoot.js +7 -3
  271. package/esm/radio-group/RadioGroup.js +4 -11
  272. package/esm/radio-group/RadioGroupContext.d.ts +0 -1
  273. package/esm/scroll-area/content/ScrollAreaContent.js +4 -4
  274. package/esm/scroll-area/root/ScrollAreaRoot.js +1 -1
  275. package/esm/scroll-area/scrollbar/ScrollAreaScrollbar.js +16 -20
  276. package/esm/scroll-area/viewport/ScrollAreaViewport.js +6 -10
  277. package/esm/select/arrow/SelectArrow.js +1 -1
  278. package/esm/select/backdrop/SelectBackdrop.js +1 -1
  279. package/esm/select/group/SelectGroup.js +1 -1
  280. package/esm/select/group-label/SelectGroupLabel.js +2 -2
  281. package/esm/select/icon/SelectIcon.js +1 -1
  282. package/esm/select/item/SelectItem.js +46 -32
  283. package/esm/select/item/SelectItemContext.d.ts +1 -1
  284. package/esm/select/item-indicator/SelectItemIndicator.js +1 -2
  285. package/esm/select/item-text/SelectItemText.js +9 -6
  286. package/esm/select/list/SelectList.js +1 -1
  287. package/esm/select/popup/SelectPopup.js +8 -3
  288. package/esm/select/positioner/SelectPositioner.js +3 -0
  289. package/esm/select/root/SelectRoot.js +46 -40
  290. package/esm/select/root/SelectRootContext.d.ts +4 -5
  291. package/esm/select/store.d.ts +3 -0
  292. package/esm/select/store.js +1 -0
  293. package/esm/select/trigger/SelectTrigger.d.ts +5 -0
  294. package/esm/select/trigger/SelectTrigger.js +19 -33
  295. package/esm/select/trigger/SelectTriggerDataAttributes.d.ts +5 -0
  296. package/esm/select/trigger/SelectTriggerDataAttributes.js +5 -0
  297. package/esm/slider/control/SliderControl.js +10 -12
  298. package/esm/slider/root/SliderRoot.js +1 -4
  299. package/esm/slider/thumb/SliderThumb.js +32 -30
  300. package/esm/slider/value/SliderValue.js +7 -15
  301. package/esm/switch/root/SwitchRoot.js +10 -10
  302. package/esm/switch/thumb/SwitchThumb.js +1 -9
  303. package/esm/tabs/indicator/TabsIndicator.js +14 -19
  304. package/esm/tabs/list/TabsList.js +4 -10
  305. package/esm/tabs/list/TabsListContext.d.ts +2 -1
  306. package/esm/tabs/panel/TabsPanel.js +1 -1
  307. package/esm/tabs/root/TabsRoot.d.ts +16 -1
  308. package/esm/tabs/root/TabsRoot.js +73 -25
  309. package/esm/tabs/root/TabsRootContext.d.ts +0 -2
  310. package/esm/toast/provider/ToastProvider.js +1 -1
  311. package/esm/toast/root/ToastRoot.d.ts +1 -1
  312. package/esm/toast/root/ToastRoot.js +108 -131
  313. package/esm/toast/root/ToastRootDataAttributes.d.ts +1 -1
  314. package/esm/toast/root/ToastRootDataAttributes.js +1 -1
  315. package/esm/toast/store.d.ts +9 -1
  316. package/esm/toast/store.js +19 -13
  317. package/esm/toast/useToastManager.d.ts +1 -1
  318. package/esm/toast/viewport/ToastViewport.js +1 -1
  319. package/esm/toggle/Toggle.js +5 -9
  320. package/esm/toggle-group/ToggleGroup.d.ts +2 -2
  321. package/esm/toggle-group/ToggleGroup.js +6 -13
  322. package/esm/toolbar/link/ToolbarLink.d.ts +1 -1
  323. package/esm/toolbar/link/ToolbarLink.js +1 -2
  324. package/esm/tooltip/arrow/TooltipArrow.js +3 -3
  325. package/esm/tooltip/popup/TooltipPopup.js +5 -4
  326. package/esm/tooltip/root/TooltipRoot.js +35 -26
  327. package/esm/tooltip/store/TooltipHandle.js +1 -1
  328. package/esm/tooltip/store/TooltipStore.d.ts +90 -2
  329. package/esm/tooltip/store/TooltipStore.js +18 -31
  330. package/esm/tooltip/trigger/TooltipTrigger.js +151 -20
  331. package/esm/tooltip/viewport/TooltipViewport.d.ts +2 -2
  332. package/esm/tooltip/viewport/TooltipViewport.js +2 -2
  333. package/esm/tooltip/viewport/TooltipViewportDataAttributes.d.ts +1 -1
  334. package/esm/tooltip/viewport/TooltipViewportDataAttributes.js +1 -1
  335. package/esm/unstable-use-media-query/index.js +1 -1
  336. package/esm/utils/popups/index.d.ts +1 -0
  337. package/esm/utils/popups/index.js +1 -0
  338. package/esm/utils/popups/inlineRect.d.ts +15 -0
  339. package/esm/utils/popups/inlineRect.js +191 -0
  340. package/esm/utils/popups/popupStoreUtils.d.ts +28 -10
  341. package/esm/utils/popups/popupStoreUtils.js +105 -20
  342. package/esm/utils/popups/popupTriggerMap.js +2 -0
  343. package/esm/utils/popups/store.d.ts +15 -2
  344. package/esm/utils/popups/store.js +38 -2
  345. package/esm/utils/popups/useTriggerFocusGuards.js +4 -5
  346. package/esm/utils/useAnchorPositioning.d.ts +5 -0
  347. package/esm/utils/useAnchorPositioning.js +12 -9
  348. package/esm/utils/useOpenInteractionType.d.ts +4 -0
  349. package/esm/utils/useOpenInteractionType.js +23 -18
  350. package/field/control/FieldControl.js +2 -6
  351. package/field/item/FieldItem.js +1 -4
  352. package/field/root/FieldRoot.js +11 -3
  353. package/field/root/useFieldValidation.d.ts +1 -0
  354. package/field/root/useFieldValidation.js +23 -20
  355. package/field/utils/getCombinedFieldValidityData.d.ts +1 -1
  356. package/field/validity/FieldValidity.d.ts +1 -1
  357. package/floating-ui-react/components/FloatingDelayGroup.js +3 -3
  358. package/floating-ui-react/components/FloatingFocusManager.d.ts +1 -1
  359. package/floating-ui-react/components/FloatingFocusManager.js +20 -8
  360. package/floating-ui-react/components/FloatingPortal.js +3 -3
  361. package/floating-ui-react/hooks/useClick.js +82 -73
  362. package/floating-ui-react/hooks/useClientPoint.js +29 -20
  363. package/floating-ui-react/hooks/useDismiss.d.ts +1 -1
  364. package/floating-ui-react/hooks/useDismiss.js +82 -92
  365. package/floating-ui-react/hooks/useFloating.js +36 -32
  366. package/floating-ui-react/hooks/useFloatingRootContext.d.ts +1 -1
  367. package/floating-ui-react/hooks/useFloatingRootContext.js +2 -2
  368. package/floating-ui-react/hooks/useFocus.js +84 -81
  369. package/floating-ui-react/hooks/useHover.js +74 -78
  370. package/floating-ui-react/hooks/useHoverFloatingInteraction.js +48 -43
  371. package/floating-ui-react/hooks/useHoverInteractionSharedState.js +1 -1
  372. package/floating-ui-react/hooks/useHoverReferenceInteraction.d.ts +7 -2
  373. package/floating-ui-react/hooks/useHoverReferenceInteraction.js +43 -38
  374. package/floating-ui-react/hooks/useHoverShared.d.ts +2 -1
  375. package/floating-ui-react/hooks/useHoverShared.js +11 -0
  376. package/floating-ui-react/hooks/useListNavigation.d.ts +1 -3
  377. package/floating-ui-react/hooks/useListNavigation.js +83 -74
  378. package/floating-ui-react/hooks/useSyncedFloatingRootContext.d.ts +9 -6
  379. package/floating-ui-react/hooks/useSyncedFloatingRootContext.js +26 -20
  380. package/floating-ui-react/hooks/useTypeahead.d.ts +2 -2
  381. package/floating-ui-react/hooks/useTypeahead.js +33 -52
  382. package/floating-ui-react/index.d.ts +0 -2
  383. package/floating-ui-react/index.js +0 -14
  384. package/floating-ui-react/types.d.ts +2 -7
  385. package/floating-ui-react/utils/composite.js +2 -0
  386. package/floating-ui-react/utils/enqueueFocus.d.ts +1 -1
  387. package/floating-ui-react/utils/enqueueFocus.js +10 -7
  388. package/floating-ui-react/utils/getEmptyRootContext.js +1 -1
  389. package/form/Form.js +2 -2
  390. package/index.js +1 -1
  391. package/internals/composite/composite.d.ts +0 -1
  392. package/internals/composite/composite.js +2 -3
  393. package/internals/composite/root/useCompositeRoot.js +1 -1
  394. package/internals/createBaseUIEventDetails.d.ts +2 -0
  395. package/internals/csp-context/index.d.ts +2 -0
  396. package/internals/csp-context/index.js +18 -0
  397. package/internals/field-register-control/index.d.ts +0 -1
  398. package/internals/field-register-control/useFieldControlRegistration.d.ts +2 -1
  399. package/internals/field-register-control/useFieldControlRegistration.js +11 -14
  400. package/internals/field-register-control/useRegisterFieldControl.d.ts +1 -4
  401. package/internals/field-register-control/useRegisterFieldControl.js +6 -11
  402. package/internals/field-root-context/FieldRootContext.d.ts +1 -0
  403. package/internals/field-root-context/FieldRootContext.js +4 -3
  404. package/internals/form-context/FormContext.d.ts +5 -1
  405. package/internals/reason-parts.d.ts +2 -0
  406. package/internals/reason-parts.js +3 -1
  407. package/internals/types.d.ts +1 -0
  408. package/internals/use-button/useButton.js +4 -4
  409. package/internals/usePressAndHold.js +2 -2
  410. package/internals/useRenderElement.js +2 -0
  411. package/menu/arrow/MenuArrow.js +1 -1
  412. package/menu/backdrop/MenuBackdrop.js +1 -1
  413. package/menu/checkbox-item/MenuCheckboxItem.js +5 -7
  414. package/menu/group/MenuGroup.js +1 -4
  415. package/menu/group/MenuGroupContext.d.ts +1 -3
  416. package/menu/group/MenuGroupContext.js +1 -1
  417. package/menu/group-label/MenuGroupLabel.js +4 -6
  418. package/menu/link-item/MenuLinkItem.js +2 -2
  419. package/menu/popup/MenuPopup.js +5 -5
  420. package/menu/radio-group/MenuRadioGroup.js +11 -5
  421. package/menu/radio-item/MenuRadioItem.js +5 -7
  422. package/menu/root/MenuRoot.js +60 -65
  423. package/menu/store/MenuHandle.js +1 -1
  424. package/menu/store/MenuStore.d.ts +87 -0
  425. package/menu/submenu-trigger/MenuSubmenuTrigger.js +7 -4
  426. package/menu/trigger/MenuTrigger.js +12 -9
  427. package/menu/viewport/MenuViewport.d.ts +2 -2
  428. package/menu/viewport/MenuViewport.js +2 -2
  429. package/navigation-menu/arrow/NavigationMenuArrow.js +1 -1
  430. package/navigation-menu/backdrop/NavigationMenuBackdrop.js +1 -1
  431. package/navigation-menu/content/NavigationMenuContent.js +8 -5
  432. package/navigation-menu/icon/NavigationMenuIcon.js +1 -1
  433. package/navigation-menu/item/NavigationMenuItem.js +2 -2
  434. package/navigation-menu/list/NavigationMenuList.js +1 -1
  435. package/navigation-menu/popup/NavigationMenuPopup.js +2 -2
  436. package/navigation-menu/root/NavigationMenuRoot.js +1 -3
  437. package/navigation-menu/trigger/NavigationMenuTrigger.js +23 -16
  438. package/navigation-menu/utils/isOutsideMenuEvent.d.ts +0 -1
  439. package/navigation-menu/utils/isOutsideMenuEvent.js +1 -5
  440. package/navigation-menu/viewport/NavigationMenuViewport.js +2 -3
  441. package/number-field/input/NumberFieldInput.js +3 -5
  442. package/number-field/root/NumberFieldRoot.js +5 -2
  443. package/number-field/scrub-area/NumberFieldScrubArea.js +7 -3
  444. package/otp-field/input/OTPFieldInput.js +42 -28
  445. package/otp-field/root/OTPFieldRoot.d.ts +17 -8
  446. package/otp-field/root/OTPFieldRoot.js +32 -32
  447. package/otp-field/root/OTPFieldRootContext.d.ts +1 -1
  448. package/otp-field/utils/otp.d.ts +5 -4
  449. package/otp-field/utils/otp.js +24 -12
  450. package/package.json +331 -317
  451. package/popover/arrow/PopoverArrow.js +1 -1
  452. package/popover/backdrop/PopoverBackdrop.js +1 -1
  453. package/popover/close/PopoverClose.js +2 -2
  454. package/popover/description/PopoverDescription.js +1 -7
  455. package/popover/popup/PopoverPopup.d.ts +1 -1
  456. package/popover/popup/PopoverPopup.js +16 -10
  457. package/popover/popup/PopoverPopupDataAttributes.d.ts +1 -1
  458. package/popover/popup/PopoverPopupDataAttributes.js +1 -1
  459. package/popover/positioner/PopoverPositioner.js +5 -5
  460. package/popover/root/PopoverRoot.d.ts +1 -1
  461. package/popover/root/PopoverRoot.js +39 -44
  462. package/popover/store/PopoverHandle.js +1 -1
  463. package/popover/store/PopoverStore.d.ts +91 -4
  464. package/popover/store/PopoverStore.js +16 -19
  465. package/popover/title/PopoverTitle.js +1 -7
  466. package/popover/trigger/PopoverTrigger.js +23 -16
  467. package/popover/viewport/PopoverViewport.d.ts +3 -3
  468. package/popover/viewport/PopoverViewport.js +2 -2
  469. package/popover/viewport/PopoverViewportDataAttributes.d.ts +1 -1
  470. package/popover/viewport/PopoverViewportDataAttributes.js +1 -1
  471. package/preview-card/positioner/PreviewCardPositioner.js +11 -1
  472. package/preview-card/root/PreviewCardRoot.d.ts +1 -1
  473. package/preview-card/root/PreviewCardRoot.js +30 -20
  474. package/preview-card/store/PreviewCardHandle.js +1 -1
  475. package/preview-card/store/PreviewCardStore.d.ts +90 -2
  476. package/preview-card/store/PreviewCardStore.js +18 -30
  477. package/preview-card/trigger/PreviewCardTrigger.js +5 -2
  478. package/preview-card/viewport/PreviewCardViewport.d.ts +2 -2
  479. package/preview-card/viewport/PreviewCardViewport.js +2 -2
  480. package/preview-card/viewport/PreviewCardViewportDataAttributes.d.ts +2 -2
  481. package/preview-card/viewport/PreviewCardViewportDataAttributes.js +2 -2
  482. package/progress/indicator/ProgressIndicator.js +6 -11
  483. package/progress/root/ProgressRoot.d.ts +1 -1
  484. package/radio/root/RadioRoot.js +7 -3
  485. package/radio-group/RadioGroup.js +4 -11
  486. package/radio-group/RadioGroupContext.d.ts +0 -1
  487. package/scroll-area/content/ScrollAreaContent.js +4 -4
  488. package/scroll-area/root/ScrollAreaRoot.js +1 -1
  489. package/scroll-area/scrollbar/ScrollAreaScrollbar.js +16 -20
  490. package/scroll-area/viewport/ScrollAreaViewport.js +6 -10
  491. package/select/arrow/SelectArrow.js +1 -1
  492. package/select/backdrop/SelectBackdrop.js +1 -1
  493. package/select/group/SelectGroup.js +1 -1
  494. package/select/group-label/SelectGroupLabel.js +2 -2
  495. package/select/icon/SelectIcon.js +1 -1
  496. package/select/item/SelectItem.js +46 -32
  497. package/select/item/SelectItemContext.d.ts +1 -1
  498. package/select/item-indicator/SelectItemIndicator.js +1 -2
  499. package/select/item-text/SelectItemText.js +9 -6
  500. package/select/list/SelectList.js +1 -1
  501. package/select/popup/SelectPopup.js +8 -3
  502. package/select/positioner/SelectPositioner.js +3 -0
  503. package/select/root/SelectRoot.js +45 -39
  504. package/select/root/SelectRootContext.d.ts +4 -5
  505. package/select/store.d.ts +3 -0
  506. package/select/store.js +1 -0
  507. package/select/trigger/SelectTrigger.d.ts +5 -0
  508. package/select/trigger/SelectTrigger.js +19 -33
  509. package/select/trigger/SelectTriggerDataAttributes.d.ts +5 -0
  510. package/select/trigger/SelectTriggerDataAttributes.js +5 -0
  511. package/slider/control/SliderControl.js +9 -11
  512. package/slider/root/SliderRoot.js +1 -4
  513. package/slider/thumb/SliderThumb.js +32 -30
  514. package/slider/value/SliderValue.js +7 -15
  515. package/switch/root/SwitchRoot.js +10 -10
  516. package/switch/thumb/SwitchThumb.js +1 -9
  517. package/tabs/indicator/TabsIndicator.js +14 -19
  518. package/tabs/list/TabsList.js +4 -10
  519. package/tabs/list/TabsListContext.d.ts +2 -1
  520. package/tabs/panel/TabsPanel.js +1 -1
  521. package/tabs/root/TabsRoot.d.ts +16 -1
  522. package/tabs/root/TabsRoot.js +71 -24
  523. package/tabs/root/TabsRootContext.d.ts +0 -2
  524. package/toast/provider/ToastProvider.js +1 -1
  525. package/toast/root/ToastRoot.d.ts +1 -1
  526. package/toast/root/ToastRoot.js +110 -133
  527. package/toast/root/ToastRootDataAttributes.d.ts +1 -1
  528. package/toast/root/ToastRootDataAttributes.js +1 -1
  529. package/toast/store.d.ts +9 -1
  530. package/toast/store.js +18 -12
  531. package/toast/useToastManager.d.ts +1 -1
  532. package/toast/viewport/ToastViewport.js +1 -1
  533. package/toggle/Toggle.js +5 -9
  534. package/toggle-group/ToggleGroup.d.ts +2 -2
  535. package/toggle-group/ToggleGroup.js +6 -13
  536. package/toolbar/link/ToolbarLink.d.ts +1 -1
  537. package/toolbar/link/ToolbarLink.js +1 -2
  538. package/tooltip/arrow/TooltipArrow.js +3 -3
  539. package/tooltip/popup/TooltipPopup.js +5 -4
  540. package/tooltip/root/TooltipRoot.js +32 -23
  541. package/tooltip/store/TooltipHandle.js +1 -1
  542. package/tooltip/store/TooltipStore.d.ts +90 -2
  543. package/tooltip/store/TooltipStore.js +17 -30
  544. package/tooltip/trigger/TooltipTrigger.js +152 -20
  545. package/tooltip/viewport/TooltipViewport.d.ts +2 -2
  546. package/tooltip/viewport/TooltipViewport.js +2 -2
  547. package/tooltip/viewport/TooltipViewportDataAttributes.d.ts +1 -1
  548. package/tooltip/viewport/TooltipViewportDataAttributes.js +1 -1
  549. package/unstable-use-media-query/index.js +1 -1
  550. package/utils/popups/index.d.ts +1 -0
  551. package/utils/popups/index.js +11 -0
  552. package/utils/popups/inlineRect.d.ts +15 -0
  553. package/utils/popups/inlineRect.js +198 -0
  554. package/utils/popups/popupStoreUtils.d.ts +28 -10
  555. package/utils/popups/popupStoreUtils.js +110 -20
  556. package/utils/popups/popupTriggerMap.js +2 -0
  557. package/utils/popups/store.d.ts +15 -2
  558. package/utils/popups/store.js +39 -2
  559. package/utils/popups/useTriggerFocusGuards.js +4 -5
  560. package/utils/useAnchorPositioning.d.ts +5 -0
  561. package/utils/useAnchorPositioning.js +12 -9
  562. package/utils/useOpenInteractionType.d.ts +4 -0
  563. package/utils/useOpenInteractionType.js +24 -17
  564. package/checkbox-group/index.parts.d.ts +0 -1
  565. package/checkbox-group/index.parts.js +0 -12
  566. package/esm/checkbox-group/index.parts.d.ts +0 -1
  567. package/esm/checkbox-group/index.parts.js +0 -1
  568. package/esm/floating-ui-react/hooks/useInteractions.d.ts +0 -20
  569. package/esm/floating-ui-react/hooks/useInteractions.js +0 -88
  570. package/esm/floating-ui-react/hooks/useRole.d.ts +0 -17
  571. package/esm/floating-ui-react/hooks/useRole.js +0 -113
  572. package/floating-ui-react/hooks/useInteractions.d.ts +0 -20
  573. package/floating-ui-react/hooks/useInteractions.js +0 -95
  574. package/floating-ui-react/hooks/useRole.d.ts +0 -17
  575. package/floating-ui-react/hooks/useRole.js +0 -120
  576. /package/{csp-provider → esm/internals/csp-context}/CSPContext.d.ts +0 -0
  577. /package/esm/{csp-provider → internals/csp-context}/CSPContext.js +0 -0
  578. /package/{esm/csp-provider → internals/csp-context}/CSPContext.d.ts +0 -0
  579. /package/{csp-provider → internals/csp-context}/CSPContext.js +0 -0
@@ -2,8 +2,8 @@ import * as React from 'react';
2
2
  import { BaseUIComponentProps } from "../../internals/types.js";
3
3
  /**
4
4
  * A viewport for displaying content transitions.
5
- * This component is only required if one popup can be opened by multiple triggers, its content change based on the trigger
6
- * and switching between them is animated.
5
+ * This component is only required if one popup can be opened by multiple triggers, its content
6
+ * changes based on the trigger, and switching between them is animated.
7
7
  * Renders a `<div>` element.
8
8
  *
9
9
  * Documentation: [Base UI Tooltip](https://base-ui.com/react/components/tooltip)
@@ -14,8 +14,8 @@ const stateAttributesMapping = {
14
14
 
15
15
  /**
16
16
  * A viewport for displaying content transitions.
17
- * This component is only required if one popup can be opened by multiple triggers, its content change based on the trigger
18
- * and switching between them is animated.
17
+ * This component is only required if one popup can be opened by multiple triggers, its content
18
+ * changes based on the trigger, and switching between them is animated.
19
19
  * Renders a `<div>` element.
20
20
  *
21
21
  * Documentation: [Base UI Tooltip](https://base-ui.com/react/components/tooltip)
@@ -11,7 +11,7 @@ export declare enum TooltipViewportDataAttributes {
11
11
  * Indicates the direction from which the popup was activated.
12
12
  * This can be used to create directional animations based on how the popup was triggered.
13
13
  * Contains space-separated values for both horizontal and vertical axes.
14
- * @type {`${'left' | 'right'} {'top' | 'bottom'}`}
14
+ * @type {`${'left' | 'right'} ${'top' | 'bottom'}`}
15
15
  */
16
16
  activationDirection = "data-activation-direction",
17
17
  /**
@@ -11,7 +11,7 @@ export let TooltipViewportDataAttributes = /*#__PURE__*/function (TooltipViewpor
11
11
  * Indicates the direction from which the popup was activated.
12
12
  * This can be used to create directional animations based on how the popup was triggered.
13
13
  * Contains space-separated values for both horizontal and vertical axes.
14
- * @type {`${'left' | 'right'} {'top' | 'bottom'}`}
14
+ * @type {`${'left' | 'right'} ${'top' | 'bottom'}`}
15
15
  */
16
16
  TooltipViewportDataAttributes["activationDirection"] = "data-activation-direction";
17
17
  /**
@@ -5,7 +5,7 @@ export function useMediaQuery(query, options) {
5
5
  // Wait for jsdom to support the match media feature.
6
6
  // All the browsers Base UI support have this built-in.
7
7
  // This defensive check is here for simplicity.
8
- // Most of the time, the match media logic isn't central to people tests.
8
+ // Most of the time, the match media logic isn't central to people's tests.
9
9
  const supportMatchMedia = typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';
10
10
  query = query.replace(/^@media( ?)/m, '');
11
11
  const {
@@ -1,3 +1,4 @@
1
+ export * from "./inlineRect.js";
1
2
  export * from "./popupStoreUtils.js";
2
3
  export * from "./popupTriggerMap.js";
3
4
  export * from "./store.js";
@@ -1,3 +1,4 @@
1
+ export * from "./inlineRect.js";
1
2
  export * from "./popupStoreUtils.js";
2
3
  export * from "./popupTriggerMap.js";
3
4
  export * from "./store.js";
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import type { Middleware } from '@floating-ui/react-dom';
3
+ export interface InlineRectCoords {
4
+ /** The x position in viewport coordinates. */
5
+ x: number;
6
+ /** The y position in viewport coordinates. */
7
+ y: number;
8
+ /** The line index under the pointer when coordinates were captured. */
9
+ lineIndex?: number | undefined;
10
+ /** The trigger element whose rects produced these coordinates. */
11
+ element: Element;
12
+ }
13
+ export declare function getInlineRectTriggerProps(coordsRef: React.RefObject<InlineRectCoords | undefined>, isOpen: boolean): Pick<React.HTMLAttributes<Element>, 'onFocus' | 'onMouseEnter' | 'onMouseMove'>;
14
+ export declare function updateInlineRectCoords(coordsRef: React.RefObject<InlineRectCoords | undefined>, element: Element, clientX: number, clientY: number): InlineRectCoords | undefined;
15
+ export declare function createInlineMiddleware(coordsRef: React.RefObject<InlineRectCoords | undefined>): Middleware;
@@ -0,0 +1,191 @@
1
+ import { isElement } from '@floating-ui/utils/dom';
2
+
3
+ // Floating UI ships an `inline()` middleware. This local version mirrors its line-rect
4
+ // selection while adding trigger identity checks, delayed-open hit-line reuse, and
5
+ // improved left/right edge grouping for Preview Card's reusable trigger model.
6
+
7
+ function createRect(left, top, right, bottom) {
8
+ return {
9
+ left,
10
+ top,
11
+ right,
12
+ bottom,
13
+ x: left,
14
+ y: top,
15
+ width: right - left,
16
+ height: bottom - top
17
+ };
18
+ }
19
+ function copyRect(rect) {
20
+ return {
21
+ left: rect.left,
22
+ top: rect.top,
23
+ right: rect.right,
24
+ bottom: rect.bottom,
25
+ width: rect.width,
26
+ height: rect.height
27
+ };
28
+ }
29
+ function getLineRects(rects) {
30
+ const lines = [];
31
+ let previousRect;
32
+ let left = Number.POSITIVE_INFINITY;
33
+ let top = Number.POSITIVE_INFINITY;
34
+ let right = Number.NEGATIVE_INFINITY;
35
+ let bottom = Number.NEGATIVE_INFINITY;
36
+ for (const rect of Array.from(rects).sort((a, b) => a.top - b.top)) {
37
+ left = Math.min(left, rect.left);
38
+ top = Math.min(top, rect.top);
39
+ right = Math.max(right, rect.right);
40
+ bottom = Math.max(bottom, rect.bottom);
41
+ if (!previousRect || rect.top - previousRect.top > previousRect.height / 2) {
42
+ lines.push(copyRect(rect));
43
+ } else {
44
+ const line = lines[lines.length - 1];
45
+ line.left = Math.min(line.left, rect.left);
46
+ line.right = Math.max(line.right, rect.right);
47
+ line.bottom = Math.max(line.bottom, rect.bottom);
48
+ line.width = line.right - line.left;
49
+ line.height = line.bottom - line.top;
50
+ }
51
+ previousRect = rect;
52
+ }
53
+ return {
54
+ lines,
55
+ fallback: createRect(left, top, right, bottom)
56
+ };
57
+ }
58
+ function findLineIndex(lines, x, y) {
59
+ return lines.findIndex(lineRect => x > lineRect.left - 2 && x < lineRect.right + 2 && y > lineRect.top - 2 && y < lineRect.bottom + 2);
60
+ }
61
+ function createClientRect(rect) {
62
+ return createRect(rect.left, rect.top, rect.right, rect.bottom);
63
+ }
64
+ function getInlineRectCoords(element, clientX, clientY) {
65
+ const {
66
+ lines
67
+ } = getLineRects(element.getClientRects());
68
+ if (lines.length < 2) {
69
+ return undefined;
70
+ }
71
+ const lineIndex = findLineIndex(lines, clientX, clientY);
72
+ return {
73
+ x: clientX,
74
+ y: clientY,
75
+ lineIndex: lineIndex === -1 ? undefined : lineIndex,
76
+ element
77
+ };
78
+ }
79
+ function getInlineReferenceRect(reference, placement, coords) {
80
+ const {
81
+ lines,
82
+ fallback
83
+ } = getLineRects(reference.getClientRects());
84
+ if (lines.length < 2) {
85
+ return null;
86
+ }
87
+ const x = coords?.x;
88
+ const y = coords?.y;
89
+ const side = placement[0];
90
+ if (coords?.lineIndex != null && lines[coords.lineIndex]) {
91
+ return createClientRect(lines[coords.lineIndex]);
92
+ }
93
+ if (x != null && y != null) {
94
+ const lineIndex = findLineIndex(lines, x, y);
95
+ if (lineIndex !== -1) {
96
+ return createClientRect(lines[lineIndex]);
97
+ }
98
+ }
99
+ if (lines.length === 2 && lines[0].left > lines[1].right && x != null && y != null) {
100
+ return fallback;
101
+ }
102
+ if (side === 't' || side === 'b') {
103
+ const firstRect = lines[0];
104
+ const lastRect = lines[lines.length - 1];
105
+ const targetRect = side === 't' ? firstRect : lastRect;
106
+ return createRect(targetRect.left, firstRect.top, targetRect.right, lastRect.bottom);
107
+ }
108
+ const isLeft = side === 'l';
109
+ let left = lines[0].left;
110
+ let right = lines[0].right;
111
+ let edge = isLeft ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
112
+ let targetFirstRect = lines[0];
113
+ let targetLastRect = lines[0];
114
+ for (const rect of lines) {
115
+ left = Math.min(left, rect.left);
116
+ right = Math.max(right, rect.right);
117
+ const nextEdge = isLeft ? rect.left : rect.right;
118
+ if (isLeft && nextEdge < edge || !isLeft && nextEdge > edge) {
119
+ edge = nextEdge;
120
+ targetFirstRect = rect;
121
+ targetLastRect = rect;
122
+ } else if (nextEdge === edge) {
123
+ targetLastRect = rect;
124
+ }
125
+ }
126
+ return createRect(left, targetFirstRect.top, right, targetLastRect.bottom);
127
+ }
128
+ function getContextElement(reference) {
129
+ if ('contextElement' in reference && reference.contextElement) {
130
+ return reference.contextElement;
131
+ }
132
+ return isElement(reference) ? reference : undefined;
133
+ }
134
+ export function getInlineRectTriggerProps(coordsRef, isOpen) {
135
+ function updateCoords(event) {
136
+ updateInlineRectCoords(coordsRef, event.currentTarget, event.clientX, event.clientY);
137
+ }
138
+ function updateCoordsOnMove(event) {
139
+ if (!isOpen) {
140
+ updateCoords(event);
141
+ }
142
+ }
143
+ return {
144
+ onFocus() {
145
+ coordsRef.current = undefined;
146
+ },
147
+ onMouseEnter: updateCoords,
148
+ onMouseMove: updateCoordsOnMove
149
+ };
150
+ }
151
+ export function updateInlineRectCoords(coordsRef, element, clientX, clientY) {
152
+ const nextCoords = getInlineRectCoords(element, clientX, clientY);
153
+ coordsRef.current = nextCoords;
154
+ return nextCoords;
155
+ }
156
+ export function createInlineMiddleware(coordsRef) {
157
+ return {
158
+ name: 'inline',
159
+ async fn(state) {
160
+ const reference = state.elements.reference;
161
+ if (typeof reference?.getClientRects !== 'function') {
162
+ return {};
163
+ }
164
+ const contextElement = getContextElement(reference);
165
+ const coords = coordsRef.current;
166
+ const currentCoords = coords?.element === reference || coords?.element === contextElement ? coords : undefined;
167
+ const rect = getInlineReferenceRect(reference, state.placement, currentCoords);
168
+ if (!rect || typeof state.platform.getElementRects !== 'function') {
169
+ return {};
170
+ }
171
+ const resetRects = await state.platform.getElementRects({
172
+ reference: {
173
+ contextElement,
174
+ getBoundingClientRect() {
175
+ return rect;
176
+ }
177
+ },
178
+ floating: state.elements.floating,
179
+ strategy: state.strategy
180
+ });
181
+ if (state.rects.reference.x === resetRects.reference.x && state.rects.reference.y === resetRects.reference.y && state.rects.reference.width === resetRects.reference.width && state.rects.reference.height === resetRects.reference.height) {
182
+ return {};
183
+ }
184
+ return {
185
+ reset: {
186
+ rects: resetRects
187
+ }
188
+ };
189
+ }
190
+ };
191
+ }
@@ -1,21 +1,35 @@
1
1
  import * as React from 'react';
2
2
  import { ReactStore } from '@base-ui/utils/store';
3
+ import type { InteractionType } from '@base-ui/utils/useEnhancedClickHandler';
4
+ import type { BaseUIChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
3
5
  import { PopupStoreState, PopupStoreContext, popupStoreSelectors, PopupStoreSelectors } from "./store.js";
6
+ export declare const FOCUSABLE_POPUP_PROPS: {
7
+ tabIndex: number;
8
+ "data-base-ui-focusable": string;
9
+ };
10
+ type PopupStoreWithOpen<State extends PopupStoreState<unknown>, SetOpenEventDetails extends BaseUIChangeEventDetails<string>> = ReactStore<State, PopupStoreContext<never>, PopupStoreSelectors> & {
11
+ setOpen(open: boolean, eventDetails: SetOpenEventDetails): void;
12
+ };
13
+ export declare function usePopupStore<State extends PopupStoreState<unknown>, SetOpenEventDetails extends BaseUIChangeEventDetails<string>, Store extends PopupStoreWithOpen<State, SetOpenEventDetails>>(externalStore: Store | undefined, createStore: (floatingId: string | undefined, nested: boolean) => Store, treatPopupAsFloatingElement?: boolean): {
14
+ store: Store;
15
+ internalStore: Store | null;
16
+ };
4
17
  /**
5
18
  * Returns a callback ref that registers/unregisters the trigger element in the store.
6
19
  *
7
20
  * @param store The Store instance where the trigger should be registered.
8
21
  */
9
- export declare function useTriggerRegistration<State extends PopupStoreState<any>>(id: string | undefined, store: ReactStore<State, PopupStoreContext<any>, PopupStoreSelectors>): (element: Element | null) => void;
22
+ export declare function useTriggerRegistration<State extends PopupStoreState<unknown>>(id: string | undefined, store: ReactStore<State, PopupStoreContext<never>, PopupStoreSelectors>): (element: Element | null) => void;
23
+ export declare function setOpenTriggerState(state: Partial<PopupStoreState<unknown>>, open: boolean, trigger: Element | undefined): void;
10
24
  /**
11
25
  * Sets up trigger data forwarding to the store.
12
26
  *
13
27
  * @param triggerId Id of the trigger.
14
- * @param triggerElement The trigger DOM element.
28
+ * @param triggerElementRef Ref for the trigger DOM element.
15
29
  * @param store The Store instance managing the popup state.
16
30
  * @param stateUpdates An object with state updates to apply when the trigger is active.
17
31
  */
18
- export declare function useTriggerDataForwarding<State extends PopupStoreState<any>>(triggerId: string | undefined, triggerElementRef: React.RefObject<Element | null>, store: ReactStore<State, PopupStoreContext<any>, typeof popupStoreSelectors>, stateUpdates: Omit<Partial<State>, 'activeTriggerId' | 'activeTriggerElement'>): {
32
+ export declare function useTriggerDataForwarding<State extends PopupStoreState<unknown>>(triggerId: string | undefined, triggerElementRef: React.RefObject<Element | null>, store: ReactStore<State, PopupStoreContext<never>, typeof popupStoreSelectors>, stateUpdates: Omit<Partial<State>, 'activeTriggerId' | 'activeTriggerElement'>): {
19
33
  registerTrigger: (element: Element | null) => void;
20
34
  isMountedByThisTrigger: boolean;
21
35
  };
@@ -24,17 +38,16 @@ export type PayloadChildRenderFunction<Payload> = (arg: {
24
38
  }) => React.ReactNode;
25
39
  /**
26
40
  * Ensures that when there's only one trigger element registered, it is set as the active trigger.
27
- * This allows controlled popups to work correctly without an explicit triggerId, maintaining compatibility
28
- * with the contained triggers.
41
+ * This keeps triggerCount reactive while open and allows controlled popups to work correctly without
42
+ * an explicit triggerId, maintaining compatibility with contained triggers.
29
43
  *
30
44
  * This should be called on the Root part.
31
45
  *
32
- * @param open Whether the popup is open.
33
46
  * @param store The Store instance managing the popup state.
34
47
  */
35
- export declare function useImplicitActiveTrigger<State extends PopupStoreState<any>>(store: ReactStore<State, PopupStoreContext<any>, typeof popupStoreSelectors>): void;
48
+ export declare function useImplicitActiveTrigger<State extends PopupStoreState<unknown>>(store: ReactStore<State, PopupStoreContext<never>, typeof popupStoreSelectors>): void;
36
49
  /**
37
- * Mangages the mounted state of the popup.
50
+ * Manages the mounted state of the popup.
38
51
  * Sets up the transition status listeners and handles unmounting when needed.
39
52
  * Updates the `mounted` and `transitionStatus` states in the store.
40
53
  *
@@ -44,7 +57,12 @@ export declare function useImplicitActiveTrigger<State extends PopupStoreState<a
44
57
  *
45
58
  * @returns A function to forcibly unmount the popup.
46
59
  */
47
- export declare function useOpenStateTransitions<State extends PopupStoreState<any>>(open: boolean, store: ReactStore<State, PopupStoreContext<any>, typeof popupStoreSelectors>, onUnmount?: () => void): {
60
+ export declare function useOpenStateTransitions<State extends PopupStoreState<unknown>>(open: boolean, store: ReactStore<State, PopupStoreContext<never>, typeof popupStoreSelectors>, onUnmount?: () => void): {
48
61
  forceUnmount: () => void;
49
62
  transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus;
50
- };
63
+ };
64
+ export declare function usePopupInteractionProps<State extends PopupStoreState<unknown>>(store: ReactStore<State, PopupStoreContext<never>, typeof popupStoreSelectors>, statePart: Partial<State> & Pick<State, 'activeTriggerProps' | 'inactiveTriggerProps' | 'popupProps'>): void;
65
+ export declare function usePopupRootSync<State extends PopupStoreState<unknown> & {
66
+ openMethod: InteractionType | null;
67
+ }>(store: ReactStore<State, PopupStoreContext<never>, typeof popupStoreSelectors>, open: boolean): void;
68
+ export {};
@@ -1,10 +1,41 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
+ import { EMPTY_OBJECT } from '@base-ui/utils/empty';
5
+ import { useId } from '@base-ui/utils/useId';
4
6
  import { useStableCallback } from '@base-ui/utils/useStableCallback';
5
7
  import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
8
+ import { FOCUSABLE_ATTRIBUTE } from "../../floating-ui-react/utils/constants.js";
9
+ import { useFloatingParentNodeId } from "../../floating-ui-react/components/FloatingTree.js";
10
+ import { useSyncedFloatingRootContext } from "../../floating-ui-react/hooks/useSyncedFloatingRootContext.js";
6
11
  import { useTransitionStatus } from "../../internals/useTransitionStatus.js";
7
12
  import { useOpenChangeComplete } from "../../internals/useOpenChangeComplete.js";
13
+ export const FOCUSABLE_POPUP_PROPS = {
14
+ tabIndex: -1,
15
+ [FOCUSABLE_ATTRIBUTE]: ''
16
+ };
17
+ export function usePopupStore(externalStore, createStore, treatPopupAsFloatingElement = false) {
18
+ const floatingId = useId();
19
+ const nested = useFloatingParentNodeId() != null;
20
+ const internalStoreRef = React.useRef(null);
21
+ if (externalStore === undefined && internalStoreRef.current === null) {
22
+ internalStoreRef.current = createStore(floatingId, nested);
23
+ }
24
+ const store = externalStore ?? internalStoreRef.current;
25
+ useSyncedFloatingRootContext({
26
+ popupStore: store,
27
+ treatPopupAsFloatingElement,
28
+ floatingRootContext: store.state.floatingRootContext,
29
+ floatingId,
30
+ nested,
31
+ onOpenChange: store.setOpen
32
+ });
33
+ return {
34
+ store,
35
+ internalStore: internalStoreRef.current
36
+ };
37
+ }
38
+
8
39
  /**
9
40
  * Returns a callback ref that registers/unregisters the trigger element in the store.
10
41
  *
@@ -18,12 +49,14 @@ export function useTriggerRegistration(id, store) {
18
49
  if (id === undefined) {
19
50
  return;
20
51
  }
52
+ let shouldSyncTriggerCount = false;
21
53
  if (registeredElementIdRef.current !== null) {
22
54
  const registeredId = registeredElementIdRef.current;
23
55
  const registeredElement = registeredElementRef.current;
24
56
  const currentElement = store.context.triggerElements.getById(registeredId);
25
57
  if (registeredElement && currentElement === registeredElement) {
26
58
  store.context.triggerElements.delete(registeredId);
59
+ shouldSyncTriggerCount = true;
27
60
  }
28
61
  registeredElementIdRef.current = null;
29
62
  registeredElementRef.current = null;
@@ -32,15 +65,32 @@ export function useTriggerRegistration(id, store) {
32
65
  registeredElementIdRef.current = id;
33
66
  registeredElementRef.current = element;
34
67
  store.context.triggerElements.add(id, element);
68
+ shouldSyncTriggerCount = true;
69
+ }
70
+ if (shouldSyncTriggerCount) {
71
+ const triggerCount = store.context.triggerElements.size;
72
+ if (store.select('open') && store.state.triggerCount !== triggerCount) {
73
+ store.set('triggerCount', triggerCount);
74
+ }
35
75
  }
36
76
  }, [store, id]);
37
77
  }
78
+ export function setOpenTriggerState(state, open, trigger) {
79
+ const triggerId = trigger?.id ?? null;
80
+
81
+ // If a popup is closing, the `trigger` may be undefined.
82
+ // We want to keep the previous value so that exit animations are played and focus is returned correctly.
83
+ if (triggerId || open) {
84
+ state.activeTriggerId = triggerId;
85
+ state.activeTriggerElement = trigger ?? null;
86
+ }
87
+ }
38
88
 
39
89
  /**
40
90
  * Sets up trigger data forwarding to the store.
41
91
  *
42
92
  * @param triggerId Id of the trigger.
43
- * @param triggerElement The trigger DOM element.
93
+ * @param triggerElementRef Ref for the trigger DOM element.
44
94
  * @param store The Store instance managing the popup state.
45
95
  * @param stateUpdates An object with state updates to apply when the trigger is active.
46
96
  */
@@ -49,22 +99,22 @@ export function useTriggerDataForwarding(triggerId, triggerElementRef, store, st
49
99
  const baseRegisterTrigger = useTriggerRegistration(triggerId, store);
50
100
  const registerTrigger = useStableCallback(element => {
51
101
  baseRegisterTrigger(element);
52
- if (!element || !store.select('open')) {
102
+ if (!element) {
53
103
  return;
54
104
  }
105
+ const open = store.select('open');
55
106
  const activeTriggerId = store.select('activeTriggerId');
56
107
  if (activeTriggerId === triggerId) {
57
108
  store.update({
58
109
  activeTriggerElement: element,
59
- ...stateUpdates
110
+ ...(open ? stateUpdates : null)
60
111
  });
61
112
  return;
62
113
  }
63
- if (activeTriggerId == null) {
64
- // This runs when popup is open, but no active trigger is set.
65
- // It can happen when using controlled mode and the trigger is mounted after opening or if `triggerId` prop is not set explicitly.
66
- // In such cases the first trigger to run this code becomes the active trigger (store.select('activeTriggerId') should not return null after that).
67
- // This is mostly for compatibility with contained triggers where no explicit `triggerId` was required in controlled mode.
114
+ if (activeTriggerId == null && open) {
115
+ // If a popup is already open, a detached trigger can mount before any active trigger
116
+ // has been established. Claim the first registered trigger so trigger-owned focus
117
+ // management and ARIA relationships work.
68
118
  store.update({
69
119
  activeTriggerId: triggerId,
70
120
  activeTriggerElement: element,
@@ -88,32 +138,44 @@ export function useTriggerDataForwarding(triggerId, triggerElementRef, store, st
88
138
  }
89
139
  /**
90
140
  * Ensures that when there's only one trigger element registered, it is set as the active trigger.
91
- * This allows controlled popups to work correctly without an explicit triggerId, maintaining compatibility
92
- * with the contained triggers.
141
+ * This keeps triggerCount reactive while open and allows controlled popups to work correctly without
142
+ * an explicit triggerId, maintaining compatibility with contained triggers.
93
143
  *
94
144
  * This should be called on the Root part.
95
145
  *
96
- * @param open Whether the popup is open.
97
146
  * @param store The Store instance managing the popup state.
98
147
  */
99
148
  export function useImplicitActiveTrigger(store) {
100
149
  const open = store.useState('open');
150
+ const reactiveTriggerCount = store.useState('triggerCount');
101
151
  useIsoLayoutEffect(() => {
102
- if (open && !store.select('activeTriggerId') && store.context.triggerElements.size === 1) {
152
+ if (!open) {
153
+ if (store.state.triggerCount !== 0) {
154
+ store.set('triggerCount', 0);
155
+ }
156
+ return;
157
+ }
158
+ const triggerCount = store.context.triggerElements.size;
159
+ const stateUpdates = {};
160
+ if (store.state.triggerCount !== triggerCount) {
161
+ stateUpdates.triggerCount = triggerCount;
162
+ }
163
+ if (!store.select('activeTriggerId') && triggerCount === 1) {
103
164
  const iteratorResult = store.context.triggerElements.entries().next();
104
165
  if (!iteratorResult.done) {
105
166
  const [implicitTriggerId, implicitTriggerElement] = iteratorResult.value;
106
- store.update({
107
- activeTriggerId: implicitTriggerId,
108
- activeTriggerElement: implicitTriggerElement
109
- });
167
+ stateUpdates.activeTriggerId = implicitTriggerId;
168
+ stateUpdates.activeTriggerElement = implicitTriggerElement;
110
169
  }
111
170
  }
112
- }, [open, store]);
171
+ if (stateUpdates.triggerCount !== undefined || stateUpdates.activeTriggerId !== undefined) {
172
+ store.update(stateUpdates);
173
+ }
174
+ }, [open, store, reactiveTriggerCount]);
113
175
  }
114
176
 
115
177
  /**
116
- * Mangages the mounted state of the popup.
178
+ * Manages the mounted state of the popup.
117
179
  * Sets up the transition status listeners and handles unmounting when needed.
118
180
  * Updates the `mounted` and `transitionStatus` states in the store.
119
181
  *
@@ -138,14 +200,15 @@ export function useOpenStateTransitions(open, store, onUnmount) {
138
200
  store.update({
139
201
  activeTriggerId: null,
140
202
  activeTriggerElement: null,
141
- mounted: false
203
+ mounted: false,
204
+ preventUnmountingOnClose: false
142
205
  });
143
206
  onUnmount?.();
144
207
  store.context.onOpenChangeComplete?.(false);
145
208
  });
146
209
  const preventUnmountingOnClose = store.useState('preventUnmountingOnClose');
147
210
  useOpenChangeComplete({
148
- enabled: !preventUnmountingOnClose,
211
+ enabled: mounted && !open && !preventUnmountingOnClose,
149
212
  open,
150
213
  ref: store.context.popupRef,
151
214
  onComplete() {
@@ -158,4 +221,26 @@ export function useOpenStateTransitions(open, store, onUnmount) {
158
221
  forceUnmount,
159
222
  transitionStatus
160
223
  };
224
+ }
225
+ export function usePopupInteractionProps(store, statePart) {
226
+ store.useSyncedValues(statePart);
227
+ useIsoLayoutEffect(() => () => {
228
+ store.update({
229
+ activeTriggerProps: EMPTY_OBJECT,
230
+ inactiveTriggerProps: EMPTY_OBJECT,
231
+ popupProps: EMPTY_OBJECT
232
+ });
233
+ }, [store]);
234
+ }
235
+ export function usePopupRootSync(store, open) {
236
+ useIsoLayoutEffect(() => {
237
+ if (!open && store.state.openMethod !== null) {
238
+ store.set('openMethod', null);
239
+ }
240
+ }, [open, store]);
241
+ useIsoLayoutEffect(() => () => {
242
+ if (store.state.openMethod !== null) {
243
+ store.set('openMethod', null);
244
+ }
245
+ }, [store]);
161
246
  }
@@ -27,6 +27,8 @@ export class PopupTriggerMap {
27
27
  this.idMap.set(id, element);
28
28
  if (process.env.NODE_ENV !== 'production') {
29
29
  if (this.elementsSet.size !== this.idMap.size) {
30
+ // TODO: fix mui/no-guarded-throw
31
+ // eslint-disable-next-line mui/no-guarded-throw
30
32
  throw new Error('Base UI: A trigger element cannot be registered under multiple IDs in PopupTriggerMap.');
31
33
  }
32
34
  }
@@ -1,4 +1,5 @@
1
1
  import { FloatingRootContext } from "../../floating-ui-react/index.js";
2
+ import { FloatingRootStore } from "../../floating-ui-react/components/FloatingRootStore.js";
2
3
  import { TransitionStatus } from "../../internals/useTransitionStatus.js";
3
4
  import { PopupTriggerMap } from "./popupTriggerMap.js";
4
5
  import { HTMLProps } from "../../internals/types.js";
@@ -24,9 +25,14 @@ export type PopupStoreState<Payload> = {
24
25
  */
25
26
  transitionStatus: TransitionStatus;
26
27
  floatingRootContext: FloatingRootContext;
28
+ floatingId: string | undefined;
29
+ /**
30
+ * Number of trigger elements currently registered for this popup.
31
+ */
32
+ triggerCount: number;
27
33
  /**
28
34
  * Whether to prevent unmounting the popup when closed.
29
- * Useful for interactling with JS animation libraries that control unmounting themselves.
35
+ * Useful for interacting with JS animation libraries that control unmounting themselves.
30
36
  */
31
37
  preventUnmountingOnClose: boolean;
32
38
  /**
@@ -67,6 +73,7 @@ export type PopupStoreState<Payload> = {
67
73
  popupProps: HTMLProps;
68
74
  };
69
75
  export declare function createInitialPopupStoreState<Payload>(): PopupStoreState<Payload>;
76
+ export declare function createPopupFloatingRootContext(triggerElements: PopupTriggerMap, floatingId?: string | undefined, nested?: boolean): FloatingRootStore;
70
77
  export type PopupStoreContext<ChangeEventDetails> = {
71
78
  /**
72
79
  * Map of registered trigger elements.
@@ -90,11 +97,13 @@ export declare const popupStoreSelectors: {
90
97
  open: (state: S) => boolean;
91
98
  mounted: (state: S) => boolean;
92
99
  transitionStatus: (state: S) => TransitionStatus;
93
- floatingRootContext: (state: S) => import("../../floating-ui-react/components/FloatingRootStore.js").FloatingRootStore;
100
+ floatingRootContext: (state: S) => FloatingRootStore;
101
+ triggerCount: (state: S) => number;
94
102
  preventUnmountingOnClose: (state: S) => boolean;
95
103
  payload: (state: S) => unknown;
96
104
  activeTriggerId: (state: S) => string | null;
97
105
  activeTriggerElement: (state: S) => Element | null;
106
+ popupId: (state: S) => string | undefined;
98
107
  /**
99
108
  * Whether the trigger with the given ID was used to open the popup.
100
109
  */
@@ -108,6 +117,10 @@ export declare const popupStoreSelectors: {
108
117
  */
109
118
  isMountedByTrigger: (state: S, triggerId: string | undefined) => boolean;
110
119
  triggerProps: (state: S, isActive: boolean) => HTMLProps;
120
+ /**
121
+ * Popup id for the trigger that currently owns the open popup.
122
+ */
123
+ triggerPopupId: (state: S, triggerId: string | undefined) => string | undefined;
111
124
  popupProps: (state: S) => HTMLProps;
112
125
  popupElement: (state: S) => HTMLElement | null;
113
126
  positionerElement: (state: S) => HTMLElement | null;