@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
@@ -66,11 +66,11 @@ function resolveTouchAction(direction) {
66
66
  */
67
67
  export const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(componentProps, forwardedRef) {
68
68
  const {
69
- className,
70
69
  render,
70
+ className,
71
+ style,
71
72
  disabled = false,
72
73
  swipeDirection: swipeDirectionProp,
73
- style,
74
74
  ...elementProps
75
75
  } = componentProps;
76
76
  const {
@@ -96,13 +96,13 @@ export const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwip
96
96
  const swipeAreaId = useBaseUiId(componentProps.id);
97
97
  const registerTrigger = useTriggerRegistration(swipeAreaId, store);
98
98
  const open = store.useState('open');
99
- const resolvedSwipeDirection = swipeDirectionProp ?? oppositeSwipeDirection[swipeDirection];
100
- const dismissDirection = oppositeSwipeDirection[resolvedSwipeDirection];
101
- const enabled = !disabled && (!open || swipeActive);
102
99
  const resetDragDelta = useStableCallback(() => {
103
100
  dragDeltaRef.current.x = 0;
104
101
  dragDeltaRef.current.y = 0;
105
102
  });
103
+ const resolvedSwipeDirection = swipeDirectionProp ?? oppositeSwipeDirection[swipeDirection];
104
+ const dismissDirection = oppositeSwipeDirection[resolvedSwipeDirection];
105
+ const enabled = !disabled && (!open || swipeActive);
106
106
  function disableDismissForSwipe() {
107
107
  releaseDismissTimeout.clear();
108
108
  store.context.outsidePressEnabledRef.current = false;
@@ -355,6 +355,7 @@ export const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwip
355
355
  return;
356
356
  }
357
357
  swipePointerProps.onPointerDown?.(event);
358
+
358
359
  // Prevent native text selection/drag gestures from competing with swipe-open dragging.
359
360
  if (event.cancelable) {
360
361
  event.preventDefault();
@@ -48,8 +48,8 @@ const DRAWER_CONTENT_SELECTOR = `[${DRAWER_CONTENT_ATTRIBUTE}]`;
48
48
  */
49
49
  export const DrawerViewport = /*#__PURE__*/React.forwardRef(function DrawerViewport(props, forwardedRef) {
50
50
  const {
51
- className,
52
51
  render,
52
+ className,
53
53
  style,
54
54
  children,
55
55
  ...elementProps
@@ -65,25 +65,25 @@ export const DrawerViewport = /*#__PURE__*/React.forwardRef(function DrawerViewp
65
65
  snapToSequentialPoints
66
66
  } = useDrawerRootContext();
67
67
  const providerContext = useDrawerProviderContext(true);
68
- const visualStateStore = providerContext?.visualStateStore;
68
+ const {
69
+ snapPoints,
70
+ resolvedSnapPoints,
71
+ activeSnapPoint,
72
+ activeSnapPointOffset,
73
+ setActiveSnapPoint,
74
+ popupHeight
75
+ } = useDrawerSnapPoints();
69
76
  const open = store.useState('open');
70
77
  const mounted = store.useState('mounted');
71
78
  const nested = store.useState('nested');
72
79
  const nestedOpenDrawerCount = store.useState('nestedOpenDrawerCount');
73
80
  const viewportElement = store.useState('viewportElement');
74
81
  const popupElementState = store.useState('popupElement');
82
+ const visualStateStore = providerContext?.visualStateStore;
75
83
  const nestedDrawerOpen = nestedOpenDrawerCount > 0;
76
84
  const scrollAxis = swipeDirection === 'left' || swipeDirection === 'right' ? 'horizontal' : 'vertical';
77
85
  const isVerticalScrollAxis = scrollAxis === 'vertical';
78
86
  const crossScrollAxis = isVerticalScrollAxis ? 'horizontal' : 'vertical';
79
- const {
80
- snapPoints,
81
- resolvedSnapPoints,
82
- activeSnapPoint,
83
- activeSnapPointOffset,
84
- setActiveSnapPoint,
85
- popupHeight
86
- } = useDrawerSnapPoints();
87
87
  const [swipeRelease, setSwipeRelease] = React.useState(null);
88
88
  const pendingSwipeCloseSnapPointRef = React.useRef(undefined);
89
89
  const resetSwipeRef = React.useRef(null);
@@ -696,10 +696,8 @@ export const DrawerViewport = /*#__PURE__*/React.forwardRef(function DrawerViewp
696
696
  swiping: swipe.swiping,
697
697
  getDragStyles: swipe.getDragStyles,
698
698
  swipeStrength: swipeRelease ?? null,
699
- setSwipeDismissed(dismissed) {
700
- setSwipeDismissedElements(store.context.popupRef.current, store.context.backdropRef.current, dismissed);
701
- }
702
- }), [store, swipe.getDragStyles, swipe.swiping, swipeRelease]);
699
+ setSwipeDismissed
700
+ }), [setSwipeDismissed, swipe.getDragStyles, swipe.swiping, swipeRelease]);
703
701
  function resetTouchTrackingState() {
704
702
  ignoreTouchSwipeRef.current = false;
705
703
  touchScrollStateRef.current = null;
@@ -709,6 +707,7 @@ export const DrawerViewport = /*#__PURE__*/React.forwardRef(function DrawerViewp
709
707
  return /*#__PURE__*/_jsx(DialogViewport, {
710
708
  ref: forwardedRef,
711
709
  className: className,
710
+ style: style,
712
711
  render: render,
713
712
  ...mergeProps(elementProps, {
714
713
  onPointerDown(event) {
@@ -85,12 +85,8 @@ export const FieldControl = /*#__PURE__*/React.forwardRef(function FieldControl(
85
85
  });
86
86
  const isControlled = valueProp !== undefined;
87
87
  const value = isControlled ? valueUnwrapped : undefined;
88
- const getFieldValue = useStableCallback(() => validation.inputRef.current?.value);
89
- useRegisterFieldControl(validation.inputRef, {
90
- id,
91
- value,
92
- getValue: getFieldValue
93
- });
88
+ const getValueFromInput = useStableCallback(() => validation.inputRef.current?.value);
89
+ useRegisterFieldControl(validation.inputRef, id, value, getValueFromInput);
94
90
  const element = useRenderElement('input', componentProps, {
95
91
  ref: [forwardedRef, inputRef],
96
92
  state,
@@ -29,11 +29,8 @@ export const FieldItem = /*#__PURE__*/React.forwardRef(function FieldItem(compon
29
29
  } = useFieldRootContext(false);
30
30
  const disabled = rootDisabled || disabledProp;
31
31
  const checkboxGroupContext = useCheckboxGroupContext();
32
- // checkboxGroupContext.parent is truthy even if no parent checkbox is involved
33
- const parentId = checkboxGroupContext?.parent.id;
34
- // this a more reliable check
35
32
  const hasParentCheckbox = checkboxGroupContext?.allValues !== undefined;
36
- const controlId = hasParentCheckbox ? parentId : undefined;
33
+ const controlId = hasParentCheckbox ? checkboxGroupContext?.parent.id : undefined;
37
34
  const fieldItemContext = React.useMemo(() => ({
38
35
  disabled
39
36
  }), [disabled]);
@@ -48,6 +48,11 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
48
48
  const dirty = dirtyProp ?? dirtyState;
49
49
  const touched = touchedProp ?? touchedState;
50
50
  const markedDirtyRef = React.useRef(false);
51
+ const registeredFieldIdRef = React.useRef(undefined);
52
+ const getRegisteredFieldId = React.useCallback(() => registeredFieldIdRef.current, []);
53
+ const setRegisteredFieldId = React.useCallback(id => {
54
+ registeredFieldIdRef.current = id;
55
+ }, []);
51
56
  const setDirty = useStableCallback(value => {
52
57
  if (dirtyProp !== undefined) {
53
58
  return;
@@ -91,17 +96,20 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
91
96
  markedDirtyRef,
92
97
  state,
93
98
  name,
94
- shouldValidateOnChange
99
+ shouldValidateOnChange,
100
+ getRegisteredFieldId
95
101
  });
102
+ const validityValue = validityData.value;
96
103
  const handleImperativeValidate = React.useCallback(() => {
97
104
  markedDirtyRef.current = true;
98
- validation.commit(validityData.value);
99
- }, [validation, validityData]);
105
+ validation.commit(validityValue);
106
+ }, [validation, validityValue]);
100
107
  const registerFieldControl = useFieldControlRegistration({
101
108
  commit: validation.commit,
102
109
  invalid,
103
110
  markedDirtyRef,
104
111
  name,
112
+ setRegisteredFieldId,
105
113
  setValidityData,
106
114
  validityData
107
115
  });
@@ -13,6 +13,7 @@ export interface UseFieldValidationParameters {
13
13
  state: FieldRootState;
14
14
  name: string | undefined;
15
15
  shouldValidateOnChange: () => boolean;
16
+ getRegisteredFieldId: () => string | undefined;
16
17
  }
17
18
  export interface UseFieldValidationReturnValue {
18
19
  getValidationProps: (props?: HTMLProps) => HTMLProps;
@@ -42,7 +42,8 @@ export function useFieldValidation(params) {
42
42
  markedDirtyRef,
43
43
  state,
44
44
  name,
45
- shouldValidateOnChange
45
+ shouldValidateOnChange,
46
+ getRegisteredFieldId
46
47
  } = params;
47
48
  const {
48
49
  controlId,
@@ -55,6 +56,21 @@ export function useFieldValidation(params) {
55
56
  if (!element) {
56
57
  return;
57
58
  }
59
+ function updateRegisteredFieldValidity(nextValidityData, externalInvalid = invalid) {
60
+ const fieldId = getRegisteredFieldId() ?? controlId;
61
+ if (fieldId == null) {
62
+ return;
63
+ }
64
+ const currentFieldData = formRef.current.fields.get(fieldId);
65
+ if (!currentFieldData) {
66
+ return;
67
+ }
68
+ const validityDataWithFormErrors = getCombinedFieldValidityData(nextValidityData, externalInvalid);
69
+ formRef.current.fields.set(fieldId, {
70
+ ...currentFieldData,
71
+ validityData: validityDataWithFormErrors
72
+ });
73
+ }
58
74
  if (revalidate) {
59
75
  if (state.valid !== false) {
60
76
  return;
@@ -75,15 +91,9 @@ export function useFieldValidation(params) {
75
91
  initialValue: validityData.initialValue
76
92
  };
77
93
  element.setCustomValidity('');
78
- if (controlId) {
79
- const currentFieldData = formRef.current.fields.get(controlId);
80
- if (currentFieldData) {
81
- formRef.current.fields.set(controlId, {
82
- ...currentFieldData,
83
- ...getCombinedFieldValidityData(nextValidityData, false) // invalid = false
84
- });
85
- }
86
- }
94
+
95
+ // The required value is now present; ignore stale external invalid state for this pass.
96
+ updateRegisteredFieldValidity(nextValidityData, false);
87
97
  setValidityData(nextValidityData);
88
98
  return;
89
99
  }
@@ -186,16 +196,9 @@ export function useFieldValidation(params) {
186
196
  errors: validationErrors,
187
197
  initialValue: validityData.initialValue
188
198
  };
189
- if (controlId) {
190
- const currentFieldData = formRef.current.fields.get(controlId);
191
- if (currentFieldData) {
192
- formRef.current.fields.set(controlId, {
193
- ...currentFieldData,
194
- // Keep Form-level errors part of overall field validity for submit blocking/focus logic.
195
- ...getCombinedFieldValidityData(nextValidityData, invalid)
196
- });
197
- }
198
- }
199
+
200
+ // Keep Form-level errors part of overall field validity for submit blocking/focus logic.
201
+ updateRegisteredFieldValidity(nextValidityData);
199
202
  setValidityData(nextValidityData);
200
203
  });
201
204
  const getValidationProps = React.useCallback((externalProps = {}) => mergeProps(getDescriptionProps, state.valid === false ? {
@@ -1,4 +1,4 @@
1
- import { FieldValidityData } from "../root/FieldRoot.js";
1
+ import type { FieldValidityData } from "../root/FieldRoot.js";
2
2
  /**
3
3
  * Combines the field's client-side, stateful validity data with the external invalid state to
4
4
  * determine the field's true validity.
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { FieldValidityData } from "../root/FieldRoot.js";
2
+ import type { FieldValidityData } from "../root/FieldRoot.js";
3
3
  import { type TransitionStatus } from "../../internals/useTransitionStatus.js";
4
4
  /**
5
5
  * Used to display a custom message based on the field's validity.
@@ -68,11 +68,11 @@ export function FloatingDelayGroup(props) {
68
68
  export function useDelayGroup(context, options = {
69
69
  open: false
70
70
  }) {
71
- const store = 'rootStore' in context ? context.rootStore : context;
72
- const floatingId = store.useState('floatingId');
73
71
  const {
74
72
  open
75
73
  } = options;
74
+ const store = 'rootStore' in context ? context.rootStore : context;
75
+ const floatingId = store.useState('floatingId');
76
76
  const groupContext = React.useContext(FloatingDelayGroupContext);
77
77
  const {
78
78
  currentIdRef,
@@ -141,7 +141,7 @@ export function useDelayGroup(context, options = {
141
141
  setIsInstantPhase(false);
142
142
  prevContext?.setIsInstantPhase(false);
143
143
  }
144
- }, [open, floatingId, store, currentIdRef, delayRef, timeoutMs, initialDelayRef, currentContextRef, timeout]);
144
+ }, [open, floatingId, store, currentIdRef, delayRef, initialDelayRef, currentContextRef, timeout]);
145
145
  useIsoLayoutEffect(() => {
146
146
  return () => {
147
147
  currentContextRef.current = null;
@@ -83,7 +83,7 @@ export interface FloatingFocusManagerProps {
83
83
  */
84
84
  beforeContentFocusGuardRef?: React.RefObject<HTMLSpanElement | null> | undefined;
85
85
  /**
86
- * External FlatingTree to use when the one provided by context can't be used.
86
+ * External FloatingTree to use when the one provided by context can't be used.
87
87
  */
88
88
  externalTree?: FloatingTreeStore | undefined;
89
89
  /**
@@ -180,7 +180,7 @@ export function FloatingFocusManager(props) {
180
180
  }
181
181
  const doc = ownerDocument(floatingFocusElement);
182
182
  return addEventListener(doc, 'keydown', onKeyDown);
183
- }, [disabled, domReference, floatingFocusElement, modal, orderRef, isUntrappedTypeableCombobox, getTabbableContent]);
183
+ }, [disabled, floatingFocusElement, modal, isUntrappedTypeableCombobox, getTabbableContent]);
184
184
 
185
185
  // Track pointer/keyboard interactions to disambiguate focus and outside presses.
186
186
  React.useEffect(() => {
@@ -329,7 +329,7 @@ export function FloatingFocusManager(props) {
329
329
  markerCleanup();
330
330
  ariaHiddenCleanup();
331
331
  };
332
- }, [open, disabled, domReference, floating, modal, orderRef, portalContext, isUntrappedTypeableCombobox, tree, getNodeId, nextFocusableElement, previousFocusableElement, getResolvedInsideElements]);
332
+ }, [open, disabled, domReference, floating, modal, portalContext, isUntrappedTypeableCombobox, tree, getNodeId, nextFocusableElement, previousFocusableElement, getResolvedInsideElements]);
333
333
 
334
334
  // Focus the initial element when the floating element opens.
335
335
  useIsoLayoutEffect(() => {
@@ -366,11 +366,20 @@ export function FloatingFocusManager(props) {
366
366
  elToFocus = resolveRef(resolvedInitialFocus);
367
367
  }
368
368
  elToFocus = elToFocus || getDefaultFocusElement();
369
+ const hadFocusInside = contains(floatingFocusElement, activeElement(doc));
369
370
  enqueueFocus(elToFocus, {
370
- preventScroll: elToFocus === floatingFocusElement
371
+ preventScroll: elToFocus === floatingFocusElement,
372
+ shouldFocus() {
373
+ if (hadFocusInside) {
374
+ return true;
375
+ }
376
+ const currentActiveElement = activeElement(doc);
377
+ const focusMovedInside = currentActiveElement !== elToFocus && contains(floatingFocusElement, currentActiveElement);
378
+ return !focusMovedInside;
379
+ }
371
380
  });
372
381
  });
373
- }, [disabled, open, floatingFocusElement, ignoreInitialFocus, getTabbableContent, initialFocusRef, openInteractionTypeRef]);
382
+ }, [disabled, open, floatingFocusElement, getTabbableContent, initialFocusRef, openInteractionTypeRef]);
374
383
 
375
384
  // Track return focus targets and restore focus on unmount/close.
376
385
  useIsoLayoutEffect(() => {
@@ -425,10 +434,12 @@ export function FloatingFocusManager(props) {
425
434
  resolvedReturnFocusValue = true;
426
435
  }
427
436
  if (typeof resolvedReturnFocusValue === 'boolean') {
428
- const el = domReference || getPreviouslyFocusedElement();
429
- return el && el.isConnected ? el : null;
437
+ if (domReference?.isConnected) {
438
+ return domReference;
439
+ }
440
+ return getPreviouslyFocusedElement() || null;
430
441
  }
431
- const fallback = domReference || getPreviouslyFocusedElement();
442
+ const fallback = domReference?.isConnected ? domReference : getPreviouslyFocusedElement();
432
443
  return resolveRef(resolvedReturnFocusValue) || fallback || null;
433
444
  }
434
445
  return () => {
@@ -456,7 +467,7 @@ export function FloatingFocusManager(props) {
456
467
  preventReturnFocusRef.current = false;
457
468
  });
458
469
  };
459
- }, [disabled, floating, floatingFocusElement, returnFocusRef, dataRef, events, tree, domReference, getNodeId, getResolvedInsideElements]);
470
+ }, [disabled, floating, floatingFocusElement, returnFocusRef, events, tree, domReference, getNodeId, getResolvedInsideElements]);
460
471
 
461
472
  // Safari may randomly scroll to the bottom of the page if an input inside a popup has focus
462
473
  // when the popup unmounts from the DOM.
@@ -473,6 +484,7 @@ export function FloatingFocusManager(props) {
473
484
  activeEl.blur();
474
485
  }
475
486
  }, [open, floating]);
487
+
476
488
  // Synchronize the `context` & `modal` value to the FloatingPortal context.
477
489
  // It will decide whether or not it needs to render its own guards.
478
490
  useIsoLayoutEffect(() => {
@@ -100,12 +100,12 @@ export function useFloatingPortalNode(props = {}) {
100
100
  */
101
101
  export const FloatingPortal = /*#__PURE__*/React.forwardRef(function FloatingPortal(componentProps, forwardedRef) {
102
102
  const {
103
+ render,
104
+ className,
105
+ style,
103
106
  children,
104
107
  container,
105
- className,
106
- render,
107
108
  renderGuards,
108
- style,
109
109
  ...elementProps
110
110
  } = componentProps;
111
111
  const {
@@ -5,7 +5,7 @@ import { useAnimationFrame } from '@base-ui/utils/useAnimationFrame';
5
5
  import { useTimeout } from '@base-ui/utils/useTimeout';
6
6
  import { EMPTY_OBJECT } from '@base-ui/utils/empty';
7
7
  import { getTarget, isTypeableElement } from "../utils/element.js";
8
- import { isClickLikeEvent, isMouseLikePointerType } from "../utils/event.js";
8
+ import { isMouseLikePointerType } from "../utils/event.js";
9
9
  import { createChangeEventDetails } from "../../internals/createBaseUIEventDetails.js";
10
10
  import { REASONS } from "../../internals/reasons.js";
11
11
  /**
@@ -13,8 +13,6 @@ import { REASONS } from "../../internals/reasons.js";
13
13
  * @see https://floating-ui.com/docs/useClick
14
14
  */
15
15
  export function useClick(context, props = {}) {
16
- const store = 'rootStore' in context ? context.rootStore : context;
17
- const dataRef = store.context.dataRef;
18
16
  const {
19
17
  enabled = true,
20
18
  event: eventOption = 'click',
@@ -24,89 +22,100 @@ export function useClick(context, props = {}) {
24
22
  touchOpenDelay = 0,
25
23
  reason = REASONS.triggerPress
26
24
  } = props;
25
+ const store = 'rootStore' in context ? context.rootStore : context;
26
+ const dataRef = store.context.dataRef;
27
27
  const pointerTypeRef = React.useRef(undefined);
28
28
  const frame = useAnimationFrame();
29
29
  const touchOpenTimeout = useTimeout();
30
- const reference = React.useMemo(() => ({
31
- onPointerDown(event) {
32
- pointerTypeRef.current = event.pointerType;
33
- },
34
- onMouseDown(event) {
35
- const pointerType = pointerTypeRef.current;
36
- const nativeEvent = event.nativeEvent;
37
- const open = store.select('open');
38
-
39
- // Ignore all buttons except for the "main" button.
40
- // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
41
- if (event.button !== 0 || eventOption === 'click' || isMouseLikePointerType(pointerType, true) && ignoreMouse) {
42
- return;
30
+ const reference = React.useMemo(() => {
31
+ function setOpenWithTouchDelay(nextOpen, nativeEvent, target, pointerType) {
32
+ const details = createChangeEventDetails(reason, nativeEvent, target);
33
+ if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
34
+ touchOpenTimeout.start(touchOpenDelay, () => {
35
+ store.setOpen(true, details);
36
+ });
37
+ } else {
38
+ store.setOpen(nextOpen, details);
43
39
  }
40
+ }
41
+ function getNextOpen(open, currentTarget, isClickLikeOpenEvent) {
44
42
  const openEvent = dataRef.current.openEvent;
45
- const openEventType = openEvent?.type;
46
- const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
47
- const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? openEventType === 'click' || openEventType === 'mousedown' : true));
43
+ const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== currentTarget;
44
+ if (open && hasClickedOnInactiveTrigger) {
45
+ // Moving between triggers should always open the newly active one.
46
+ return true;
47
+ }
48
+ if (!open) {
49
+ // A closed popup should open on the next press.
50
+ return true;
51
+ }
52
+ if (!toggle) {
53
+ // Non-toggle mode never closes on a repeated trigger press.
54
+ return true;
55
+ }
56
+ if (openEvent && stickIfOpen) {
57
+ // Preserve hover/focus-opened popups until the matching click-like event closes them.
58
+ return !isClickLikeOpenEvent(openEvent.type);
59
+ }
60
+
61
+ // Otherwise, a repeated click toggles the popup closed.
62
+ return false;
63
+ }
64
+ return {
65
+ onPointerDown(event) {
66
+ pointerTypeRef.current = event.pointerType;
67
+ },
68
+ onMouseDown(event) {
69
+ const pointerType = pointerTypeRef.current;
70
+ const nativeEvent = event.nativeEvent;
71
+ const open = store.select('open');
48
72
 
49
- // Animations sometimes won't run on a typeable element if using a rAF.
50
- // Focus is always set on these elements. For touch, we may delay opening.
51
- const target = getTarget(nativeEvent);
52
- if (isTypeableElement(target)) {
53
- const details = createChangeEventDetails(reason, nativeEvent, target);
54
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
55
- touchOpenTimeout.start(touchOpenDelay, () => {
56
- store.setOpen(true, details);
57
- });
58
- } else {
59
- store.setOpen(nextOpen, details);
73
+ // Ignore all buttons except for the "main" button.
74
+ // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
75
+ if (event.button !== 0 || eventOption === 'click' || isMouseLikePointerType(pointerType, true) && ignoreMouse) {
76
+ return;
77
+ }
78
+ const nextOpen = getNextOpen(open, event.currentTarget, openEventType => openEventType === 'click' || openEventType === 'mousedown');
79
+
80
+ // Animations sometimes won't run on a typeable element if using a rAF.
81
+ // Focus is always set on these elements. For touch, we may delay opening.
82
+ const target = getTarget(nativeEvent);
83
+ if (isTypeableElement(target)) {
84
+ setOpenWithTouchDelay(nextOpen, nativeEvent, target, pointerType);
85
+ return;
60
86
  }
61
- return;
62
- }
63
87
 
64
- // Capture the currentTarget before the rAF.
65
- // as React sets it to null after the event handler completes.
66
- const eventCurrentTarget = event.currentTarget;
88
+ // Capture the currentTarget before the rAF.
89
+ // as React sets it to null after the event handler completes.
90
+ const eventCurrentTarget = event.currentTarget;
67
91
 
68
- // Wait until focus is set on the element. This is an alternative to
69
- // `event.preventDefault()` to avoid :focus-visible from appearing when using a pointer.
70
- frame.request(() => {
71
- const details = createChangeEventDetails(reason, nativeEvent, eventCurrentTarget);
72
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
73
- touchOpenTimeout.start(touchOpenDelay, () => {
74
- store.setOpen(true, details);
75
- });
76
- } else {
77
- store.setOpen(nextOpen, details);
92
+ // Wait until focus is set on the element. This is an alternative to
93
+ // `event.preventDefault()` to avoid :focus-visible from appearing when using a pointer.
94
+ frame.request(() => {
95
+ setOpenWithTouchDelay(nextOpen, nativeEvent, eventCurrentTarget, pointerType);
96
+ });
97
+ },
98
+ onClick(event) {
99
+ if (eventOption === 'mousedown-only') {
100
+ return;
78
101
  }
79
- });
80
- },
81
- onClick(event) {
82
- if (eventOption === 'mousedown-only') {
83
- return;
84
- }
85
- const pointerType = pointerTypeRef.current;
86
- if (eventOption === 'mousedown' && pointerType) {
102
+ const pointerType = pointerTypeRef.current;
103
+ if (eventOption === 'mousedown' && pointerType) {
104
+ pointerTypeRef.current = undefined;
105
+ return;
106
+ }
107
+ if (isMouseLikePointerType(pointerType, true) && ignoreMouse) {
108
+ return;
109
+ }
110
+ const open = store.select('open');
111
+ const nextOpen = getNextOpen(open, event.currentTarget, openEventType => openEventType === 'click' || openEventType === 'mousedown' || openEventType === 'keydown' || openEventType === 'keyup');
112
+ setOpenWithTouchDelay(nextOpen, event.nativeEvent, event.currentTarget, pointerType);
113
+ },
114
+ onKeyDown() {
87
115
  pointerTypeRef.current = undefined;
88
- return;
89
116
  }
90
- if (isMouseLikePointerType(pointerType, true) && ignoreMouse) {
91
- return;
92
- }
93
- const open = store.select('open');
94
- const openEvent = dataRef.current.openEvent;
95
- const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
96
- const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? isClickLikeEvent(openEvent) : true));
97
- const details = createChangeEventDetails(reason, event.nativeEvent, event.currentTarget);
98
- if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
99
- touchOpenTimeout.start(touchOpenDelay, () => {
100
- store.setOpen(true, details);
101
- });
102
- } else {
103
- store.setOpen(nextOpen, details);
104
- }
105
- },
106
- onKeyDown() {
107
- pointerTypeRef.current = undefined;
108
- }
109
- }), [dataRef, eventOption, ignoreMouse, store, stickIfOpen, toggle, frame, touchOpenTimeout, touchOpenDelay, reason]);
117
+ };
118
+ }, [dataRef, eventOption, ignoreMouse, reason, store, stickIfOpen, toggle, frame, touchOpenTimeout, touchOpenDelay]);
110
119
  return React.useMemo(() => enabled ? {
111
120
  reference
112
121
  } : EMPTY_OBJECT, [enabled, reference]);