@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
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import { getWindow } from '@floating-ui/utils/dom';
5
4
  import { addEventListener } from '@base-ui/utils/addEventListener';
6
5
  import { useStableCallback } from '@base-ui/utils/useStableCallback';
6
+ import { getWindow } from '@floating-ui/utils/dom';
7
7
  import { contains, getTarget } from "../utils/element.js";
8
8
  import { isMouseLikePointerType } from "../utils/event.js";
9
9
  function createVirtualElement(domElement, data) {
@@ -68,19 +68,22 @@ function isMouseBasedEvent(event) {
68
68
  * @see https://floating-ui.com/docs/useClientPoint
69
69
  */
70
70
  export function useClientPoint(context, props = {}) {
71
+ const {
72
+ enabled = true,
73
+ axis = 'both'
74
+ } = props;
71
75
  const store = 'rootStore' in context ? context.rootStore : context;
72
76
  const open = store.useState('open');
73
77
  const floating = store.useState('floatingElement');
74
78
  const domReference = store.useState('domReferenceElement');
75
79
  const dataRef = store.context.dataRef;
76
- const {
77
- enabled = true,
78
- axis = 'both'
79
- } = props;
80
80
  const initialRef = React.useRef(false);
81
81
  const cleanupListenerRef = React.useRef(null);
82
82
  const [pointerType, setPointerType] = React.useState();
83
83
  const [reactive, setReactive] = React.useState([]);
84
+ const resetReference = useStableCallback(reference => {
85
+ store.set('positionReference', reference);
86
+ });
84
87
  const setReference = useStableCallback((newX, newY, referenceElement) => {
85
88
  if (initialRef.current) {
86
89
  return;
@@ -107,6 +110,7 @@ export function useClientPoint(context, props = {}) {
107
110
  // If there's no cleanup, there's no listener, but we want to ensure
108
111
  // we add the listener if the cursor landed on the floating element and
109
112
  // then back on the reference (i.e. it's interactive).
113
+ setReference(event.clientX, event.clientY, event.currentTarget);
110
114
  setReactive([]);
111
115
  }
112
116
  });
@@ -116,34 +120,39 @@ export function useClientPoint(context, props = {}) {
116
120
  // devices, this is undesirable because the floating element will move to
117
121
  // the dismissal touch point.
118
122
  const openCheck = isMouseLikePointerType(pointerType) ? floating : open;
119
- const addListener = React.useCallback(() => {
120
- if (!openCheck || !enabled) {
123
+ React.useEffect(() => {
124
+ if (!enabled) {
125
+ resetReference(domReference);
126
+ return undefined;
127
+ }
128
+ if (!openCheck) {
121
129
  return undefined;
122
130
  }
131
+ function cleanupListener() {
132
+ cleanupListenerRef.current?.();
133
+ cleanupListenerRef.current = null;
134
+ }
123
135
  const win = getWindow(floating);
124
136
  function handleMouseMove(event) {
125
137
  const target = getTarget(event);
126
138
  if (!contains(floating, target)) {
127
139
  setReference(event.clientX, event.clientY);
128
140
  } else {
129
- cleanupListenerRef.current?.();
130
- cleanupListenerRef.current = null;
141
+ cleanupListener();
131
142
  }
132
143
  }
133
144
  if (!dataRef.current.openEvent || isMouseBasedEvent(dataRef.current.openEvent)) {
134
- const cleanup = () => {
135
- cleanupListenerRef.current?.();
136
- cleanupListenerRef.current = null;
137
- };
138
145
  cleanupListenerRef.current = addEventListener(win, 'mousemove', handleMouseMove);
139
- return cleanup;
146
+ } else {
147
+ resetReference(domReference);
140
148
  }
141
- store.set('positionReference', domReference);
142
- return undefined;
143
- }, [openCheck, enabled, floating, dataRef, domReference, store, setReference]);
144
- React.useEffect(() => {
145
- return addListener();
146
- }, [addListener, reactive]);
149
+ return cleanupListener;
150
+ }, [openCheck, enabled, floating, dataRef, domReference, store, setReference, resetReference, reactive]);
151
+
152
+ // Clear virtual cursor references when the hook unmounts. Enabled flips are handled above.
153
+ React.useEffect(() => () => {
154
+ store.set('positionReference', null);
155
+ }, [store]);
147
156
  React.useEffect(() => {
148
157
  if (enabled && !floating) {
149
158
  initialRef.current = false;
@@ -71,7 +71,7 @@ export interface UseDismissProps {
71
71
  outsidePress?: boolean | undefined;
72
72
  } | undefined;
73
73
  /**
74
- * External FlatingTree to use when the one provided by context can't be used.
74
+ * External FloatingTree to use when the one provided by context can't be used.
75
75
  */
76
76
  externalTree?: FloatingTreeStore | undefined;
77
77
  }
@@ -1,22 +1,20 @@
1
1
  'use client';
2
2
 
3
+ /* eslint-disable no-underscore-dangle */
3
4
  import * as React from 'react';
4
- import { getComputedStyle, getParentNode, isElement, isHTMLElement, isLastTraversableNode, isShadowRoot, isWebKit } from '@floating-ui/utils/dom';
5
5
  import { addEventListener } from '@base-ui/utils/addEventListener';
6
6
  import { mergeCleanups } from '@base-ui/utils/mergeCleanups';
7
- import { Timeout, useTimeout } from '@base-ui/utils/useTimeout';
8
- import { useStableCallback } from '@base-ui/utils/useStableCallback';
9
7
  import { ownerDocument } from '@base-ui/utils/owner';
10
- import { contains, getTarget, isEventTargetWithin, isRootElement } from "../utils/element.js";
11
- import { isReactEvent } from "../utils/event.js";
12
- import { getNodeChildren } from "../utils/nodes.js";
13
-
14
- /* eslint-disable no-underscore-dangle */
15
-
8
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
9
+ import { Timeout, useTimeout } from '@base-ui/utils/useTimeout';
10
+ import { getComputedStyle, getParentNode, isElement, isHTMLElement, isLastTraversableNode, isShadowRoot, isWebKit } from '@floating-ui/utils/dom';
16
11
  import { useFloatingTree } from "../components/FloatingTree.js";
17
12
  import { createChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
18
13
  import { REASONS } from "../../internals/reasons.js";
19
14
  import { createAttribute } from "../utils/createAttribute.js";
15
+ import { contains, getTarget, isEventTargetWithin, isRootElement } from "../utils/element.js";
16
+ import { isReactEvent } from "../utils/event.js";
17
+ import { getNodeChildren } from "../utils/nodes.js";
20
18
  const bubbleHandlerKeys = {
21
19
  intentional: 'onClick',
22
20
  sloppy: 'onPointerDown'
@@ -36,12 +34,6 @@ export function normalizeProp(normalizable) {
36
34
  * @see https://floating-ui.com/docs/useDismiss
37
35
  */
38
36
  export function useDismiss(context, props = {}) {
39
- const store = 'rootStore' in context ? context.rootStore : context;
40
- const open = store.useState('open');
41
- const floatingElement = store.useState('floatingElement');
42
- const {
43
- dataRef
44
- } = store.context;
45
37
  const {
46
38
  enabled = true,
47
39
  escapeKey = true,
@@ -52,19 +44,27 @@ export function useDismiss(context, props = {}) {
52
44
  bubbles,
53
45
  externalTree
54
46
  } = props;
47
+ const store = 'rootStore' in context ? context.rootStore : context;
48
+ const open = store.useState('open');
49
+ const floatingElement = store.useState('floatingElement');
50
+ const {
51
+ dataRef
52
+ } = store.context;
55
53
  const tree = useFloatingTree(externalTree);
56
54
  const outsidePressFn = useStableCallback(typeof outsidePressProp === 'function' ? outsidePressProp : () => false);
57
55
  const outsidePress = typeof outsidePressProp === 'function' ? outsidePressFn : outsidePressProp;
58
56
  const outsidePressEnabled = outsidePress !== false;
59
57
  const getOutsidePressEventProp = useStableCallback(() => outsidePressEvent);
60
- const pressStartedInsideRef = React.useRef(false);
61
- const pressStartPreventedRef = React.useRef(false);
62
- // Ignore only the very next outside click after dragging from inside to outside.
63
- const suppressNextOutsideClickRef = React.useRef(false);
64
58
  const {
65
59
  escapeKey: escapeKeyBubbles,
66
60
  outsidePress: outsidePressBubbles
67
61
  } = normalizeProp(bubbles);
62
+ const pressStartedInsideRef = React.useRef(false);
63
+ const pressStartPreventedRef = React.useRef(false);
64
+ // Ignore only the very next outside click after dragging from inside to outside.
65
+ const suppressNextOutsideClickRef = React.useRef(false);
66
+ const isComposingRef = React.useRef(false);
67
+ const currentPointerTypeRef = React.useRef('');
68
68
  const touchStateRef = React.useRef(null);
69
69
  const cancelDismissOnEndTimeout = useTimeout();
70
70
  const clearInsideReactTreeTimeout = useTimeout();
@@ -72,9 +72,20 @@ export function useDismiss(context, props = {}) {
72
72
  clearInsideReactTreeTimeout.clear();
73
73
  dataRef.current.insideReactTree = false;
74
74
  });
75
- const isComposingRef = React.useRef(false);
76
- const currentPointerTypeRef = React.useRef('');
77
- const isReferencePressEnabled = useStableCallback(referencePress);
75
+ const hasBlockingChild = useStableCallback(bubbleKey => {
76
+ const nodeId = dataRef.current.floatingContext?.nodeId;
77
+ const children = tree ? getNodeChildren(tree.nodesRef.current, nodeId) : [];
78
+ return children.some(child => child.context?.open && !child.context.dataRef.current[bubbleKey]);
79
+ });
80
+ const isEventWithinOwnElements = useStableCallback(event => {
81
+ return isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'));
82
+ });
83
+ const closeOnReferencePress = useStableCallback(event => {
84
+ if (!referencePress()) {
85
+ return;
86
+ }
87
+ store.setOpen(false, createChangeEventDetails(REASONS.triggerPress, event.nativeEvent));
88
+ });
78
89
  const closeOnEscapeKeyDown = useStableCallback(event => {
79
90
  if (!open || !enabled || !escapeKey || event.key !== 'Escape') {
80
91
  return;
@@ -85,24 +96,15 @@ export function useDismiss(context, props = {}) {
85
96
  if (isComposingRef.current) {
86
97
  return;
87
98
  }
88
- const nodeId = dataRef.current.floatingContext?.nodeId;
89
- const children = tree ? getNodeChildren(tree.nodesRef.current, nodeId) : [];
90
- if (!escapeKeyBubbles) {
91
- if (children.length > 0) {
92
- let shouldDismiss = true;
93
- children.forEach(child => {
94
- if (child.context?.open && !child.context.dataRef.current.__escapeKeyBubbles) {
95
- shouldDismiss = false;
96
- }
97
- });
98
- if (!shouldDismiss) {
99
- return;
100
- }
101
- }
99
+ if (!escapeKeyBubbles && hasBlockingChild('__escapeKeyBubbles')) {
100
+ return;
102
101
  }
103
102
  const native = isReactEvent(event) ? event.nativeEvent : event;
104
103
  const eventDetails = createChangeEventDetails(REASONS.escapeKey, native);
105
104
  store.setOpen(false, eventDetails);
105
+ if (!eventDetails.isCanceled) {
106
+ event.preventDefault();
107
+ }
106
108
  if (!escapeKeyBubbles && !eventDetails.isPropagationAllowed) {
107
109
  event.stopPropagation();
108
110
  }
@@ -111,6 +113,33 @@ export function useDismiss(context, props = {}) {
111
113
  dataRef.current.insideReactTree = true;
112
114
  clearInsideReactTreeTimeout.start(0, clearInsideReactTree);
113
115
  });
116
+ const markPressStartedInsideReactTree = useStableCallback(event => {
117
+ if (!open || !enabled || event.button !== 0) {
118
+ return;
119
+ }
120
+ const target = getTarget(event.nativeEvent);
121
+
122
+ // Only treat presses that start within the floating DOM subtree as inside.
123
+ // This avoids suppressing parent dismissal when interacting with nested portals.
124
+ if (!contains(store.select('floatingElement'), target)) {
125
+ return;
126
+ }
127
+ if (!pressStartedInsideRef.current) {
128
+ pressStartedInsideRef.current = true;
129
+ pressStartPreventedRef.current = false;
130
+ }
131
+ });
132
+ const markInsidePressStartPrevented = useStableCallback(event => {
133
+ if (!open || !enabled) {
134
+ return;
135
+ }
136
+ if (!(event.defaultPrevented || event.nativeEvent.defaultPrevented)) {
137
+ return;
138
+ }
139
+ if (pressStartedInsideRef.current) {
140
+ pressStartPreventedRef.current = true;
141
+ }
142
+ });
114
143
  React.useEffect(() => {
115
144
  if (!open || !enabled) {
116
145
  return undefined;
@@ -163,10 +192,16 @@ export function useDismiss(context, props = {}) {
163
192
  function isEventWithinFloatingTree(event) {
164
193
  const nodeId = dataRef.current.floatingContext?.nodeId;
165
194
  const targetIsInsideChildren = tree && getNodeChildren(tree.nodesRef.current, nodeId).some(node => isEventTargetWithin(event, node.context?.elements.floating));
166
- return isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement')) || targetIsInsideChildren;
195
+ return isEventWithinOwnElements(event) || targetIsInsideChildren;
167
196
  }
168
197
  function closeOnPressOutside(event) {
169
198
  if (shouldIgnoreEvent(event)) {
199
+ // A new press began outside the floating element and its trigger. Clear any
200
+ // leftover drag-out suppression so this press's eventual click can dismiss.
201
+ if (event.type !== 'click' && !isEventWithinOwnElements(event)) {
202
+ preventedPressSuppressionTimeout.clear();
203
+ suppressNextOutsideClickRef.current = false;
204
+ }
170
205
  clearInsideReactTree();
171
206
  return;
172
207
  }
@@ -242,30 +277,20 @@ export function useDismiss(context, props = {}) {
242
277
  if (typeof outsidePress === 'function' && !outsidePress(event)) {
243
278
  return;
244
279
  }
245
- const nodeId = dataRef.current.floatingContext?.nodeId;
246
- const children = tree ? getNodeChildren(tree.nodesRef.current, nodeId) : [];
247
- if (children.length > 0) {
248
- let shouldDismiss = true;
249
- children.forEach(child => {
250
- if (child.context?.open && !child.context.dataRef.current.__outsidePressBubbles) {
251
- shouldDismiss = false;
252
- }
253
- });
254
- if (!shouldDismiss) {
255
- return;
256
- }
280
+ if (hasBlockingChild('__outsidePressBubbles')) {
281
+ return;
257
282
  }
258
283
  store.setOpen(false, createChangeEventDetails(REASONS.outsidePress, event));
259
284
  clearInsideReactTree();
260
285
  }
261
286
  function handlePointerDown(event) {
262
- if (getOutsidePressEvent() !== 'sloppy' || event.pointerType === 'touch' || !store.select('open') || !enabled || isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'))) {
287
+ if (getOutsidePressEvent() !== 'sloppy' || event.pointerType === 'touch' || !store.select('open') || !enabled || isEventWithinOwnElements(event)) {
263
288
  return;
264
289
  }
265
290
  closeOnPressOutside(event);
266
291
  }
267
292
  function handleTouchStart(event) {
268
- if (getOutsidePressEvent() !== 'sloppy' || !store.select('open') || !enabled || isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'))) {
293
+ if (getOutsidePressEvent() !== 'sloppy' || !store.select('open') || !enabled || isEventWithinOwnElements(event)) {
269
294
  return;
270
295
  }
271
296
  const touch = event.touches[0];
@@ -352,7 +377,7 @@ export function useDismiss(context, props = {}) {
352
377
  clearInsideReactTree();
353
378
  }
354
379
  function handleTouchMove(event) {
355
- if (getOutsidePressEvent() !== 'sloppy' || !touchStateRef.current || isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'))) {
380
+ if (getOutsidePressEvent() !== 'sloppy' || !touchStateRef.current || isEventWithinOwnElements(event)) {
356
381
  return;
357
382
  }
358
383
  const touch = event.touches[0];
@@ -375,7 +400,7 @@ export function useDismiss(context, props = {}) {
375
400
  addTargetEventListenerOnce(event, handleTouchMove);
376
401
  }
377
402
  function handleTouchEnd(event) {
378
- if (getOutsidePressEvent() !== 'sloppy' || !touchStateRef.current || isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'))) {
403
+ if (getOutsidePressEvent() !== 'sloppy' || !touchStateRef.current || isEventWithinOwnElements(event)) {
379
404
  return;
380
405
  }
381
406
  if (touchStateRef.current.dismissOnTouchEnd) {
@@ -396,51 +421,15 @@ export function useDismiss(context, props = {}) {
396
421
  resetPressStartState();
397
422
  suppressNextOutsideClickRef.current = false;
398
423
  };
399
- }, [dataRef, floatingElement, escapeKey, outsidePressEnabled, outsidePress, open, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, clearInsideReactTree, getOutsidePressEventProp, tree, store, cancelDismissOnEndTimeout]);
424
+ }, [dataRef, floatingElement, escapeKey, outsidePressEnabled, outsidePress, open, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, clearInsideReactTree, getOutsidePressEventProp, hasBlockingChild, isEventWithinOwnElements, tree, store, cancelDismissOnEndTimeout]);
400
425
  React.useEffect(clearInsideReactTree, [outsidePress, clearInsideReactTree]);
401
426
  const reference = React.useMemo(() => ({
402
427
  onKeyDown: closeOnEscapeKeyDown,
403
- [bubbleHandlerKeys[referencePressEvent]]: event => {
404
- if (!isReferencePressEnabled()) {
405
- return;
406
- }
407
- store.setOpen(false, createChangeEventDetails(REASONS.triggerPress, event.nativeEvent));
408
- },
428
+ [bubbleHandlerKeys[referencePressEvent]]: closeOnReferencePress,
409
429
  ...(referencePressEvent !== 'intentional' && {
410
- onClick(event) {
411
- if (!isReferencePressEnabled()) {
412
- return;
413
- }
414
- store.setOpen(false, createChangeEventDetails(REASONS.triggerPress, event.nativeEvent));
415
- }
430
+ onClick: closeOnReferencePress
416
431
  })
417
- }), [closeOnEscapeKeyDown, store, referencePressEvent, isReferencePressEnabled]);
418
- const markPressStartedInsideReactTree = useStableCallback(event => {
419
- if (!open || !enabled || event.button !== 0) {
420
- return;
421
- }
422
- const target = getTarget(event.nativeEvent);
423
- // Only treat presses that start within the floating DOM subtree as inside.
424
- // This avoids suppressing parent dismissal when interacting with nested portals.
425
- if (!contains(store.select('floatingElement'), target)) {
426
- return;
427
- }
428
- if (!pressStartedInsideRef.current) {
429
- pressStartedInsideRef.current = true;
430
- pressStartPreventedRef.current = false;
431
- }
432
- });
433
- const markInsidePressStartPrevented = useStableCallback(event => {
434
- if (!open || !enabled) {
435
- return;
436
- }
437
- if (!(event.defaultPrevented || event.nativeEvent.defaultPrevented)) {
438
- return;
439
- }
440
- if (pressStartedInsideRef.current) {
441
- pressStartPreventedRef.current = true;
442
- }
443
- });
432
+ }), [closeOnEscapeKeyDown, closeOnReferencePress, referencePressEvent]);
444
433
  const floating = React.useMemo(() => ({
445
434
  onKeyDown: closeOnEscapeKeyDown,
446
435
  // `onMouseDown` may be blocked if `event.preventDefault()` is called in
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
+ import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
4
5
  import { useFloating as usePosition } from '@floating-ui/react-dom';
5
6
  import { isElement } from '@floating-ui/utils/dom';
6
- import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
7
7
  import { useFloatingTree } from "../components/FloatingTree.js";
8
8
  import { useFloatingRootContext } from "./useFloatingRootContext.js";
9
+
9
10
  /**
10
11
  * Provides data to position a floating element and context to add interactions.
11
12
  * @see https://floating-ui.com/docs/useFloating
@@ -15,30 +16,37 @@ export function useFloating(options = {}) {
15
16
  nodeId,
16
17
  externalTree
17
18
  } = options;
18
- const internalRootStore = useFloatingRootContext(options);
19
- const rootContext = options.rootContext || internalRootStore;
20
- const rootContextElements = {
21
- reference: rootContext.useState('referenceElement'),
22
- floating: rootContext.useState('floatingElement'),
23
- domReference: rootContext.useState('domReferenceElement')
24
- };
19
+ const internalStore = useFloatingRootContext(options);
20
+ const store = options.rootContext || internalStore;
21
+ const referenceElement = store.useState('referenceElement');
22
+ const floatingElement = store.useState('floatingElement');
23
+ const domReferenceElement = store.useState('domReferenceElement');
24
+ const open = store.useState('open');
25
+ const floatingId = store.useState('floatingId');
25
26
  const [positionReference, setPositionReferenceRaw] = React.useState(null);
27
+ const [localDomReference, setLocalDomReference] = React.useState(undefined);
28
+ const [localFloatingElement, setLocalFloatingElement] = React.useState(undefined);
26
29
  const domReferenceRef = React.useRef(null);
27
30
  const tree = useFloatingTree(externalTree);
28
- useIsoLayoutEffect(() => {
29
- if (rootContextElements.domReference) {
30
- domReferenceRef.current = rootContextElements.domReference;
31
- }
32
- }, [rootContextElements.domReference]);
31
+ const storeElements = React.useMemo(() => ({
32
+ reference: referenceElement,
33
+ floating: floatingElement,
34
+ domReference: domReferenceElement
35
+ }), [referenceElement, floatingElement, domReferenceElement]);
33
36
  const position = usePosition({
34
37
  ...options,
35
38
  elements: {
36
- ...rootContextElements,
39
+ ...storeElements,
37
40
  ...(positionReference && {
38
41
  reference: positionReference
39
42
  })
40
43
  }
41
44
  });
45
+ const localDomReferenceElement = isElement(localDomReference) ? localDomReference : null;
46
+ const syncedFloatingElement = localFloatingElement === undefined ? store.state.floatingElement : localFloatingElement;
47
+ store.useSyncedValue('referenceElement', localDomReference ?? null);
48
+ store.useSyncedValue('domReferenceElement', localDomReference === undefined ? domReferenceElement : localDomReferenceElement);
49
+ store.useSyncedValue('floatingElement', syncedFloatingElement);
42
50
  const setPositionReference = React.useCallback(node => {
43
51
  const computedPositionReference = isElement(node) ? {
44
52
  getBoundingClientRect: () => node.getBoundingClientRect(),
@@ -50,12 +58,6 @@ export function useFloating(options = {}) {
50
58
  setPositionReferenceRaw(computedPositionReference);
51
59
  position.refs.setReference(computedPositionReference);
52
60
  }, [position.refs]);
53
- const [localDomReference, setLocalDomReference] = React.useState(undefined);
54
- const [localFloatingElement, setLocalFloatingElement] = React.useState(null);
55
- rootContext.useSyncedValue('referenceElement', localDomReference ?? null);
56
- const localDomReferenceElement = isElement(localDomReference) ? localDomReference : null;
57
- rootContext.useSyncedValue('domReferenceElement', localDomReference === undefined ? rootContextElements.domReference : localDomReferenceElement);
58
- rootContext.useSyncedValue('floatingElement', localFloatingElement);
59
61
  const setReference = React.useCallback(node => {
60
62
  if (isElement(node) || node === null) {
61
63
  domReferenceRef.current = node;
@@ -85,24 +87,27 @@ export function useFloating(options = {}) {
85
87
  }), [position.refs, setReference, setFloating, setPositionReference]);
86
88
  const elements = React.useMemo(() => ({
87
89
  ...position.elements,
88
- domReference: rootContextElements.domReference
89
- }), [position.elements, rootContextElements.domReference]);
90
- const open = rootContext.useState('open');
91
- const floatingId = rootContext.useState('floatingId');
90
+ domReference: domReferenceElement
91
+ }), [position.elements, domReferenceElement]);
92
92
  const context = React.useMemo(() => ({
93
93
  ...position,
94
- dataRef: rootContext.context.dataRef,
94
+ dataRef: store.context.dataRef,
95
95
  open,
96
- onOpenChange: rootContext.setOpen,
97
- events: rootContext.context.events,
96
+ onOpenChange: store.setOpen,
97
+ events: store.context.events,
98
98
  floatingId,
99
99
  refs,
100
100
  elements,
101
101
  nodeId,
102
- rootStore: rootContext
103
- }), [position, refs, elements, nodeId, rootContext, open, floatingId]);
102
+ rootStore: store
103
+ }), [position, refs, elements, nodeId, store, open, floatingId]);
104
+ useIsoLayoutEffect(() => {
105
+ if (domReferenceElement) {
106
+ domReferenceRef.current = domReferenceElement;
107
+ }
108
+ }, [domReferenceElement]);
104
109
  useIsoLayoutEffect(() => {
105
- rootContext.context.dataRef.current.floatingContext = context;
110
+ store.context.dataRef.current.floatingContext = context;
106
111
  const node = tree?.nodesRef.current.find(n => n.id === nodeId);
107
112
  if (node) {
108
113
  node.context = context;
@@ -113,6 +118,6 @@ export function useFloating(options = {}) {
113
118
  context,
114
119
  refs,
115
120
  elements,
116
- rootStore: rootContext
117
- }), [position, refs, elements, context, rootContext]);
121
+ rootStore: store
122
+ }), [position, refs, elements, context, store]);
118
123
  }
@@ -1,6 +1,6 @@
1
- import type { ReferenceType } from "../types.js";
2
1
  import type { BaseUIChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
3
2
  import { FloatingRootStore } from "../components/FloatingRootStore.js";
3
+ import type { ReferenceType } from "../types.js";
4
4
  export interface UseFloatingRootContextOptions {
5
5
  open?: boolean | undefined;
6
6
  onOpenChange?(open: boolean, eventDetails: BaseUIChangeEventDetails<string>): void;
@@ -2,11 +2,11 @@
2
2
 
3
3
  import { isElement } from '@floating-ui/utils/dom';
4
4
  import { useId } from '@base-ui/utils/useId';
5
- import { useRefWithInit } from '@base-ui/utils/useRefWithInit';
6
5
  import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
6
+ import { useRefWithInit } from '@base-ui/utils/useRefWithInit';
7
+ import { PopupTriggerMap } from "../../utils/popups/index.js";
7
8
  import { useFloatingParentNodeId } from "../components/FloatingTree.js";
8
9
  import { FloatingRootStore } from "../components/FloatingRootStore.js";
9
- import { PopupTriggerMap } from "../../utils/popups/index.js";
10
10
  export function useFloatingRootContext(options) {
11
11
  const {
12
12
  open = false,