@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,19 +2,19 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import * as ReactDOM from 'react-dom';
5
- import { isElement } from '@floating-ui/utils/dom';
6
5
  import { addEventListener } from '@base-ui/utils/addEventListener';
7
6
  import { mergeCleanups } from '@base-ui/utils/mergeCleanups';
8
- import { useValueAsRef } from '@base-ui/utils/useValueAsRef';
9
- import { useStableCallback } from '@base-ui/utils/useStableCallback';
10
7
  import { ownerDocument } from '@base-ui/utils/owner';
11
- import { contains, getTarget, isTargetInsideEnabledTrigger } from "../utils/element.js";
12
- import { isMouseLikePointerType } from "../utils/event.js";
8
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
9
+ import { useValueAsRef } from '@base-ui/utils/useValueAsRef';
10
+ import { isElement } from '@floating-ui/utils/dom';
13
11
  import { createChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
14
12
  import { REASONS } from "../../internals/reasons.js";
15
13
  import { useFloatingTree } from "../components/FloatingTree.js";
14
+ import { contains, getTarget } from "../utils/element.js";
15
+ import { isMouseLikePointerType } from "../utils/event.js";
16
16
  import { applySafePolygonPointerEventsMutation, clearSafePolygonPointerEventsMutation, useHoverInteractionSharedState } from "./useHoverInteractionSharedState.js";
17
- import { getDelay, getRestMs, isClickLikeOpenEvent as isClickLikeOpenEventShared } from "./useHoverShared.js";
17
+ import { getDelay, getRestMs, isClickLikeOpenEvent as isClickLikeOpenEventShared, isInsideEnabledTrigger } from "./useHoverShared.js";
18
18
  const EMPTY_REF = {
19
19
  current: null
20
20
  };
@@ -24,11 +24,6 @@ const EMPTY_REF = {
24
24
  * elements.
25
25
  */
26
26
  export function useHoverReferenceInteraction(context, props = {}) {
27
- const store = 'rootStore' in context ? context.rootStore : context;
28
- const {
29
- dataRef,
30
- events
31
- } = store.context;
32
27
  const {
33
28
  enabled = true,
34
29
  delay = 0,
@@ -40,8 +35,14 @@ export function useHoverReferenceInteraction(context, props = {}) {
40
35
  externalTree,
41
36
  isActiveTrigger = true,
42
37
  getHandleCloseContext,
43
- isClosing
38
+ isClosing,
39
+ shouldOpen: shouldOpenProp
44
40
  } = props;
41
+ const store = 'rootStore' in context ? context.rootStore : context;
42
+ const {
43
+ dataRef,
44
+ events
45
+ } = store.context;
45
46
  const tree = useFloatingTree(externalTree);
46
47
  const instance = useHoverInteractionSharedState(store);
47
48
  const isHoverCloseActiveRef = React.useRef(false);
@@ -49,16 +50,13 @@ export function useHoverReferenceInteraction(context, props = {}) {
49
50
  const delayRef = useValueAsRef(delay);
50
51
  const restMsRef = useValueAsRef(restMs);
51
52
  const enabledRef = useValueAsRef(enabled);
53
+ const shouldOpenRef = useValueAsRef(shouldOpenProp);
52
54
  const isClosingRef = useValueAsRef(isClosing);
53
- if (isActiveTrigger) {
54
- // eslint-disable-next-line no-underscore-dangle
55
- instance.handleCloseOptions = handleCloseRef.current?.__options;
56
- }
57
55
  const isClickLikeOpenEvent = useStableCallback(() => {
58
56
  return isClickLikeOpenEventShared(dataRef.current.openEvent?.type, instance.interactedInside);
59
57
  });
60
- const isRelatedTargetInsideEnabledTrigger = useStableCallback(target => {
61
- return isTargetInsideEnabledTrigger(target, store.context.triggerElements);
58
+ const checkShouldOpen = useStableCallback(() => {
59
+ return shouldOpenRef.current?.() !== false;
62
60
  });
63
61
  const isOverInactiveTrigger = useStableCallback((currentDomReference, currentTarget, target) => {
64
62
  const allTriggers = store.context.triggerElements;
@@ -75,19 +73,6 @@ export function useHoverReferenceInteraction(context, props = {}) {
75
73
  const targetElement = target;
76
74
  return allTriggers.hasMatchingElement(trigger => contains(trigger, targetElement)) && (!currentDomReference || !contains(currentDomReference, targetElement));
77
75
  });
78
- const closeWithDelay = useStableCallback((event, runElseBranch = true) => {
79
- const closeDelay = getDelay(delayRef.current, 'close', instance.pointerType);
80
- if (closeDelay) {
81
- instance.openChangeTimeout.start(closeDelay, () => {
82
- store.setOpen(false, createChangeEventDetails(REASONS.triggerHover, event));
83
- tree?.events.emit('floating.closed', event);
84
- });
85
- } else if (runElseBranch) {
86
- instance.openChangeTimeout.clear();
87
- store.setOpen(false, createChangeEventDetails(REASONS.triggerHover, event));
88
- tree?.events.emit('floating.closed', event);
89
- }
90
- });
91
76
  const cleanupMouseMoveHandler = useStableCallback(() => {
92
77
  if (!instance.handler) {
93
78
  return;
@@ -99,6 +84,10 @@ export function useHoverReferenceInteraction(context, props = {}) {
99
84
  const clearPointerEvents = useStableCallback(() => {
100
85
  clearSafePolygonPointerEventsMutation(instance);
101
86
  });
87
+ if (isActiveTrigger) {
88
+ // eslint-disable-next-line no-underscore-dangle
89
+ instance.handleCloseOptions = handleCloseRef.current?.__options;
90
+ }
102
91
  React.useEffect(() => cleanupMouseMoveHandler, [cleanupMouseMoveHandler]);
103
92
 
104
93
  // When closing before opening, clear the delay timeouts to cancel it
@@ -128,6 +117,19 @@ export function useHoverReferenceInteraction(context, props = {}) {
128
117
  if (!enabled) {
129
118
  return undefined;
130
119
  }
120
+ function closeWithDelay(event, runElseBranch = true) {
121
+ const closeDelay = getDelay(delayRef.current, 'close', instance.pointerType);
122
+ if (closeDelay) {
123
+ instance.openChangeTimeout.start(closeDelay, () => {
124
+ store.setOpen(false, createChangeEventDetails(REASONS.triggerHover, event));
125
+ tree?.events.emit('floating.closed', event);
126
+ });
127
+ } else if (runElseBranch) {
128
+ instance.openChangeTimeout.clear();
129
+ store.setOpen(false, createChangeEventDetails(REASONS.triggerHover, event));
130
+ tree?.events.emit('floating.closed', event);
131
+ }
132
+ }
131
133
  const trigger = triggerElementRef.current ?? (isActiveTrigger ? store.select('domReferenceElement') : null);
132
134
  if (!isElement(trigger)) {
133
135
  return undefined;
@@ -175,7 +177,9 @@ export function useHoverReferenceInteraction(context, props = {}) {
175
177
  // Open immediately when moving between triggers while open, or during
176
178
  // a hover-driven close transition (including same-trigger re-entry).
177
179
  if (shouldOpenImmediately) {
178
- store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, event, triggerNode));
180
+ if (checkShouldOpen()) {
181
+ store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, event, triggerNode));
182
+ }
179
183
  return;
180
184
  }
181
185
  if (isRestOnlyDelay) {
@@ -183,12 +187,14 @@ export function useHoverReferenceInteraction(context, props = {}) {
183
187
  }
184
188
  if (openDelay) {
185
189
  instance.openChangeTimeout.start(openDelay, () => {
186
- if (shouldOpen) {
190
+ if (shouldOpen && checkShouldOpen()) {
187
191
  store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, event, triggerNode));
188
192
  }
189
193
  });
190
194
  } else if (shouldOpen) {
191
- store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, event, triggerNode));
195
+ if (checkShouldOpen()) {
196
+ store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, event, triggerNode));
197
+ }
192
198
  }
193
199
  }
194
200
  function onMouseLeave(event) {
@@ -202,8 +208,7 @@ export function useHoverReferenceInteraction(context, props = {}) {
202
208
  instance.restTimeout.clear();
203
209
  instance.restTimeoutPending = false;
204
210
  const handleCloseContextBase = dataRef.current.floatingContext ?? getHandleCloseContext?.();
205
- const ignoreRelatedTargetTrigger = isRelatedTargetInsideEnabledTrigger(event.relatedTarget);
206
- if (ignoreRelatedTargetTrigger) {
211
+ if (isInsideEnabledTrigger(event.relatedTarget, store.context.triggerElements)) {
207
212
  return;
208
213
  }
209
214
  if (handleCloseRef.current && handleCloseContextBase) {
@@ -239,7 +244,7 @@ export function useHoverReferenceInteraction(context, props = {}) {
239
244
  }), addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave));
240
245
  }
241
246
  return mergeCleanups(addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave));
242
- }, [cleanupMouseMoveHandler, clearPointerEvents, dataRef, delayRef, closeWithDelay, store, enabled, handleCloseRef, instance, isActiveTrigger, isOverInactiveTrigger, isClickLikeOpenEvent, isRelatedTargetInsideEnabledTrigger, mouseOnly, move, restMsRef, triggerElementRef, tree, enabledRef, getHandleCloseContext, isClosingRef]);
247
+ }, [cleanupMouseMoveHandler, clearPointerEvents, dataRef, delayRef, store, enabled, handleCloseRef, instance, isActiveTrigger, isOverInactiveTrigger, isClickLikeOpenEvent, mouseOnly, move, restMsRef, triggerElementRef, tree, enabledRef, getHandleCloseContext, isClosingRef, checkShouldOpen]);
243
248
  return React.useMemo(() => {
244
249
  if (!enabled) {
245
250
  return undefined;
@@ -289,7 +294,7 @@ export function useHoverReferenceInteraction(context, props = {}) {
289
294
  return;
290
295
  }
291
296
  const latestOpen = store.select('open');
292
- if (!instance.blockMouseMove && (!latestOpen || isOverInactive)) {
297
+ if (!instance.blockMouseMove && (!latestOpen || isOverInactive) && checkShouldOpen()) {
293
298
  store.setOpen(true, createChangeEventDetails(REASONS.triggerHover, nativeEvent, trigger));
294
299
  }
295
300
  }
@@ -305,5 +310,5 @@ export function useHoverReferenceInteraction(context, props = {}) {
305
310
  }
306
311
  }
307
312
  };
308
- }, [enabled, instance, isClickLikeOpenEvent, isOverInactiveTrigger, mouseOnly, store, restMsRef]);
313
+ }, [enabled, instance, isClickLikeOpenEvent, isOverInactiveTrigger, mouseOnly, store, restMsRef, checkShouldOpen]);
309
314
  }
@@ -1,4 +1,5 @@
1
1
  import type { ExtendedElements, FloatingTreeType, Placement } from "../types.js";
2
+ export { isTargetInsideEnabledTrigger as isInsideEnabledTrigger } from "../utils/element.js";
2
3
  export interface HandleCloseOptions {
3
4
  blockPointerEvents?: boolean | undefined;
4
5
  getScope?: (() => HTMLElement | SVGSVGElement | null) | undefined;
@@ -25,4 +26,4 @@ type HoverDelay = number | Partial<{
25
26
  export declare function getDelay(value: HoverDelay | (() => HoverDelay) | undefined, prop: 'open' | 'close', pointerType?: PointerEvent['pointerType']): number | undefined;
26
27
  export declare function getRestMs(value: number | (() => number)): number;
27
28
  export declare function isClickLikeOpenEvent(openEventType: string | undefined, interactedInside: boolean): boolean;
28
- export {};
29
+ export declare function isHoverOpenEvent(openEventType: string | undefined): boolean | undefined;
@@ -1,4 +1,5 @@
1
1
  import { isMouseLikePointerType } from "../utils/event.js";
2
+ export { isTargetInsideEnabledTrigger as isInsideEnabledTrigger } from "../utils/element.js";
2
3
  function resolveValue(value, pointerType) {
3
4
  if (pointerType != null && !isMouseLikePointerType(pointerType)) {
4
5
  return 0;
@@ -23,4 +24,7 @@ export function getRestMs(value) {
23
24
  }
24
25
  export function isClickLikeOpenEvent(openEventType, interactedInside) {
25
26
  return interactedInside || openEventType === 'click' || openEventType === 'mousedown';
27
+ }
28
+ export function isHoverOpenEvent(openEventType) {
29
+ return openEventType?.includes('mouse') && openEventType !== 'mousedown';
26
30
  }
@@ -99,8 +99,6 @@ export interface UseListNavigationProps {
99
99
  * (such as an input), but allow arrow keys to navigate list items.
100
100
  * This is common in autocomplete listbox components.
101
101
  * Your virtually-focused list items must have a unique `id` set on them.
102
- * If you're using a component role with the `useRole()` Hook, then an `id` is
103
- * generated automatically.
104
102
  * @default false
105
103
  */
106
104
  virtual?: boolean | undefined;
@@ -128,7 +126,7 @@ export interface UseListNavigationProps {
128
126
  */
129
127
  resetOnPointerLeave?: boolean | undefined;
130
128
  /**
131
- * External FlatingTree to use when the one provided by context can't be used.
129
+ * External FloatingTree to use when the one provided by context can't be used.
132
130
  */
133
131
  externalTree?: FloatingTreeStore | undefined;
134
132
  }
@@ -1,19 +1,20 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import { isHTMLElement } from '@floating-ui/utils/dom';
5
- import { useValueAsRef } from '@base-ui/utils/useValueAsRef';
6
- import { useStableCallback } from '@base-ui/utils/useStableCallback';
4
+ import { useAnimationFrame } from '@base-ui/utils/useAnimationFrame';
7
5
  import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
8
6
  import { ownerDocument } from '@base-ui/utils/owner';
9
- import { activeElement, contains, getTarget, isTypeableCombobox, getFloatingFocusElement } from "../utils/element.js";
10
- import { isVirtualClick, isVirtualPointerEvent, stopEvent } from "../utils/event.js";
11
- import { isIndexOutOfListBounds, getMinListIndex, getMaxListIndex, getGridNavigatedIndex, isListIndexDisabled, createGridCellMap, getGridCellIndices, getGridCellIndexOfCorner, findNonDisabledListIndex } from "../utils/composite.js";
12
- import { useFloatingParentNodeId, useFloatingTree } from "../components/FloatingTree.js";
7
+ import { useStableCallback } from '@base-ui/utils/useStableCallback';
8
+ import { useValueAsRef } from '@base-ui/utils/useValueAsRef';
9
+ import { isHTMLElement } from '@floating-ui/utils/dom';
13
10
  import { createChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
14
11
  import { REASONS } from "../../internals/reasons.js";
12
+ import { useFloatingParentNodeId, useFloatingTree } from "../components/FloatingTree.js";
13
+ import { createGridCellMap, findNonDisabledListIndex, getGridCellIndexOfCorner, getGridCellIndices, getGridNavigatedIndex, getMaxListIndex, getMinListIndex, isIndexOutOfListBounds, isListIndexDisabled } from "../utils/composite.js";
14
+ import { ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP } from "../utils/constants.js";
15
+ import { activeElement, contains, getFloatingFocusElement, getTarget, isTypeableCombobox } from "../utils/element.js";
15
16
  import { enqueueFocus } from "../utils/enqueueFocus.js";
16
- import { ARROW_UP, ARROW_DOWN, ARROW_RIGHT, ARROW_LEFT } from "../utils/constants.js";
17
+ import { isVirtualClick, isVirtualPointerEvent, stopEvent } from "../utils/event.js";
17
18
  export const ESCAPE = 'Escape';
18
19
  function doSwitch(orientation, vertical, horizontal) {
19
20
  switch (orientation) {
@@ -54,11 +55,6 @@ function isCrossOrientationCloseKey(key, orientation, rtl, cols) {
54
55
  * @see https://floating-ui.com/docs/useListNavigation
55
56
  */
56
57
  export function useListNavigation(context, props) {
57
- const store = 'rootStore' in context ? context.rootStore : context;
58
- const open = store.useState('open');
59
- const floatingElement = store.useState('floatingElement');
60
- const domReferenceElement = store.useState('domReferenceElement');
61
- const dataRef = store.context.dataRef;
62
58
  const {
63
59
  listRef,
64
60
  activeIndex,
@@ -94,14 +90,16 @@ export function useListNavigation(context, props) {
94
90
  console.warn('In grid list navigation mode (`cols` > 1), the `orientation` should', 'be either "horizontal" or "both".');
95
91
  }
96
92
  }
93
+ const store = 'rootStore' in context ? context.rootStore : context;
94
+ const open = store.useState('open');
95
+ const floatingElement = store.useState('floatingElement');
96
+ const domReferenceElement = store.useState('domReferenceElement');
97
+ const dataRef = store.context.dataRef;
97
98
  const floatingFocusElement = getFloatingFocusElement(floatingElement);
99
+ const typeableComboboxReference = isTypeableCombobox(domReferenceElement);
98
100
  const floatingFocusElementRef = useValueAsRef(floatingFocusElement);
99
101
  const parentId = useFloatingParentNodeId();
100
102
  const tree = useFloatingTree(externalTree);
101
- useIsoLayoutEffect(() => {
102
- dataRef.current.orientation = orientation;
103
- }, [dataRef, orientation]);
104
- const typeableComboboxReference = isTypeableCombobox(domReferenceElement);
105
103
  const focusItemOnOpenRef = React.useRef(focusItemOnOpen);
106
104
  const indexRef = React.useRef(selectedIndex ?? -1);
107
105
  const keyRef = React.useRef(null);
@@ -119,6 +117,8 @@ export function useListNavigation(context, props) {
119
117
  const latestOpenRef = useValueAsRef(open);
120
118
  const selectedIndexRef = useValueAsRef(selectedIndex);
121
119
  const resetOnPointerLeaveRef = useValueAsRef(resetOnPointerLeave);
120
+ const focusFrame = useAnimationFrame();
121
+ const waitForListPopulatedFrame = useAnimationFrame();
122
122
  const focusItem = useStableCallback(() => {
123
123
  function runFocus(item) {
124
124
  if (virtual) {
@@ -135,7 +135,7 @@ export function useListNavigation(context, props) {
135
135
  if (initialItem) {
136
136
  runFocus(initialItem);
137
137
  }
138
- const scheduler = forceSyncFocusRef.current ? v => v() : requestAnimationFrame;
138
+ const scheduler = forceSyncFocusRef.current ? callback => callback() : callback => focusFrame.request(callback);
139
139
  scheduler(() => {
140
140
  const waitedItem = listRef.current[indexRef.current] || initialItem;
141
141
  if (!waitedItem) {
@@ -157,6 +157,9 @@ export function useListNavigation(context, props) {
157
157
  }
158
158
  });
159
159
  });
160
+ useIsoLayoutEffect(() => {
161
+ dataRef.current.orientation = orientation;
162
+ }, [dataRef, orientation]);
160
163
 
161
164
  // Sync `selectedIndex` to be the `activeIndex` upon opening the floating
162
165
  // element. Also, reset `activeIndex` upon closing the floating element.
@@ -215,7 +218,7 @@ export function useListNavigation(context, props) {
215
218
  // otherwise use rAF. Don't try more than twice, since something
216
219
  // is wrong otherwise.
217
220
  if (runs < 2) {
218
- const scheduler = runs ? requestAnimationFrame : queueMicrotask;
221
+ const scheduler = runs ? callback => waitForListPopulatedFrame.request(callback) : queueMicrotask;
219
222
  scheduler(waitForListPopulated);
220
223
  }
221
224
  runs += 1;
@@ -233,7 +236,7 @@ export function useListNavigation(context, props) {
233
236
  focusItem();
234
237
  forceScrollIntoViewRef.current = false;
235
238
  }
236
- }, [enabled, open, floatingElement, activeIndex, selectedIndexRef, nested, listRef, orientation, rtl, onNavigate, focusItem, disabledIndicesRef]);
239
+ }, [enabled, open, floatingElement, activeIndex, selectedIndexRef, nested, listRef, orientation, rtl, onNavigate, focusItem, waitForListPopulatedFrame]);
237
240
 
238
241
  // Ensure the parent floating element has focus when a nested child closes
239
242
  // to allow arrow key navigation to work after the pointer leaves the child.
@@ -273,57 +276,12 @@ export function useListNavigation(context, props) {
273
276
  onNavigate(event);
274
277
  }
275
278
  });
276
- const item = React.useMemo(() => {
277
- const itemProps = {
278
- onFocus(event) {
279
- forceSyncFocusRef.current = true;
280
- syncCurrentTarget(event);
281
- },
282
- onClick: ({
283
- currentTarget
284
- }) => currentTarget.focus({
285
- preventScroll: true
286
- }),
287
- // Safari
288
- onMouseMove(event) {
289
- forceSyncFocusRef.current = true;
290
- forceScrollIntoViewRef.current = false;
291
- if (focusItemOnHover) {
292
- syncCurrentTarget(event);
293
- }
294
- },
295
- onPointerLeave(event) {
296
- if (!latestOpenRef.current || !isPointerModalityRef.current || event.pointerType === 'touch') {
297
- return;
298
- }
299
- forceSyncFocusRef.current = true;
300
- const relatedTarget = event.relatedTarget;
301
- if (!focusItemOnHover || listRef.current.includes(relatedTarget)) {
302
- return;
303
- }
304
- if (!resetOnPointerLeaveRef.current) {
305
- return;
306
- }
307
- cancelQueuedFocusRef.current?.();
308
- cancelQueuedFocusRef.current = null;
309
- indexRef.current = -1;
310
- onNavigate(event);
311
- if (!virtual) {
312
- const floatingFocusEl = floatingFocusElementRef.current;
313
- const activeEl = activeElement(ownerDocument(floatingFocusEl));
314
- if (floatingFocusEl && contains(floatingFocusEl, activeEl)) {
315
- floatingFocusEl.focus({
316
- preventScroll: true
317
- });
318
- }
319
- }
320
- }
321
- };
322
- return itemProps;
323
- }, [syncCurrentTarget, latestOpenRef, floatingFocusElementRef, focusItemOnHover, listRef, onNavigate, resetOnPointerLeaveRef, virtual]);
324
- const getParentOrientation = React.useCallback(() => {
279
+ const getParentOrientation = useStableCallback(() => {
325
280
  return parentOrientation ?? tree?.nodesRef.current.find(node => node.id === parentId)?.context?.dataRef?.current.orientation;
326
- }, [parentId, tree, parentOrientation]);
281
+ });
282
+ const getMinEnabledIndex = useStableCallback(() => {
283
+ return getMinListIndex(listRef, disabledIndicesRef.current);
284
+ });
327
285
  const commonOnKeyDown = useStableCallback(event => {
328
286
  isPointerModalityRef.current = false;
329
287
  forceSyncFocusRef.current = true;
@@ -475,6 +433,54 @@ export function useListNavigation(context, props) {
475
433
  onNavigate(event);
476
434
  }
477
435
  });
436
+ const item = React.useMemo(() => {
437
+ const itemProps = {
438
+ onFocus(event) {
439
+ forceSyncFocusRef.current = true;
440
+ syncCurrentTarget(event);
441
+ },
442
+ onClick: ({
443
+ currentTarget
444
+ }) => currentTarget.focus({
445
+ preventScroll: true
446
+ }),
447
+ // Safari
448
+ onMouseMove(event) {
449
+ forceSyncFocusRef.current = true;
450
+ forceScrollIntoViewRef.current = false;
451
+ if (focusItemOnHover) {
452
+ syncCurrentTarget(event);
453
+ }
454
+ },
455
+ onPointerLeave(event) {
456
+ if (!latestOpenRef.current || !isPointerModalityRef.current || event.pointerType === 'touch') {
457
+ return;
458
+ }
459
+ forceSyncFocusRef.current = true;
460
+ const relatedTarget = event.relatedTarget;
461
+ if (!focusItemOnHover || listRef.current.includes(relatedTarget)) {
462
+ return;
463
+ }
464
+ if (!resetOnPointerLeaveRef.current) {
465
+ return;
466
+ }
467
+ cancelQueuedFocusRef.current?.();
468
+ cancelQueuedFocusRef.current = null;
469
+ indexRef.current = -1;
470
+ onNavigate(event);
471
+ if (!virtual) {
472
+ const floatingFocusEl = floatingFocusElementRef.current;
473
+ const activeEl = activeElement(ownerDocument(floatingFocusEl));
474
+ if (floatingFocusEl && contains(floatingFocusEl, activeEl)) {
475
+ floatingFocusEl.focus({
476
+ preventScroll: true
477
+ });
478
+ }
479
+ }
480
+ }
481
+ };
482
+ return itemProps;
483
+ }, [syncCurrentTarget, latestOpenRef, floatingFocusElementRef, focusItemOnHover, listRef, onNavigate, resetOnPointerLeaveRef, virtual]);
478
484
  const ariaActiveDescendantProp = React.useMemo(() => {
479
485
  return virtual && open && hasActiveIndex && {
480
486
  'aria-activedescendant': `${id}-${activeIndex}`
@@ -509,6 +515,9 @@ export function useListNavigation(context, props) {
509
515
  };
510
516
  }, [ariaActiveDescendantProp, commonOnKeyDown, floatingFocusElementRef, orientation, typeableComboboxReference, store, open, virtual, domReferenceElement]);
511
517
  const trigger = React.useMemo(() => {
518
+ function openOnNavigationKeyDown(event) {
519
+ store.setOpen(true, createChangeEventDetails(REASONS.listNavigation, event.nativeEvent, event.currentTarget));
520
+ }
512
521
  function checkVirtualMouse(event) {
513
522
  if (focusItemOnOpen === 'auto' && isVirtualClick(event.nativeEvent)) {
514
523
  focusItemOnOpenRef.current = !virtual;
@@ -547,10 +556,10 @@ export function useListNavigation(context, props) {
547
556
  if (isParentCrossOpenKey) {
548
557
  stopEvent(event);
549
558
  if (currentOpen) {
550
- indexRef.current = getMinListIndex(listRef, disabledIndicesRef.current);
559
+ indexRef.current = getMinEnabledIndex();
551
560
  onNavigate(event);
552
561
  } else {
553
- store.setOpen(true, createChangeEventDetails(REASONS.listNavigation, event.nativeEvent, event.currentTarget));
562
+ openOnNavigationKeyDown(event);
554
563
  }
555
564
  }
556
565
  return undefined;
@@ -561,7 +570,7 @@ export function useListNavigation(context, props) {
561
570
  }
562
571
  stopEvent(event);
563
572
  if (!currentOpen && openOnArrowKeyDown) {
564
- store.setOpen(true, createChangeEventDetails(REASONS.listNavigation, event.nativeEvent, event.currentTarget));
573
+ openOnNavigationKeyDown(event);
565
574
  } else {
566
575
  commonOnKeyDown(event);
567
576
  }
@@ -582,7 +591,7 @@ export function useListNavigation(context, props) {
582
591
  onMouseDown: checkVirtualMouse,
583
592
  onClick: checkVirtualMouse
584
593
  };
585
- }, [commonOnKeyDown, disabledIndicesRef, focusItemOnOpen, listRef, nested, onNavigate, store, openOnArrowKeyDown, orientation, getParentOrientation, rtl, selectedIndexRef, virtual]);
594
+ }, [commonOnKeyDown, focusItemOnOpen, getMinEnabledIndex, nested, onNavigate, store, openOnArrowKeyDown, orientation, getParentOrientation, rtl, selectedIndexRef, virtual]);
586
595
  const reference = React.useMemo(() => {
587
596
  return {
588
597
  ...ariaActiveDescendantProp,
@@ -2,16 +2,19 @@ import { ReactStore } from '@base-ui/utils/store';
2
2
  import { BaseUIChangeEventDetails } from "../../types/index.js";
3
3
  import { PopupStoreContext, PopupStoreSelectors, PopupStoreState } from "../../utils/popups/index.js";
4
4
  import { FloatingRootStore } from "../components/FloatingRootStore.js";
5
- export interface UseSyncedFloatingRootContextOptions<State extends PopupStoreState<any>> {
6
- popupStore: ReactStore<State, PopupStoreContext<any>, PopupStoreSelectors>;
5
+ export interface UseSyncedFloatingRootContextOptions<State extends PopupStoreState<unknown>, ContextEventDetails extends BaseUIChangeEventDetails<string>, OpenChangeEventDetails extends BaseUIChangeEventDetails<string>> {
6
+ popupStore: ReactStore<State, PopupStoreContext<ContextEventDetails>, PopupStoreSelectors>;
7
7
  /**
8
8
  * Whether the Popup element is passed to Floating UI as the floating element instead of the default Positioner.
9
9
  */
10
10
  treatPopupAsFloatingElement?: boolean | undefined;
11
- onOpenChange(open: boolean, eventDetails: BaseUIChangeEventDetails<string>): void;
11
+ floatingRootContext?: FloatingRootStore | undefined;
12
+ floatingId: string | undefined;
13
+ nested: boolean;
14
+ onOpenChange(open: boolean, eventDetails: OpenChangeEventDetails): void;
12
15
  }
13
16
  /**
14
- * Initializes a FloatingRootStore that is kept in sync with the provided PopupStore.
15
- * The new instance is created only once and updated on every render.
17
+ * Keeps a FloatingRootStore in sync with the provided PopupStore.
18
+ * Uses the provided FloatingRootStore when one exists, otherwise creates one once and updates it on every render.
16
19
  */
17
- export declare function useSyncedFloatingRootContext<State extends PopupStoreState<any>>(options: UseSyncedFloatingRootContextOptions<State>): FloatingRootStore;
20
+ export declare function useSyncedFloatingRootContext<State extends PopupStoreState<unknown>, ContextEventDetails extends BaseUIChangeEventDetails<string>, OpenChangeEventDetails extends BaseUIChangeEventDetails<string>>(options: UseSyncedFloatingRootContextOptions<State, ContextEventDetails, OpenChangeEventDetails>): FloatingRootStore;
@@ -1,38 +1,43 @@
1
1
  'use client';
2
2
 
3
- import { useId } from '@base-ui/utils/useId';
4
- import { useRefWithInit } from '@base-ui/utils/useRefWithInit';
3
+ import * as React from 'react';
5
4
  import { useIsoLayoutEffect } from '@base-ui/utils/useIsoLayoutEffect';
6
5
  import { isElement } from '@floating-ui/utils/dom';
7
- import { useFloatingParentNodeId } from "../components/FloatingTree.js";
8
6
  import { FloatingRootStore } from "../components/FloatingRootStore.js";
9
7
  /**
10
- * Initializes a FloatingRootStore that is kept in sync with the provided PopupStore.
11
- * The new instance is created only once and updated on every render.
8
+ * Keeps a FloatingRootStore in sync with the provided PopupStore.
9
+ * Uses the provided FloatingRootStore when one exists, otherwise creates one once and updates it on every render.
12
10
  */
13
11
  export function useSyncedFloatingRootContext(options) {
14
12
  const {
15
13
  popupStore,
16
14
  treatPopupAsFloatingElement = false,
15
+ floatingRootContext: floatingRootContextProp,
16
+ floatingId,
17
+ nested,
17
18
  onOpenChange
18
19
  } = options;
19
- const floatingId = useId();
20
- const nested = useFloatingParentNodeId() != null;
21
20
  const open = popupStore.useState('open');
22
21
  const referenceElement = popupStore.useState('activeTriggerElement');
23
22
  const floatingElement = popupStore.useState(treatPopupAsFloatingElement ? 'popupElement' : 'positionerElement');
24
23
  const triggerElements = popupStore.context.triggerElements;
25
- const store = useRefWithInit(() => new FloatingRootStore({
26
- open,
27
- transitionStatus: undefined,
28
- referenceElement,
29
- floatingElement,
30
- triggerElements,
31
- onOpenChange,
32
- floatingId,
33
- syncOnly: true,
34
- nested
35
- })).current;
24
+ const handleOpenChange = onOpenChange;
25
+ const internalStoreRef = React.useRef(null);
26
+ if (floatingRootContextProp === undefined && internalStoreRef.current === null) {
27
+ internalStoreRef.current = new FloatingRootStore({
28
+ open,
29
+ transitionStatus: undefined,
30
+ referenceElement,
31
+ floatingElement,
32
+ triggerElements,
33
+ onOpenChange: handleOpenChange,
34
+ floatingId,
35
+ syncOnly: true,
36
+ nested
37
+ });
38
+ }
39
+ const store = floatingRootContextProp ?? internalStoreRef.current;
40
+ popupStore.useSyncedValue('floatingId', floatingId);
36
41
  useIsoLayoutEffect(() => {
37
42
  const valuesToSync = {
38
43
  open,
@@ -49,8 +54,8 @@ export function useSyncedFloatingRootContext(options) {
49
54
  store.update(valuesToSync);
50
55
  }, [open, floatingId, referenceElement, floatingElement, store]);
51
56
 
52
- // TODO: When `setOpen` is a part of the PopupStore API, we don't need to sync it.
53
- store.context.onOpenChange = onOpenChange;
57
+ // Keep non-reactive context values fresh for interactions that call `store.setOpen`.
58
+ store.context.onOpenChange = handleOpenChange;
54
59
  store.context.nested = nested;
55
60
  return store;
56
61
  }
@@ -24,9 +24,9 @@ export interface UseTypeaheadProps {
24
24
  */
25
25
  elementsRef?: React.RefObject<Array<HTMLElement | null>> | undefined;
26
26
  /**
27
- * Callback invoked with the typing state as the user types.
27
+ * Callback invoked with the current typing activity as the user types.
28
28
  */
29
- onTypingChange?: ((isTyping: boolean) => void) | undefined;
29
+ onTyping?: ((isTyping: boolean) => void) | undefined;
30
30
  /**
31
31
  * Whether the Hook is enabled, including all internal Effects and event
32
32
  * handlers.