@bigbinary/neeto-atoms 1.0.9 → 1.0.10

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 (576) hide show
  1. package/dist/Accordion-BzfsJePA.js +22 -0
  2. package/dist/Accordion-BzfsJePA.js.map +1 -0
  3. package/dist/Alert-D_FV8xxo.js +65 -0
  4. package/dist/Alert-D_FV8xxo.js.map +1 -0
  5. package/dist/Avatar-D5YGlXVF.js +50 -0
  6. package/dist/Avatar-D5YGlXVF.js.map +1 -0
  7. package/dist/Badge-8FkscqDt.js +59 -0
  8. package/dist/Badge-8FkscqDt.js.map +1 -0
  9. package/dist/Button-Q7MPG6ph.js +92 -0
  10. package/dist/Button-Q7MPG6ph.js.map +1 -0
  11. package/dist/Calendar-pDD7nRF-.js +8025 -0
  12. package/dist/Calendar-pDD7nRF-.js.map +1 -0
  13. package/dist/Callout-B0w4GQtx.js +65 -0
  14. package/dist/Callout-B0w4GQtx.js.map +1 -0
  15. package/dist/Checkbox-zCxgcZiC.js +24 -0
  16. package/dist/Checkbox-zCxgcZiC.js.map +1 -0
  17. package/dist/DatePicker-COxwHPIZ.js +2960 -0
  18. package/dist/DatePicker-COxwHPIZ.js.map +1 -0
  19. package/dist/Dialog-BURSzxaP.js +61 -0
  20. package/dist/Dialog-BURSzxaP.js.map +1 -0
  21. package/dist/Empty-B2JwFmru.js +26 -0
  22. package/dist/Empty-B2JwFmru.js.map +1 -0
  23. package/dist/Input-C1gcv9o2.js +147 -0
  24. package/dist/Input-C1gcv9o2.js.map +1 -0
  25. package/dist/Kbd-EqbC0bua.js +36 -0
  26. package/dist/Kbd-EqbC0bua.js.map +1 -0
  27. package/dist/Label-BVy4hy9Z.js +58 -0
  28. package/dist/Label-BVy4hy9Z.js.map +1 -0
  29. package/dist/MultiEmailInput-SCTYovtX.js +139 -0
  30. package/dist/MultiEmailInput-SCTYovtX.js.map +1 -0
  31. package/dist/Pagination-DSc9yXPy.js +61 -0
  32. package/dist/Pagination-DSc9yXPy.js.map +1 -0
  33. package/dist/Popover-BFMrtVPq.js +95 -0
  34. package/dist/Popover-BFMrtVPq.js.map +1 -0
  35. package/dist/Progress-B9NlUm6e.js +13 -0
  36. package/dist/Progress-B9NlUm6e.js.map +1 -0
  37. package/dist/RadioGroup-BNeYQAoT.js +34 -0
  38. package/dist/RadioGroup-BNeYQAoT.js.map +1 -0
  39. package/dist/Select-BGODpJGc.js +561 -0
  40. package/dist/Select-BGODpJGc.js.map +1 -0
  41. package/dist/{components/SelectFieldWrapper.js → SelectFieldWrapper-BJzq9aCY.js} +3 -11
  42. package/dist/SelectFieldWrapper-BJzq9aCY.js.map +1 -0
  43. package/dist/Sheet-QFC_mHyj.js +63 -0
  44. package/dist/Sheet-QFC_mHyj.js.map +1 -0
  45. package/dist/Slider-BCQXhs0Q.js +25 -0
  46. package/dist/Slider-BCQXhs0Q.js.map +1 -0
  47. package/dist/Spinner-C8HSac-2.js +17 -0
  48. package/dist/Spinner-C8HSac-2.js.map +1 -0
  49. package/dist/Stepper-BoGkmkY0.js +29 -0
  50. package/dist/Stepper-BoGkmkY0.js.map +1 -0
  51. package/dist/Switch-B83TGxJ_.js +20 -0
  52. package/dist/Switch-B83TGxJ_.js.map +1 -0
  53. package/dist/Tabs-DWfKnl3S.js +38 -0
  54. package/dist/Tabs-DWfKnl3S.js.map +1 -0
  55. package/dist/Textarea-C0z50h0N.js +73 -0
  56. package/dist/Textarea-C0z50h0N.js.map +1 -0
  57. package/dist/TimePicker-C4x62jI1.js +142 -0
  58. package/dist/TimePicker-C4x62jI1.js.map +1 -0
  59. package/dist/TimePickerPanel-CiF0RExY.js +126 -0
  60. package/dist/TimePickerPanel-CiF0RExY.js.map +1 -0
  61. package/dist/Toastr-DYqpSaMd.js +115 -0
  62. package/dist/Toastr-DYqpSaMd.js.map +1 -0
  63. package/dist/Tooltip-DhwIZnOU.js +80 -0
  64. package/dist/Tooltip-DhwIZnOU.js.map +1 -0
  65. package/dist/Tree-Dkr11OPy.js +7977 -0
  66. package/dist/Tree-Dkr11OPy.js.map +1 -0
  67. package/dist/TreeSelect-Cmc90YWJ.js +168 -0
  68. package/dist/TreeSelect-Cmc90YWJ.js.map +1 -0
  69. package/dist/Typography-D5TjXEfu.js +82 -0
  70. package/dist/Typography-D5TjXEfu.js.map +1 -0
  71. package/dist/cjs/Accordion-BX5I9ypV.js +28 -0
  72. package/dist/cjs/Accordion-BX5I9ypV.js.map +1 -0
  73. package/dist/cjs/Alert-BVvLyM_d.js +67 -0
  74. package/dist/cjs/Alert-BVvLyM_d.js.map +1 -0
  75. package/dist/cjs/Avatar-CNao5gvP.js +52 -0
  76. package/dist/cjs/Avatar-CNao5gvP.js.map +1 -0
  77. package/dist/cjs/Badge-STBHzYLs.js +61 -0
  78. package/dist/cjs/Badge-STBHzYLs.js.map +1 -0
  79. package/dist/cjs/Button-Bt_AElge.js +94 -0
  80. package/dist/cjs/Button-Bt_AElge.js.map +1 -0
  81. package/dist/cjs/Calendar-Nk76Y9yP.js +8066 -0
  82. package/dist/cjs/Calendar-Nk76Y9yP.js.map +1 -0
  83. package/dist/cjs/Callout-CS2U6pM7.js +67 -0
  84. package/dist/cjs/Callout-CS2U6pM7.js.map +1 -0
  85. package/dist/cjs/Checkbox-DOlS2oCD.js +26 -0
  86. package/dist/cjs/Checkbox-DOlS2oCD.js.map +1 -0
  87. package/dist/cjs/DatePicker-DpijPndg.js +2962 -0
  88. package/dist/cjs/DatePicker-DpijPndg.js.map +1 -0
  89. package/dist/cjs/Dialog-CtI_yWsJ.js +63 -0
  90. package/dist/cjs/Dialog-CtI_yWsJ.js.map +1 -0
  91. package/dist/cjs/Empty-qzle6YvT.js +28 -0
  92. package/dist/cjs/Empty-qzle6YvT.js.map +1 -0
  93. package/dist/cjs/Input-pkugjUb0.js +149 -0
  94. package/dist/cjs/Input-pkugjUb0.js.map +1 -0
  95. package/dist/cjs/Kbd-DHirsI--.js +38 -0
  96. package/dist/cjs/Kbd-DHirsI--.js.map +1 -0
  97. package/dist/cjs/Label-DpyfZsiT.js +60 -0
  98. package/dist/cjs/Label-DpyfZsiT.js.map +1 -0
  99. package/dist/cjs/MultiEmailInput-l0_YVjbp.js +141 -0
  100. package/dist/cjs/MultiEmailInput-l0_YVjbp.js.map +1 -0
  101. package/dist/cjs/Pagination-Byzt9Kmj.js +63 -0
  102. package/dist/cjs/Pagination-Byzt9Kmj.js.map +1 -0
  103. package/dist/cjs/Popover-LIxANoTc.js +101 -0
  104. package/dist/cjs/Popover-LIxANoTc.js.map +1 -0
  105. package/dist/cjs/Progress-DoCxZ_ZH.js +15 -0
  106. package/dist/cjs/Progress-DoCxZ_ZH.js.map +1 -0
  107. package/dist/cjs/RadioGroup-1RAoe38m.js +36 -0
  108. package/dist/cjs/RadioGroup-1RAoe38m.js.map +1 -0
  109. package/dist/cjs/Select-DOPZHlqc.js +567 -0
  110. package/dist/cjs/Select-DOPZHlqc.js.map +1 -0
  111. package/dist/cjs/{components/SelectFieldWrapper.js → SelectFieldWrapper-DEA--2wj.js} +2 -10
  112. package/dist/cjs/SelectFieldWrapper-DEA--2wj.js.map +1 -0
  113. package/dist/cjs/Sheet-CIhtNCBV.js +65 -0
  114. package/dist/cjs/Sheet-CIhtNCBV.js.map +1 -0
  115. package/dist/cjs/Slider-jNUS9vt8.js +27 -0
  116. package/dist/cjs/Slider-jNUS9vt8.js.map +1 -0
  117. package/dist/cjs/Spinner-DQutDMQq.js +19 -0
  118. package/dist/cjs/Spinner-DQutDMQq.js.map +1 -0
  119. package/dist/cjs/Stepper-DCoLl2ZS.js +35 -0
  120. package/dist/cjs/Stepper-DCoLl2ZS.js.map +1 -0
  121. package/dist/cjs/Switch-CFf8DtB_.js +22 -0
  122. package/dist/cjs/Switch-CFf8DtB_.js.map +1 -0
  123. package/dist/cjs/Tabs-D2247rd7.js +40 -0
  124. package/dist/cjs/Tabs-D2247rd7.js.map +1 -0
  125. package/dist/cjs/Textarea-BfdlAJ59.js +75 -0
  126. package/dist/cjs/Textarea-BfdlAJ59.js.map +1 -0
  127. package/dist/cjs/TimePicker-Ba2FdT1O.js +144 -0
  128. package/dist/cjs/TimePicker-Ba2FdT1O.js.map +1 -0
  129. package/dist/cjs/TimePickerPanel-DGNr97cj.js +132 -0
  130. package/dist/cjs/TimePickerPanel-DGNr97cj.js.map +1 -0
  131. package/dist/cjs/Toastr-BGp7-kmf.js +117 -0
  132. package/dist/cjs/Toastr-BGp7-kmf.js.map +1 -0
  133. package/dist/cjs/Tooltip-CtxI7QBY.js +86 -0
  134. package/dist/cjs/Tooltip-CtxI7QBY.js.map +1 -0
  135. package/dist/cjs/Tree-qpOcsGL9.js +7985 -0
  136. package/dist/cjs/Tree-qpOcsGL9.js.map +1 -0
  137. package/dist/cjs/TreeSelect-DiIEdiAU.js +170 -0
  138. package/dist/cjs/TreeSelect-DiIEdiAU.js.map +1 -0
  139. package/dist/cjs/Typography-C3rGpmAY.js +104 -0
  140. package/dist/cjs/Typography-C3rGpmAY.js.map +1 -0
  141. package/dist/cjs/components/Accordion.js +6 -28
  142. package/dist/cjs/components/Accordion.js.map +1 -1
  143. package/dist/cjs/components/Alert.js +9 -70
  144. package/dist/cjs/components/Alert.js.map +1 -1
  145. package/dist/cjs/components/Avatar.js +8 -51
  146. package/dist/cjs/components/Avatar.js.map +1 -1
  147. package/dist/cjs/components/Badge.js +10 -64
  148. package/dist/cjs/components/Badge.js.map +1 -1
  149. package/dist/cjs/components/Button.js +10 -94
  150. package/dist/cjs/components/Button.js.map +1 -1
  151. package/dist/cjs/components/Callout.js +9 -66
  152. package/dist/cjs/components/Callout.js.map +1 -1
  153. package/dist/cjs/components/Checkbox.js +8 -24
  154. package/dist/cjs/components/Checkbox.js.map +1 -1
  155. package/dist/cjs/components/DataTable.js +1 -1
  156. package/dist/cjs/components/DatePicker.js +45 -0
  157. package/dist/cjs/components/DatePicker.js.map +1 -0
  158. package/dist/cjs/components/Dialog.js +7 -63
  159. package/dist/cjs/components/Dialog.js.map +1 -1
  160. package/dist/cjs/components/Empty.js +10 -29
  161. package/dist/cjs/components/Empty.js.map +1 -1
  162. package/dist/cjs/components/Input.js +8 -151
  163. package/dist/cjs/components/Input.js.map +1 -1
  164. package/dist/cjs/components/Kbd.js +8 -41
  165. package/dist/cjs/components/Kbd.js.map +1 -1
  166. package/dist/cjs/components/Label.js +11 -59
  167. package/dist/cjs/components/Label.js.map +1 -1
  168. package/dist/cjs/components/MultiEmailInput.js +20 -0
  169. package/dist/cjs/components/MultiEmailInput.js.map +1 -0
  170. package/dist/cjs/components/Pagination.js +21 -0
  171. package/dist/cjs/components/Pagination.js.map +1 -0
  172. package/dist/cjs/components/Popover.js +7 -103
  173. package/dist/cjs/components/Popover.js.map +1 -1
  174. package/dist/cjs/components/Progress.js +7 -13
  175. package/dist/cjs/components/Progress.js.map +1 -1
  176. package/dist/cjs/components/RadioGroup.js +9 -40
  177. package/dist/cjs/components/RadioGroup.js.map +1 -1
  178. package/dist/cjs/components/Select.js +33 -0
  179. package/dist/cjs/components/Select.js.map +1 -1
  180. package/dist/cjs/components/Sheet.js +7 -65
  181. package/dist/cjs/components/Sheet.js.map +1 -1
  182. package/dist/cjs/components/Slider.js +8 -25
  183. package/dist/cjs/components/Slider.js.map +1 -1
  184. package/dist/cjs/components/Spinner.js +7 -19
  185. package/dist/cjs/components/Spinner.js.map +1 -1
  186. package/dist/cjs/components/Stepper.js +6 -32
  187. package/dist/cjs/components/Stepper.js.map +1 -1
  188. package/dist/cjs/components/Switch.js +8 -20
  189. package/dist/cjs/components/Switch.js.map +1 -1
  190. package/dist/cjs/components/Tabs.js +8 -55
  191. package/dist/cjs/components/Tabs.js.map +1 -1
  192. package/dist/cjs/components/Textarea.js +8 -77
  193. package/dist/cjs/components/Textarea.js.map +1 -1
  194. package/dist/cjs/components/TimePicker.js +42 -0
  195. package/dist/cjs/components/TimePicker.js.map +1 -0
  196. package/dist/cjs/components/Toastr.js +4 -126
  197. package/dist/cjs/components/Toastr.js.map +1 -1
  198. package/dist/cjs/components/Tooltip.js +5 -85
  199. package/dist/cjs/components/Tooltip.js.map +1 -1
  200. package/dist/cjs/components/Tree.js +62 -0
  201. package/dist/cjs/components/Tree.js.map +1 -0
  202. package/dist/cjs/components/TreeSelect.js +45 -0
  203. package/dist/cjs/components/TreeSelect.js.map +1 -0
  204. package/dist/cjs/components/Typography.js +8 -98
  205. package/dist/cjs/components/Typography.js.map +1 -1
  206. package/dist/cjs/formik/Button.js +45 -0
  207. package/dist/cjs/formik/Button.js.map +1 -0
  208. package/dist/cjs/formik/Checkbox.js +38 -0
  209. package/dist/cjs/formik/Checkbox.js.map +1 -0
  210. package/dist/cjs/formik/Form.js +116 -0
  211. package/dist/cjs/formik/Form.js.map +1 -0
  212. package/dist/cjs/formik/Input.js +38 -0
  213. package/dist/cjs/formik/Input.js.map +1 -0
  214. package/dist/cjs/formik/MultiEmailInput.js +31 -0
  215. package/dist/cjs/formik/MultiEmailInput.js.map +1 -0
  216. package/dist/cjs/formik/RadioGroup.js +44 -0
  217. package/dist/cjs/formik/RadioGroup.js.map +1 -0
  218. package/dist/cjs/formik/Select.js +61 -0
  219. package/dist/cjs/formik/Select.js.map +1 -0
  220. package/dist/cjs/formik/Slider.js +39 -0
  221. package/dist/cjs/formik/Slider.js.map +1 -0
  222. package/dist/cjs/formik/Switch.js +33 -0
  223. package/dist/cjs/formik/Switch.js.map +1 -0
  224. package/dist/cjs/formik/Textarea.js +34 -0
  225. package/dist/cjs/formik/Textarea.js.map +1 -0
  226. package/dist/cjs/formik/TreeSelect.js +56 -0
  227. package/dist/cjs/formik/TreeSelect.js.map +1 -0
  228. package/dist/cjs/formik/index.js +101 -0
  229. package/dist/cjs/formik/index.js.map +1 -0
  230. package/dist/cjs/index.js +317 -427
  231. package/dist/cjs/index.js.map +1 -1
  232. package/dist/cjs/primitives/Calendar.js +10 -8020
  233. package/dist/cjs/primitives/Calendar.js.map +1 -1
  234. package/dist/cjs/primitives/Chart.js +410 -207
  235. package/dist/cjs/primitives/Chart.js.map +1 -1
  236. package/dist/cjs/primitives/Combobox.js +783 -1096
  237. package/dist/cjs/primitives/Combobox.js.map +1 -1
  238. package/dist/cjs/primitives/Pagination.js +1 -1
  239. package/dist/cjs/primitives/Resizable.js +799 -778
  240. package/dist/cjs/primitives/Resizable.js.map +1 -1
  241. package/dist/cjs/primitives/ScrollArea.js +10 -10
  242. package/dist/cjs/primitives/Select.js +77 -77
  243. package/dist/cjs/primitives/index.js +3 -2
  244. package/dist/cjs/primitives/index.js.map +1 -1
  245. package/dist/cjs/redux-DEF7lAd1.js +240 -0
  246. package/dist/cjs/redux-DEF7lAd1.js.map +1 -0
  247. package/dist/cjs/with-selector-DeKHbQY7.js +121 -0
  248. package/dist/cjs/with-selector-DeKHbQY7.js.map +1 -0
  249. package/dist/components/Accordion/index.d.ts +2 -0
  250. package/dist/components/Accordion.js +5 -27
  251. package/dist/components/Accordion.js.map +1 -1
  252. package/dist/components/{Alert.d.ts → Alert/Alert.d.ts} +2 -2
  253. package/dist/components/Alert/constants.d.ts +3 -0
  254. package/dist/components/Alert/index.d.ts +2 -0
  255. package/dist/components/Alert.js +10 -75
  256. package/dist/components/Alert.js.map +1 -1
  257. package/dist/components/{Avatar.d.ts → Avatar/Avatar.d.ts} +2 -2
  258. package/dist/components/Avatar/constants.d.ts +3 -0
  259. package/dist/components/Avatar/index.d.ts +2 -0
  260. package/dist/components/Avatar/utils.d.ts +1 -0
  261. package/dist/components/Avatar.js +9 -56
  262. package/dist/components/Avatar.js.map +1 -1
  263. package/dist/components/{Badge.d.ts → Badge/Badge.d.ts} +1 -1
  264. package/dist/components/Badge/constants.d.ts +25 -0
  265. package/dist/components/Badge/index.d.ts +2 -0
  266. package/dist/components/Badge.js +8 -66
  267. package/dist/components/Badge.js.map +1 -1
  268. package/dist/components/Button/constants.d.ts +5 -0
  269. package/dist/components/Button/index.d.ts +2 -0
  270. package/dist/components/Button.js +11 -99
  271. package/dist/components/Button.js.map +1 -1
  272. package/dist/components/{Callout.d.ts → Callout/Callout.d.ts} +1 -1
  273. package/dist/components/Callout/constants.d.ts +8 -0
  274. package/dist/components/Callout/index.d.ts +2 -0
  275. package/dist/components/Callout.js +8 -69
  276. package/dist/components/Callout.js.map +1 -1
  277. package/dist/components/Checkbox/index.d.ts +2 -0
  278. package/dist/components/Checkbox.js +6 -26
  279. package/dist/components/Checkbox.js.map +1 -1
  280. package/dist/components/ColorPicker.js +2 -2
  281. package/dist/components/DataTable.js +4 -4
  282. package/dist/components/DatePicker/DatePicker.d.ts +4 -0
  283. package/dist/components/DatePicker/DatePickerFooter.d.ts +12 -0
  284. package/dist/components/DatePicker/TimezoneSelect.d.ts +8 -0
  285. package/dist/components/DatePicker/constants.d.ts +17 -0
  286. package/dist/components/DatePicker/index.d.ts +2 -0
  287. package/dist/components/DatePicker/types.d.ts +56 -0
  288. package/dist/components/DatePicker/utils.d.ts +6 -0
  289. package/dist/components/DatePicker.js +39 -0
  290. package/dist/components/DatePicker.js.map +1 -0
  291. package/dist/components/{Dialog.d.ts → Dialog/Dialog.d.ts} +1 -1
  292. package/dist/components/Dialog/constants.d.ts +2 -0
  293. package/dist/components/Dialog/index.d.ts +2 -0
  294. package/dist/components/Dialog.js +5 -65
  295. package/dist/components/Dialog.js.map +1 -1
  296. package/dist/components/DropdownMenu.js +3 -3
  297. package/dist/components/Empty/index.d.ts +2 -0
  298. package/dist/components/Empty.js +11 -34
  299. package/dist/components/Empty.js.map +1 -1
  300. package/dist/components/Input/constants.d.ts +17 -0
  301. package/dist/components/Input/index.d.ts +2 -0
  302. package/dist/components/Input/utils.d.ts +7 -0
  303. package/dist/components/Input.js +6 -153
  304. package/dist/components/Input.js.map +1 -1
  305. package/dist/components/{Kbd.d.ts → Kbd/Kbd.d.ts} +1 -1
  306. package/dist/components/Kbd/constants.d.ts +1 -0
  307. package/dist/components/Kbd/index.d.ts +2 -0
  308. package/dist/components/Kbd.js +9 -46
  309. package/dist/components/Kbd.js.map +1 -1
  310. package/dist/components/Label/constants.d.ts +1 -0
  311. package/dist/components/Label/index.d.ts +2 -0
  312. package/dist/components/Label.js +13 -65
  313. package/dist/components/Label.js.map +1 -1
  314. package/dist/components/MultiEmailInput/MultiEmailInput.d.ts +3 -0
  315. package/dist/components/MultiEmailInput/constants.d.ts +3 -0
  316. package/dist/components/MultiEmailInput/index.d.ts +2 -0
  317. package/dist/components/MultiEmailInput/types.d.ts +53 -0
  318. package/dist/components/MultiEmailInput/useMultiEmailState.d.ts +18 -0
  319. package/dist/components/MultiEmailInput/utils.d.ts +9 -0
  320. package/dist/components/MultiEmailInput.js +14 -0
  321. package/dist/components/MultiEmailInput.js.map +1 -0
  322. package/dist/components/Pagination/Pagination.d.ts +18 -0
  323. package/dist/components/Pagination/constants.d.ts +1 -0
  324. package/dist/components/Pagination/hooks/usePaginationRange.d.ts +7 -0
  325. package/dist/components/Pagination/index.d.ts +2 -0
  326. package/dist/components/Pagination/utils.d.ts +1 -0
  327. package/dist/components/Pagination.js +15 -0
  328. package/dist/components/Pagination.js.map +1 -0
  329. package/dist/components/Popover/constants.d.ts +2 -0
  330. package/dist/components/Popover/index.d.ts +2 -0
  331. package/dist/components/Popover.js +8 -104
  332. package/dist/components/Popover.js.map +1 -1
  333. package/dist/components/Progress/index.d.ts +2 -0
  334. package/dist/components/Progress.js +5 -15
  335. package/dist/components/Progress.js.map +1 -1
  336. package/dist/components/RadioGroup/index.d.ts +2 -0
  337. package/dist/components/RadioGroup.js +7 -42
  338. package/dist/components/RadioGroup.js.map +1 -1
  339. package/dist/components/Select/MultiSelectCombobox.d.ts +2 -0
  340. package/dist/components/{MultiSelectCombobox.types.d.ts → Select/MultiSelectCombobox.types.d.ts} +3 -13
  341. package/dist/components/{OptionItem.d.ts → Select/OptionItem.d.ts} +1 -1
  342. package/dist/components/Select/Select.d.ts +5 -0
  343. package/dist/components/Select/SelectCombobox.d.ts +2 -0
  344. package/dist/components/Select/SelectCombobox.types.d.ts +73 -0
  345. package/dist/components/Select/dropdown.types.d.ts +12 -0
  346. package/dist/components/Select/index.d.ts +2 -0
  347. package/dist/components/Select/types.d.ts +148 -0
  348. package/dist/components/{MultiSelect.utils.d.ts → Select/utils.d.ts} +1 -1
  349. package/dist/components/Select.js +29 -1
  350. package/dist/components/Select.js.map +1 -1
  351. package/dist/components/Sheet/constants.d.ts +3 -0
  352. package/dist/components/Sheet/index.d.ts +2 -0
  353. package/dist/components/Sheet.js +5 -67
  354. package/dist/components/Sheet.js.map +1 -1
  355. package/dist/components/Slider/index.d.ts +2 -0
  356. package/dist/components/Slider.js +6 -27
  357. package/dist/components/Slider.js.map +1 -1
  358. package/dist/components/Spinner/constants.d.ts +1 -0
  359. package/dist/components/Spinner/index.d.ts +2 -0
  360. package/dist/components/Spinner.js +5 -21
  361. package/dist/components/Spinner.js.map +1 -1
  362. package/dist/components/Stepper/index.d.ts +2 -0
  363. package/dist/components/Stepper.js +5 -31
  364. package/dist/components/Stepper.js.map +1 -1
  365. package/dist/components/Switch/index.d.ts +2 -0
  366. package/dist/components/Switch.js +6 -22
  367. package/dist/components/Switch.js.map +1 -1
  368. package/dist/components/Tabs/constants.d.ts +5 -0
  369. package/dist/components/Tabs/index.d.ts +2 -0
  370. package/dist/components/Tabs.js +6 -57
  371. package/dist/components/Tabs.js.map +1 -1
  372. package/dist/components/{Textarea.d.ts → Textarea/Textarea.d.ts} +1 -1
  373. package/dist/components/Textarea/constants.d.ts +5 -0
  374. package/dist/components/Textarea/index.d.ts +2 -0
  375. package/dist/components/Textarea/utils.d.ts +2 -0
  376. package/dist/components/Textarea.js +6 -79
  377. package/dist/components/Textarea.js.map +1 -1
  378. package/dist/components/TimePicker/TimeColumn.d.ts +11 -0
  379. package/dist/components/TimePicker/TimePicker.d.ts +4 -0
  380. package/dist/components/TimePicker/TimePickerPanel.d.ts +4 -0
  381. package/dist/components/TimePicker/constants.d.ts +3 -0
  382. package/dist/components/TimePicker/index.d.ts +3 -0
  383. package/dist/components/TimePicker/types.d.ts +61 -0
  384. package/dist/components/TimePicker/utils.d.ts +11 -0
  385. package/dist/components/TimePicker.js +35 -0
  386. package/dist/components/TimePicker.js.map +1 -0
  387. package/dist/components/{Toastr.d.ts → Toastr/Toastr.d.ts} +2 -2
  388. package/dist/components/Toastr/index.d.ts +2 -0
  389. package/dist/components/Toastr/utils.d.ts +10 -0
  390. package/dist/components/Toastr.js +2 -128
  391. package/dist/components/Toastr.js.map +1 -1
  392. package/dist/components/Tooltip/constants.d.ts +2 -0
  393. package/dist/components/Tooltip/index.d.ts +2 -0
  394. package/dist/components/Tooltip.js +7 -87
  395. package/dist/components/Tooltip.js.map +1 -1
  396. package/dist/components/Tree/Tree.d.ts +2 -0
  397. package/dist/components/Tree/TreeContext.d.ts +26 -0
  398. package/dist/components/Tree/components/SwitcherIcon.d.ts +6 -0
  399. package/dist/components/Tree/components/TreeCheckbox.d.ts +8 -0
  400. package/dist/components/Tree/components/TreeNode.d.ts +3 -0
  401. package/dist/components/Tree/constants.d.ts +3 -0
  402. package/dist/components/Tree/hooks/useTreeCheck.d.ts +18 -0
  403. package/dist/components/Tree/hooks/useTreeExpansion.d.ts +18 -0
  404. package/dist/components/Tree/hooks/useTreeSelection.d.ts +16 -0
  405. package/dist/components/Tree/index.d.ts +3 -0
  406. package/dist/components/Tree/types.d.ts +110 -0
  407. package/dist/components/Tree/utils/adapter.d.ts +10 -0
  408. package/dist/components/Tree/utils/checkCascade.d.ts +5 -0
  409. package/dist/components/Tree/utils/search.d.ts +10 -0
  410. package/dist/components/Tree.js +57 -0
  411. package/dist/components/Tree.js.map +1 -0
  412. package/dist/components/TreeSelect/TreeSelect.d.ts +3 -0
  413. package/dist/components/TreeSelect/TreeSelectTrigger.d.ts +14 -0
  414. package/dist/components/{Select.constants.d.ts → TreeSelect/constants.d.ts} +2 -2
  415. package/dist/components/TreeSelect/hooks/useTreeSelectState.d.ts +30 -0
  416. package/dist/components/TreeSelect/hooks/useTreeSelectValue.d.ts +19 -0
  417. package/dist/components/TreeSelect/index.d.ts +2 -0
  418. package/dist/components/TreeSelect/types.d.ts +49 -0
  419. package/dist/components/TreeSelect/utils/pruneTree.d.ts +2 -0
  420. package/dist/components/TreeSelect/utils/resolveFieldNames.d.ts +5 -0
  421. package/dist/components/TreeSelect.js +39 -0
  422. package/dist/components/TreeSelect.js.map +1 -0
  423. package/dist/components/{Typography.d.ts → Typography/Typography.d.ts} +1 -1
  424. package/dist/components/Typography/index.d.ts +1 -0
  425. package/dist/components/Typography.js +6 -81
  426. package/dist/components/Typography.js.map +1 -1
  427. package/dist/{floating-ui.react-dom-CcGbtPEK.js → floating-ui.react-dom-D8_f_WWh.js} +2 -2
  428. package/dist/{floating-ui.react-dom-CcGbtPEK.js.map → floating-ui.react-dom-D8_f_WWh.js.map} +1 -1
  429. package/dist/formik/Button.d.ts +7 -0
  430. package/dist/formik/Button.js +43 -0
  431. package/dist/formik/Button.js.map +1 -0
  432. package/dist/formik/Checkbox.d.ts +8 -0
  433. package/dist/formik/Checkbox.js +36 -0
  434. package/dist/formik/Checkbox.js.map +1 -0
  435. package/dist/formik/Form/FormWrapper.d.ts +9 -0
  436. package/dist/formik/Form/ScrollToErrorField/index.d.ts +5 -0
  437. package/dist/formik/Form/ScrollToErrorField/utils.d.ts +2 -0
  438. package/dist/formik/Form/index.d.ts +16 -0
  439. package/dist/formik/Form.js +114 -0
  440. package/dist/formik/Form.js.map +1 -0
  441. package/dist/formik/Input.d.ts +8 -0
  442. package/dist/formik/Input.js +36 -0
  443. package/dist/formik/Input.js.map +1 -0
  444. package/dist/formik/MultiEmailInput.d.ts +7 -0
  445. package/dist/formik/MultiEmailInput.js +29 -0
  446. package/dist/formik/MultiEmailInput.js.map +1 -0
  447. package/dist/formik/RadioGroup.js +42 -0
  448. package/dist/formik/RadioGroup.js.map +1 -0
  449. package/dist/formik/Select.d.ts +7 -0
  450. package/dist/formik/Select.js +59 -0
  451. package/dist/formik/Select.js.map +1 -0
  452. package/dist/formik/Slider.d.ts +8 -0
  453. package/dist/formik/Slider.js +37 -0
  454. package/dist/formik/Slider.js.map +1 -0
  455. package/dist/formik/Switch.d.ts +10 -0
  456. package/dist/formik/Switch.js +31 -0
  457. package/dist/formik/Switch.js.map +1 -0
  458. package/dist/formik/Textarea.d.ts +8 -0
  459. package/dist/formik/Textarea.js +32 -0
  460. package/dist/formik/Textarea.js.map +1 -0
  461. package/dist/formik/TreeSelect.d.ts +7 -0
  462. package/dist/formik/TreeSelect.js +54 -0
  463. package/dist/formik/TreeSelect.js.map +1 -0
  464. package/dist/formik/index.d.ts +22 -0
  465. package/dist/formik/index.js +85 -0
  466. package/dist/formik/index.js.map +1 -0
  467. package/dist/hooks/useAsyncOptions.d.ts +4 -4
  468. package/dist/hooks/useComboboxAnchor.d.ts +6 -0
  469. package/dist/hooks/useCreatableItems.d.ts +1 -1
  470. package/dist/hooks/useMultiSelectOptions.d.ts +22 -4
  471. package/dist/hooks/useMultiSelectState.d.ts +7 -4
  472. package/dist/hooks/useSelectState.d.ts +39 -14
  473. package/dist/{index-ByEpUy7w.js → index-C3hByjk3.js} +2 -2
  474. package/dist/{index-ByEpUy7w.js.map → index-C3hByjk3.js.map} +1 -1
  475. package/dist/{index-KzJfsx-e.js → index-DLPtgEJ_.js} +2 -2
  476. package/dist/{index-KzJfsx-e.js.map → index-DLPtgEJ_.js.map} +1 -1
  477. package/dist/index.css +2 -1
  478. package/dist/index.d.ts +13 -2
  479. package/dist/index.js +281 -402
  480. package/dist/index.js.map +1 -1
  481. package/dist/primitives/Calendar.js +8 -8003
  482. package/dist/primitives/Calendar.js.map +1 -1
  483. package/dist/primitives/Chart.js +253 -50
  484. package/dist/primitives/Chart.js.map +1 -1
  485. package/dist/primitives/Combobox.d.ts +3 -3
  486. package/dist/primitives/Combobox.js +787 -1100
  487. package/dist/primitives/Combobox.js.map +1 -1
  488. package/dist/primitives/ContextMenu.js +3 -3
  489. package/dist/primitives/DropdownMenu.js +3 -3
  490. package/dist/primitives/HoverCard.js +2 -2
  491. package/dist/primitives/Menubar.js +3 -3
  492. package/dist/primitives/Pagination.js +1 -1
  493. package/dist/primitives/Popover.js +2 -2
  494. package/dist/primitives/Resizable.js +799 -778
  495. package/dist/primitives/Resizable.js.map +1 -1
  496. package/dist/primitives/Select.js +4 -4
  497. package/dist/primitives/Sidebar.js +3 -3
  498. package/dist/primitives/Tooltip.js +3 -3
  499. package/dist/primitives/index.js +7 -6
  500. package/dist/primitives/index.js.map +1 -1
  501. package/dist/redux-BKH6DnBB.js +235 -0
  502. package/dist/redux-BKH6DnBB.js.map +1 -0
  503. package/dist/shadcn/components/combobox.d.ts +1 -1
  504. package/dist/shadcn/components/typography.d.ts +2 -2
  505. package/dist/{tooltip-DzjIJacP.js → tooltip-XkHLgxlU.js} +2 -2
  506. package/dist/{tooltip-DzjIJacP.js.map → tooltip-XkHLgxlU.js.map} +1 -1
  507. package/dist/utils/dayjs/index.d.ts +4 -0
  508. package/dist/utils/dayjs/timezonePlugin.d.ts +3 -0
  509. package/dist/with-selector-Dv0G_V_o.js +115 -0
  510. package/dist/with-selector-Dv0G_V_o.js.map +1 -0
  511. package/package.json +17 -3
  512. package/dist/cjs/components/MultiSelect.js +0 -13
  513. package/dist/cjs/components/MultiSelect.js.map +0 -1
  514. package/dist/cjs/components/MultiSelectCombobox.js +0 -3
  515. package/dist/cjs/components/MultiSelectCombobox.js.map +0 -1
  516. package/dist/cjs/components/MultiSelectDropdown.js +0 -38
  517. package/dist/cjs/components/MultiSelectDropdown.js.map +0 -1
  518. package/dist/cjs/components/OptionItem.js +0 -34
  519. package/dist/cjs/components/OptionItem.js.map +0 -1
  520. package/dist/cjs/components/SelectFieldWrapper.js.map +0 -1
  521. package/dist/cjs/components/SelectOptions.js +0 -43
  522. package/dist/cjs/components/SelectOptions.js.map +0 -1
  523. package/dist/cjs/components/SelectTriggerContent.js +0 -47
  524. package/dist/cjs/components/SelectTriggerContent.js.map +0 -1
  525. package/dist/cjs/components/shared.js +0 -8
  526. package/dist/cjs/components/shared.js.map +0 -1
  527. package/dist/cjs/useCreatableItems-BTHtd7uo.js +0 -100
  528. package/dist/cjs/useCreatableItems-BTHtd7uo.js.map +0 -1
  529. package/dist/cjs/with-selector-u4xTSzCv.js +0 -457
  530. package/dist/cjs/with-selector-u4xTSzCv.js.map +0 -1
  531. package/dist/components/MultiSelect.d.ts +0 -4
  532. package/dist/components/MultiSelect.js +0 -4
  533. package/dist/components/MultiSelect.js.map +0 -1
  534. package/dist/components/MultiSelect.types.d.ts +0 -121
  535. package/dist/components/MultiSelectCombobox.d.ts +0 -3
  536. package/dist/components/MultiSelectCombobox.js +0 -2
  537. package/dist/components/MultiSelectCombobox.js.map +0 -1
  538. package/dist/components/MultiSelectDropdown.js +0 -36
  539. package/dist/components/MultiSelectDropdown.js.map +0 -1
  540. package/dist/components/OptionItem.js +0 -32
  541. package/dist/components/OptionItem.js.map +0 -1
  542. package/dist/components/Select.d.ts +0 -4
  543. package/dist/components/Select.types.d.ts +0 -58
  544. package/dist/components/SelectFieldWrapper.js.map +0 -1
  545. package/dist/components/SelectOptions.d.ts +0 -2
  546. package/dist/components/SelectOptions.js +0 -41
  547. package/dist/components/SelectOptions.js.map +0 -1
  548. package/dist/components/SelectTriggerContent.d.ts +0 -18
  549. package/dist/components/SelectTriggerContent.js +0 -45
  550. package/dist/components/SelectTriggerContent.js.map +0 -1
  551. package/dist/components/shared.js +0 -6
  552. package/dist/components/shared.js.map +0 -1
  553. package/dist/components/shared.types.d.ts +0 -16
  554. package/dist/useCreatableItems-B0seQA1_.js +0 -89
  555. package/dist/useCreatableItems-B0seQA1_.js.map +0 -1
  556. package/dist/with-selector--fY1NrB9.js +0 -448
  557. package/dist/with-selector--fY1NrB9.js.map +0 -1
  558. /package/dist/components/{Accordion.d.ts → Accordion/Accordion.d.ts} +0 -0
  559. /package/dist/components/{Button.d.ts → Button/Button.d.ts} +0 -0
  560. /package/dist/components/{Checkbox.d.ts → Checkbox/Checkbox.d.ts} +0 -0
  561. /package/dist/components/{Empty.d.ts → Empty/Empty.d.ts} +0 -0
  562. /package/dist/components/{Input.d.ts → Input/Input.d.ts} +0 -0
  563. /package/dist/components/{Label.d.ts → Label/Label.d.ts} +0 -0
  564. /package/dist/components/{Popover.d.ts → Popover/Popover.d.ts} +0 -0
  565. /package/dist/components/{Progress.d.ts → Progress/Progress.d.ts} +0 -0
  566. /package/dist/components/{RadioGroup.d.ts → RadioGroup/RadioGroup.d.ts} +0 -0
  567. /package/dist/components/{MultiSelectDropdown.d.ts → Select/MultiSelectDropdown.d.ts} +0 -0
  568. /package/dist/components/{SelectFieldWrapper.d.ts → Select/SelectFieldWrapper.d.ts} +0 -0
  569. /package/dist/components/{MultiSelect.constants.d.ts → Select/constants.d.ts} +0 -0
  570. /package/dist/components/{Sheet.d.ts → Sheet/Sheet.d.ts} +0 -0
  571. /package/dist/components/{Slider.d.ts → Slider/Slider.d.ts} +0 -0
  572. /package/dist/components/{Spinner.d.ts → Spinner/Spinner.d.ts} +0 -0
  573. /package/dist/components/{Stepper.d.ts → Stepper/Stepper.d.ts} +0 -0
  574. /package/dist/components/{Switch.d.ts → Switch/Switch.d.ts} +0 -0
  575. /package/dist/components/{Tabs.d.ts → Tabs/Tabs.d.ts} +0 -0
  576. /package/dist/components/{Tooltip.d.ts → Tooltip/Tooltip.d.ts} +0 -0
@@ -1,16 +1,16 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import { createElement } from 'react';
3
+ import React__default, { createElement } from 'react';
4
4
  import { c as cn } from '../utils-DdHUxIdC.js';
5
5
  import { B as Button } from '../button-COIbN8dg.js';
6
6
  import { I as InputGroup, c as InputGroupInput, a as InputGroupAddon, d as InputGroupButton } from '../input-group-ytECR3Hw.js';
7
- import { X } from '../x-_o2T3n6D.js';
8
7
  import { C as Check } from '../check-Cpkv29p1.js';
8
+ import { X } from '../x-_o2T3n6D.js';
9
9
  import { C as ChevronDown } from '../chevron-down-BNi0ntys.js';
10
- import { c as createSelectorCreator, l as lruMemoize, w as withSelectorExports } from '../with-selector--fY1NrB9.js';
11
- import * as ReactDOM from 'react-dom';
12
- import { i as isHTMLElement, d as isShadowRoot, g as getComputedStyle$1, e as floor, j as getWindow, k as isOverflowElement, m as getNodeName, n as isNode, p as isWebKit$1, q as isElement, r as isLastTraversableNode, t as getParentNode, u as useFloating$1, v as evaluate, w as getPaddingObject, x as getAlignmentAxis, y as getAlignment, z as getAxisLength, A as clamp, h as hide$1, o as offset, f as flip, s as shift, l as limitShift, a as size, B as getSide, C as getSideAxis, c as autoUpdate } from '../floating-ui.react-dom-CcGbtPEK.js';
10
+ import { i as isHTMLElement, d as isShadowRoot, g as getComputedStyle, e as floor, j as getNodeName, k as getWindow, m as isOverflowElement, n as isNode, p as isWebKit$1, q as isElement, r as isLastTraversableNode, t as getParentNode, u as useFloating$1, v as evaluate, w as getPaddingObject, x as getAlignmentAxis, y as getAlignment, z as getAxisLength, A as clamp, h as hide$1, o as offset, f as flip, s as shift, l as limitShift, a as size, B as getSide, C as getSideAxis, c as autoUpdate } from '../floating-ui.react-dom-D8_f_WWh.js';
13
11
  import { s as shimExports } from '../index-DZXbzIgC.js';
12
+ import { w as withSelectorExports } from '../with-selector-Dv0G_V_o.js';
13
+ import * as ReactDOM from 'react-dom';
14
14
  import '../index-D7Zy7P05.js';
15
15
  import '../index-CfriMyrd.js';
16
16
  import '../index-BtkPdosV.js';
@@ -492,7 +492,7 @@ const EMPTY_PROPS = {};
492
492
  * Props can either be provided as objects or as functions that take the previous props as an argument.
493
493
  * The function will receive the merged props up to that point (going from left to right):
494
494
  * so in the case of `(obj1, obj2, fn, obj3)`, `fn` will receive the merged props of `obj1` and `obj2`.
495
- * The function is responsible for chaining event handlers if needed (i.e. we don't run the merge logic).
495
+ * The function is responsible for chaining event handlers if needed (that is, we don't run the merge logic).
496
496
  *
497
497
  * Event handlers returned by the functions are not automatically prevented when `preventBaseUIHandler` is called.
498
498
  * They must check `event.baseUIHandlerPrevented` themselves and bail out if it's true.
@@ -508,18 +508,20 @@ const EMPTY_PROPS = {};
508
508
  */
509
509
 
510
510
  function mergeProps$1(a, b, c, d, e) {
511
- // We need to mutably own `merged`
512
- let merged = {
513
- ...resolvePropsGetter(a, EMPTY_PROPS)
514
- };
511
+ if (!c && !d && true && !a) {
512
+ return createInitialMergedProps(b);
513
+ }
514
+
515
+ // We need to mutably own `merged`.
516
+ let merged = createInitialMergedProps(a);
515
517
  if (b) {
516
- merged = mergeOne(merged, b);
518
+ merged = mergeInto(merged, b);
517
519
  }
518
520
  if (c) {
519
- merged = mergeOne(merged, c);
521
+ merged = mergeInto(merged, c);
520
522
  }
521
523
  if (d) {
522
- merged = mergeOne(merged, d);
524
+ merged = mergeInto(merged, d);
523
525
  }
524
526
  return merged;
525
527
  }
@@ -543,24 +545,46 @@ function mergePropsN(props) {
543
545
  return EMPTY_PROPS;
544
546
  }
545
547
  if (props.length === 1) {
546
- return resolvePropsGetter(props[0], EMPTY_PROPS);
548
+ return createInitialMergedProps(props[0]);
547
549
  }
548
550
 
549
- // We need to mutably own `merged`
550
- let merged = {
551
- ...resolvePropsGetter(props[0], EMPTY_PROPS)
552
- };
551
+ // We need to mutably own `merged`.
552
+ let merged = createInitialMergedProps(props[0]);
553
553
  for (let i = 1; i < props.length; i += 1) {
554
- merged = mergeOne(merged, props[i]);
554
+ merged = mergeInto(merged, props[i]);
555
555
  }
556
556
  return merged;
557
557
  }
558
- function mergeOne(merged, inputProps) {
558
+ function createInitialMergedProps(inputProps) {
559
559
  if (isPropsGetter(inputProps)) {
560
- return inputProps(merged);
560
+ // Getter-returned handlers intentionally keep their existing semantics.
561
+ return {
562
+ ...resolvePropsGetter(inputProps, EMPTY_PROPS)
563
+ };
564
+ }
565
+ return copyInitialProps(inputProps);
566
+ }
567
+ function mergeInto(merged, inputProps) {
568
+ if (isPropsGetter(inputProps)) {
569
+ return resolvePropsGetter(inputProps, merged);
561
570
  }
562
571
  return mutablyMergeInto(merged, inputProps);
563
572
  }
573
+ function copyInitialProps(inputProps) {
574
+ const copiedProps = {
575
+ ...inputProps
576
+ };
577
+
578
+ // `copiedProps` is our fresh own-object copy, so iterating with `for...in` is safe here.
579
+ // eslint-disable-next-line guard-for-in
580
+ for (const propName in copiedProps) {
581
+ const propValue = copiedProps[propName];
582
+ if (isEventHandler(propName, propValue)) {
583
+ copiedProps[propName] = wrapEventHandler(propValue);
584
+ }
585
+ }
586
+ return copiedProps;
587
+ }
564
588
 
565
589
  /**
566
590
  * Merges two sets of props. In case of conflicts, the external props take precedence.
@@ -617,7 +641,7 @@ function mergeEventHandlers(ourHandler, theirHandler) {
617
641
  return ourHandler;
618
642
  }
619
643
  if (!ourHandler) {
620
- return theirHandler;
644
+ return wrapEventHandler(theirHandler);
621
645
  }
622
646
  return event => {
623
647
  if (isSyntheticEvent(event)) {
@@ -634,6 +658,17 @@ function mergeEventHandlers(ourHandler, theirHandler) {
634
658
  return result;
635
659
  };
636
660
  }
661
+ function wrapEventHandler(handler) {
662
+ if (!handler) {
663
+ return handler;
664
+ }
665
+ return event => {
666
+ if (isSyntheticEvent(event)) {
667
+ makeEventPreventable(event);
668
+ }
669
+ return handler(event);
670
+ };
671
+ }
637
672
  function makeEventPreventable(event) {
638
673
  event.preventBaseUIHandler = () => {
639
674
  event.baseUIHandlerPrevented = true;
@@ -722,7 +757,12 @@ function useRenderElementProps(componentProps, params = {}) {
722
757
  const className = enabled ? resolveClassName(classNameProp, state) : undefined;
723
758
  const style = enabled ? resolveStyle(styleProp, state) : undefined;
724
759
  const stateProps = enabled ? getStateAttributesProps(state, stateAttributesMapping) : EMPTY_OBJECT;
725
- const outProps = enabled ? mergeObjects(stateProps, Array.isArray(props) ? mergePropsN(props) : props) ?? EMPTY_OBJECT : EMPTY_OBJECT;
760
+ const resolvedProps = enabled && props ? resolveRenderFunctionProps(props) : undefined;
761
+
762
+ // Ensure outProps is always a new mutable object when enabled, never EMPTY_OBJECT.
763
+ // This prevents potential TypeError when setting ref, className, or style properties,
764
+ // since EMPTY_OBJECT is frozen and mutations would fail in strict mode.
765
+ const outProps = enabled ? mergeObjects(stateProps, resolvedProps) ?? {} : EMPTY_OBJECT;
726
766
 
727
767
  // SAFETY: The `useMergedRefs` functions use a single hook to store the same value,
728
768
  // switching between them at runtime is safe. If this assertion fails, React will
@@ -750,6 +790,12 @@ function useRenderElementProps(componentProps, params = {}) {
750
790
  }
751
791
  return outProps;
752
792
  }
793
+ function resolveRenderFunctionProps(props) {
794
+ if (Array.isArray(props)) {
795
+ return mergePropsN(props);
796
+ }
797
+ return mergeProps$1(undefined, props);
798
+ }
753
799
 
754
800
  // The symbol React uses internally for lazy components
755
801
  // https://github.com/facebook/react/blob/a0566250b210499b4c5677f5ac2eedbd71d51a1b/packages/shared/ReactSymbols.js#L31
@@ -1090,70 +1136,67 @@ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false
1090
1136
  */
1091
1137
  signal = null) => {
1092
1138
  frame.cancel();
1093
- function done() {
1094
- // Synchronously flush the unmounting of the component so that the browser doesn't
1095
- // paint: https://github.com/mui/base-ui/issues/979
1096
- ReactDOM.flushSync(fnToExecute);
1097
- }
1098
1139
  const element = resolveRef(elementOrRef);
1099
1140
  if (element == null) {
1100
1141
  return;
1101
1142
  }
1102
1143
  const resolvedElement = element;
1144
+ const done = () => {
1145
+ // Synchronously flush the unmounting of the component so that the browser doesn't
1146
+ // paint: https://github.com/mui/base-ui/issues/979
1147
+ ReactDOM.flushSync(fnToExecute);
1148
+ };
1103
1149
  if (typeof resolvedElement.getAnimations !== 'function' || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
1104
1150
  fnToExecute();
1105
- } else {
1106
- function execWaitForStartingStyleRemoved() {
1107
- const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
1108
-
1109
- // If `[data-starting-style]` isn't present, fall back to waiting one more frame
1110
- // to give "open" animations a chance to be registered.
1111
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1112
- frame.request(exec);
1113
- return;
1114
- }
1115
-
1116
- // Wait for `[data-starting-style]` to have been removed.
1117
- const attributeObserver = new MutationObserver(() => {
1118
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1119
- attributeObserver.disconnect();
1120
- exec();
1121
- }
1122
- });
1123
- attributeObserver.observe(resolvedElement, {
1124
- attributes: true,
1125
- attributeFilter: [startingStyleAttribute]
1126
- });
1127
- signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
1128
- once: true
1129
- });
1130
- }
1131
- function exec() {
1132
- Promise.all(resolvedElement.getAnimations().map(anim => anim.finished)).then(() => {
1133
- if (signal?.aborted) {
1134
- return;
1135
- }
1151
+ return;
1152
+ }
1153
+ function exec() {
1154
+ Promise.all(resolvedElement.getAnimations().map(animation => animation.finished)).then(() => {
1155
+ if (!signal?.aborted) {
1136
1156
  done();
1137
- }).catch(() => {
1138
- const currentAnimations = resolvedElement.getAnimations();
1139
- if (treatAbortedAsFinished) {
1140
- if (signal?.aborted) {
1141
- return;
1142
- }
1157
+ }
1158
+ }).catch(() => {
1159
+ if (treatAbortedAsFinished) {
1160
+ if (!signal?.aborted) {
1143
1161
  done();
1144
- } else if (currentAnimations.length > 0 && currentAnimations.some(anim => anim.pending || anim.playState !== 'finished')) {
1145
- // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
1146
- // In such cases, we need to re-check if any new animations have started.
1147
- exec();
1148
1162
  }
1149
- });
1150
- }
1151
- if (waitForStartingStyleRemoved) {
1152
- execWaitForStartingStyleRemoved();
1163
+ return;
1164
+ }
1165
+ const currentAnimations = resolvedElement.getAnimations();
1166
+ if (!signal?.aborted && currentAnimations.length > 0 && currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
1167
+ // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
1168
+ // In such cases, we need to re-check if any new animations have started.
1169
+ exec();
1170
+ }
1171
+ });
1172
+ }
1173
+ if (waitForStartingStyleRemoved) {
1174
+ const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
1175
+
1176
+ // If `[data-starting-style]` isn't present, fall back to waiting one more frame
1177
+ // to give "open" animations a chance to be registered.
1178
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1179
+ frame.request(exec);
1153
1180
  return;
1154
1181
  }
1155
- frame.request(exec);
1182
+
1183
+ // Wait for `[data-starting-style]` to have been removed.
1184
+ const attributeObserver = new MutationObserver(() => {
1185
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
1186
+ attributeObserver.disconnect();
1187
+ exec();
1188
+ }
1189
+ });
1190
+ attributeObserver.observe(resolvedElement, {
1191
+ attributes: true,
1192
+ attributeFilter: [startingStyleAttribute]
1193
+ });
1194
+ signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
1195
+ once: true
1196
+ });
1197
+ return;
1156
1198
  }
1199
+ frame.request(exec);
1157
1200
  });
1158
1201
  }
1159
1202
 
@@ -1212,12 +1255,12 @@ function useTransitionStatus(open, enableIdleState = false, deferEndingState = f
1212
1255
  return () => {
1213
1256
  AnimationFrame.cancel(frame);
1214
1257
  };
1215
- }, [enableIdleState, open, mounted, setTransitionStatus, transitionStatus]);
1216
- return React.useMemo(() => ({
1258
+ }, [enableIdleState, open, mounted, transitionStatus]);
1259
+ return {
1217
1260
  mounted,
1218
1261
  setMounted,
1219
1262
  transitionStatus
1220
- }), [mounted, transitionStatus]);
1263
+ };
1221
1264
  }
1222
1265
 
1223
1266
  let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
@@ -1576,12 +1619,12 @@ function contains(parent, child) {
1576
1619
  }
1577
1620
  const rootNode = child.getRootNode?.();
1578
1621
 
1579
- // First, attempt with faster native method
1622
+ // First, attempt with the faster native method.
1580
1623
  if (parent.contains(child)) {
1581
1624
  return true;
1582
1625
  }
1583
1626
 
1584
- // then fallback to custom implementation with Shadow DOM support
1627
+ // Then fall back to traversing out of shadow roots when needed.
1585
1628
  if (rootNode && isShadowRoot(rootNode)) {
1586
1629
  let next = child;
1587
1630
  while (next) {
@@ -1591,8 +1634,6 @@ function contains(parent, child) {
1591
1634
  next = next.parentNode || next.host;
1592
1635
  }
1593
1636
  }
1594
-
1595
- // Give up, the result is false
1596
1637
  return false;
1597
1638
  }
1598
1639
  function getTarget(event) {
@@ -1600,10 +1641,11 @@ function getTarget(event) {
1600
1641
  return event.composedPath()[0];
1601
1642
  }
1602
1643
 
1603
- // TS thinks `event` is of type never as it assumes all browsers support
1604
- // `composedPath()`, but browsers without shadow DOM don't.
1644
+ // TS assumes `composedPath()` always exists, but older browsers without
1645
+ // shadow DOM support still fall back to `target`.
1605
1646
  return event.target;
1606
1647
  }
1648
+
1607
1649
  function isEventTargetWithin(event, node) {
1608
1650
  if (node == null) {
1609
1651
  return false;
@@ -1622,6 +1664,9 @@ function isRootElement(element) {
1622
1664
  function isTypeableElement(element) {
1623
1665
  return isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
1624
1666
  }
1667
+ function isInteractiveElement(element) {
1668
+ return element?.closest(`button,a[href],[role="button"],select,[tabindex]:not([tabindex="-1"]),${TYPEABLE_SELECTOR}`) != null;
1669
+ }
1625
1670
  function isTypeableCombobox(element) {
1626
1671
  if (!element) {
1627
1672
  return false;
@@ -1642,8 +1687,8 @@ function getFloatingFocusElement(floatingElement) {
1642
1687
  /* eslint-disable @typescript-eslint/no-loop-func */
1643
1688
 
1644
1689
  function getNodeChildren(nodes, id, onlyOpenChildren = true) {
1645
- const directChildren = nodes.filter(node => node.parentId === id && (!onlyOpenChildren || node.context?.open));
1646
- return directChildren.flatMap(child => [child, ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);
1690
+ const directChildren = nodes.filter(node => node.parentId === id);
1691
+ return directChildren.flatMap(child => [...(!onlyOpenChildren || child.context?.open ? [child] : []), ...getNodeChildren(nodes, child.id, onlyOpenChildren)]);
1647
1692
  }
1648
1693
  function getNodeAncestors(nodes, id) {
1649
1694
  let allAncestors = [];
@@ -1698,22 +1743,22 @@ function isClickLikeEvent(event) {
1698
1743
  function isDifferentGridRow(index, cols, prevRow) {
1699
1744
  return Math.floor(index / cols) !== prevRow;
1700
1745
  }
1701
- function isIndexOutOfListBounds(listRef, index) {
1702
- return index < 0 || index >= listRef.current.length;
1746
+ function isIndexOutOfListBounds(list, index) {
1747
+ return index < 0 || index >= list.length;
1703
1748
  }
1704
1749
  function getMinListIndex(listRef, disabledIndices) {
1705
- return findNonDisabledListIndex(listRef, {
1750
+ return findNonDisabledListIndex(listRef.current, {
1706
1751
  disabledIndices
1707
1752
  });
1708
1753
  }
1709
1754
  function getMaxListIndex(listRef, disabledIndices) {
1710
- return findNonDisabledListIndex(listRef, {
1755
+ return findNonDisabledListIndex(listRef.current, {
1711
1756
  decrement: true,
1712
1757
  startingIndex: listRef.current.length,
1713
1758
  disabledIndices
1714
1759
  });
1715
1760
  }
1716
- function findNonDisabledListIndex(listRef, {
1761
+ function findNonDisabledListIndex(list, {
1717
1762
  startingIndex = -1,
1718
1763
  decrement = false,
1719
1764
  disabledIndices,
@@ -1722,13 +1767,14 @@ function findNonDisabledListIndex(listRef, {
1722
1767
  let index = startingIndex;
1723
1768
  do {
1724
1769
  index += decrement ? -amount : amount;
1725
- } while (index >= 0 && index <= listRef.current.length - 1 && isListIndexDisabled(listRef, index, disabledIndices));
1770
+ } while (index >= 0 && index <= list.length - 1 && isListIndexDisabled(list, index, disabledIndices));
1726
1771
  return index;
1727
1772
  }
1728
- function getGridNavigatedIndex(listRef, {
1773
+ function getGridNavigatedIndex(list, {
1729
1774
  event,
1730
1775
  orientation,
1731
1776
  loopFocus,
1777
+ onLoop,
1732
1778
  rtl,
1733
1779
  cols,
1734
1780
  disabledIndices,
@@ -1756,7 +1802,7 @@ function getGridNavigatedIndex(listRef, {
1756
1802
  {
1757
1803
  let currentRowEl = null;
1758
1804
  let currentRowIndex = -1;
1759
- listRef.current.forEach((el, idx) => {
1805
+ list.forEach((el, idx) => {
1760
1806
  if (el == null) {
1761
1807
  return;
1762
1808
  }
@@ -1787,7 +1833,7 @@ function getGridNavigatedIndex(listRef, {
1787
1833
  }
1788
1834
  }
1789
1835
  }
1790
- const hasVirtualizedGaps = hasDomRows && visibleItemCount < listRef.current.length;
1836
+ const hasVirtualizedGaps = hasDomRows && visibleItemCount < list.length;
1791
1837
  const verticalCols = inferredDomCols || cols;
1792
1838
  const navigateVertically = direction => {
1793
1839
  if (!hasDomRows || prevIndex === -1) {
@@ -1805,11 +1851,17 @@ function getGridNavigatedIndex(listRef, {
1805
1851
  return undefined;
1806
1852
  }
1807
1853
  nextRow = nextRow < 0 ? rows.length - 1 : 0;
1854
+ if (onLoop) {
1855
+ const clampedCol = Math.min(colInRow, rows[nextRow].length - 1);
1856
+ const targetItemIndex = rows[nextRow][clampedCol] ?? rows[nextRow][0];
1857
+ const returnedItemIndex = onLoop(event, prevIndex, targetItemIndex);
1858
+ nextRow = rowIndexMap[returnedItemIndex] ?? nextRow;
1859
+ }
1808
1860
  }
1809
1861
  const targetRow = rows[nextRow];
1810
1862
  for (let col = Math.min(colInRow, targetRow.length - 1); col >= 0; col -= 1) {
1811
1863
  const candidate = targetRow[col];
1812
- if (!isListIndexDisabled(listRef, candidate, disabledIndices)) {
1864
+ if (!isListIndexDisabled(list, candidate, disabledIndices)) {
1813
1865
  return candidate;
1814
1866
  }
1815
1867
  }
@@ -1833,7 +1885,7 @@ function getGridNavigatedIndex(listRef, {
1833
1885
  }
1834
1886
  const rowEnd = Math.min(rowStart + verticalCols - 1, maxIndex);
1835
1887
  for (let candidate = Math.min(rowStart + colInRow, rowEnd); candidate >= rowStart; candidate -= 1) {
1836
- if (!isListIndexDisabled(listRef, candidate, disabledIndices)) {
1888
+ if (!isListIndexDisabled(list, candidate, disabledIndices)) {
1837
1889
  return candidate;
1838
1890
  }
1839
1891
  }
@@ -1849,7 +1901,7 @@ function getGridNavigatedIndex(listRef, {
1849
1901
  } else if (prevIndex === -1) {
1850
1902
  nextIndex = verticalDirection === 'up' ? maxIndex : minIndex;
1851
1903
  } else {
1852
- nextIndex = findNonDisabledListIndex(listRef, {
1904
+ nextIndex = findNonDisabledListIndex(list, {
1853
1905
  startingIndex: prevIndex,
1854
1906
  amount: verticalCols,
1855
1907
  decrement: verticalDirection === 'up',
@@ -1865,17 +1917,23 @@ function getGridNavigatedIndex(listRef, {
1865
1917
  } else {
1866
1918
  nextIndex = maxCol > col ? offset : offset - verticalCols;
1867
1919
  }
1920
+ if (onLoop) {
1921
+ nextIndex = onLoop(event, prevIndex, nextIndex);
1922
+ }
1868
1923
  }
1869
1924
  if (verticalDirection === 'down' && prevIndex + verticalCols > maxIndex) {
1870
- nextIndex = findNonDisabledListIndex(listRef, {
1925
+ nextIndex = findNonDisabledListIndex(list, {
1871
1926
  startingIndex: prevIndex % verticalCols - verticalCols,
1872
1927
  amount: verticalCols,
1873
1928
  disabledIndices
1874
1929
  });
1930
+ if (onLoop) {
1931
+ nextIndex = onLoop(event, prevIndex, nextIndex);
1932
+ }
1875
1933
  }
1876
1934
  }
1877
1935
  }
1878
- if (isIndexOutOfListBounds(listRef, nextIndex)) {
1936
+ if (isIndexOutOfListBounds(list, nextIndex)) {
1879
1937
  nextIndex = prevIndex;
1880
1938
  }
1881
1939
  }
@@ -1888,21 +1946,27 @@ function getGridNavigatedIndex(listRef, {
1888
1946
  stopEvent(event);
1889
1947
  }
1890
1948
  if (prevIndex % cols !== cols - 1) {
1891
- nextIndex = findNonDisabledListIndex(listRef, {
1949
+ nextIndex = findNonDisabledListIndex(list, {
1892
1950
  startingIndex: prevIndex,
1893
1951
  disabledIndices
1894
1952
  });
1895
1953
  if (loopFocus && isDifferentGridRow(nextIndex, cols, prevRow)) {
1896
- nextIndex = findNonDisabledListIndex(listRef, {
1954
+ nextIndex = findNonDisabledListIndex(list, {
1897
1955
  startingIndex: prevIndex - prevIndex % cols - 1,
1898
1956
  disabledIndices
1899
1957
  });
1958
+ if (onLoop) {
1959
+ nextIndex = onLoop(event, prevIndex, nextIndex);
1960
+ }
1900
1961
  }
1901
1962
  } else if (loopFocus) {
1902
- nextIndex = findNonDisabledListIndex(listRef, {
1963
+ nextIndex = findNonDisabledListIndex(list, {
1903
1964
  startingIndex: prevIndex - prevIndex % cols - 1,
1904
1965
  disabledIndices
1905
1966
  });
1967
+ if (onLoop) {
1968
+ nextIndex = onLoop(event, prevIndex, nextIndex);
1969
+ }
1906
1970
  }
1907
1971
  if (isDifferentGridRow(nextIndex, cols, prevRow)) {
1908
1972
  nextIndex = prevIndex;
@@ -1913,36 +1977,45 @@ function getGridNavigatedIndex(listRef, {
1913
1977
  stopEvent(event);
1914
1978
  }
1915
1979
  if (prevIndex % cols !== 0) {
1916
- nextIndex = findNonDisabledListIndex(listRef, {
1980
+ nextIndex = findNonDisabledListIndex(list, {
1917
1981
  startingIndex: prevIndex,
1918
1982
  decrement: true,
1919
1983
  disabledIndices
1920
1984
  });
1921
1985
  if (loopFocus && isDifferentGridRow(nextIndex, cols, prevRow)) {
1922
- nextIndex = findNonDisabledListIndex(listRef, {
1986
+ nextIndex = findNonDisabledListIndex(list, {
1923
1987
  startingIndex: prevIndex + (cols - prevIndex % cols),
1924
1988
  decrement: true,
1925
1989
  disabledIndices
1926
1990
  });
1991
+ if (onLoop) {
1992
+ nextIndex = onLoop(event, prevIndex, nextIndex);
1993
+ }
1927
1994
  }
1928
1995
  } else if (loopFocus) {
1929
- nextIndex = findNonDisabledListIndex(listRef, {
1996
+ nextIndex = findNonDisabledListIndex(list, {
1930
1997
  startingIndex: prevIndex + (cols - prevIndex % cols),
1931
1998
  decrement: true,
1932
1999
  disabledIndices
1933
2000
  });
2001
+ if (onLoop) {
2002
+ nextIndex = onLoop(event, prevIndex, nextIndex);
2003
+ }
1934
2004
  }
1935
2005
  if (isDifferentGridRow(nextIndex, cols, prevRow)) {
1936
2006
  nextIndex = prevIndex;
1937
2007
  }
1938
2008
  }
1939
2009
  const lastRow = floor(maxIndex / cols) === prevRow;
1940
- if (isIndexOutOfListBounds(listRef, nextIndex)) {
2010
+ if (isIndexOutOfListBounds(list, nextIndex)) {
1941
2011
  if (loopFocus && lastRow) {
1942
- nextIndex = event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT) ? maxIndex : findNonDisabledListIndex(listRef, {
2012
+ nextIndex = event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT) ? maxIndex : findNonDisabledListIndex(list, {
1943
2013
  startingIndex: prevIndex - prevIndex % cols - 1,
1944
2014
  disabledIndices
1945
2015
  });
2016
+ if (onLoop) {
2017
+ nextIndex = onLoop(event, prevIndex, nextIndex);
2018
+ }
1946
2019
  } else {
1947
2020
  nextIndex = prevIndex;
1948
2021
  }
@@ -2013,12 +2086,12 @@ function getGridCellIndexOfCorner(index, sizes, cellMap, cols, corner) {
2013
2086
  function getGridCellIndices(indices, cellMap) {
2014
2087
  return cellMap.flatMap((index, cellIndex) => indices.includes(index) ? [cellIndex] : []);
2015
2088
  }
2016
- function isListIndexDisabled(listRef, index, disabledIndices) {
2089
+ function isListIndexDisabled(list, index, disabledIndices) {
2017
2090
  const isExplicitlyDisabled = typeof disabledIndices === 'function' ? disabledIndices(index) : disabledIndices?.includes(index) ?? false;
2018
2091
  if (isExplicitlyDisabled) {
2019
2092
  return true;
2020
2093
  }
2021
- const element = listRef.current[index];
2094
+ const element = list[index];
2022
2095
  if (!element) {
2023
2096
  return false;
2024
2097
  }
@@ -2028,599 +2101,137 @@ function isListIndexDisabled(listRef, index, disabledIndices) {
2028
2101
  return !disabledIndices && (element.hasAttribute('disabled') || element.getAttribute('aria-disabled') === 'true');
2029
2102
  }
2030
2103
  function isElementVisible(element) {
2031
- return getComputedStyle$1(element).display !== 'none';
2032
- }
2033
-
2034
- /*!
2035
- * tabbable 6.4.0
2036
- * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
2037
- */
2038
- // NOTE: separate `:not()` selectors has broader browser support than the newer
2039
- // `:not([inert], [inert] *)` (Feb 2023)
2040
- var candidateSelectors = ['input:not([inert]):not([inert] *)', 'select:not([inert]):not([inert] *)', 'textarea:not([inert]):not([inert] *)', 'a[href]:not([inert]):not([inert] *)', 'button:not([inert]):not([inert] *)', '[tabindex]:not(slot):not([inert]):not([inert] *)', 'audio[controls]:not([inert]):not([inert] *)', 'video[controls]:not([inert]):not([inert] *)', '[contenteditable]:not([contenteditable="false"]):not([inert]):not([inert] *)', 'details>summary:first-of-type:not([inert]):not([inert] *)', 'details:not([inert]):not([inert] *)'];
2041
- var candidateSelector = /* #__PURE__ */candidateSelectors.join(',');
2042
- var NoElement = typeof Element === 'undefined';
2043
- var matches = NoElement ? function () {} : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
2044
- var getRootNode = !NoElement && Element.prototype.getRootNode ? function (element) {
2045
- var _element$getRootNode;
2046
- return element === null || element === void 0 ? void 0 : (_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element);
2047
- } : function (element) {
2048
- return element === null || element === void 0 ? void 0 : element.ownerDocument;
2049
- };
2050
-
2051
- /**
2052
- * Determines if a node is inert or in an inert ancestor.
2053
- * @param {Node} [node]
2054
- * @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to
2055
- * see if any of them are inert. If false, only `node` itself is considered.
2056
- * @returns {boolean} True if inert itself or by way of being in an inert ancestor.
2057
- * False if `node` is falsy.
2058
- */
2059
- var _isInert = function isInert(node, lookUp) {
2060
- var _node$getAttribute;
2061
- if (lookUp === void 0) {
2062
- lookUp = true;
2063
- }
2064
- // CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert`
2065
- // JS API property; we have to check the attribute, which can either be empty or 'true';
2066
- // if it's `null` (not specified) or 'false', it's an active element
2067
- var inertAtt = node === null || node === void 0 ? void 0 : (_node$getAttribute = node.getAttribute) === null || _node$getAttribute === void 0 ? void 0 : _node$getAttribute.call(node, 'inert');
2068
- var inert = inertAtt === '' || inertAtt === 'true';
2069
-
2070
- // NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`
2071
- // if it weren't for `matches()` not being a function on shadow roots; the following
2072
- // code works for any kind of node
2073
- var result = inert || lookUp && node && (
2074
- // closest does not exist on shadow roots, so we fall back to a manual
2075
- // lookup upward, in case it is not defined.
2076
- typeof node.closest === 'function' ? node.closest('[inert]') : _isInert(node.parentNode));
2077
- return result;
2078
- };
2079
-
2080
- /**
2081
- * Determines if a node's content is editable.
2082
- * @param {Element} [node]
2083
- * @returns True if it's content-editable; false if it's not or `node` is falsy.
2084
- */
2085
- var isContentEditable = function isContentEditable(node) {
2086
- var _node$getAttribute2;
2087
- // CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have
2088
- // to use the attribute directly to check for this, which can either be empty or 'true';
2089
- // if it's `null` (not specified) or 'false', it's a non-editable element
2090
- var attValue = node === null || node === void 0 ? void 0 : (_node$getAttribute2 = node.getAttribute) === null || _node$getAttribute2 === void 0 ? void 0 : _node$getAttribute2.call(node, 'contenteditable');
2091
- return attValue === '' || attValue === 'true';
2092
- };
2093
-
2094
- /**
2095
- * @param {Element} el container to check in
2096
- * @param {boolean} includeContainer add container to check
2097
- * @param {(node: Element) => boolean} filter filter candidates
2098
- * @returns {Element[]}
2099
- */
2100
- var getCandidates = function getCandidates(el, includeContainer, filter) {
2101
- // even if `includeContainer=false`, we still have to check it for inertness because
2102
- // if it's inert (either by itself or via its parent), then all its children are inert
2103
- if (_isInert(el)) {
2104
- return [];
2105
- }
2106
- var candidates = Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));
2107
- if (includeContainer && matches.call(el, candidateSelector)) {
2108
- candidates.unshift(el);
2109
- }
2110
- candidates = candidates.filter(filter);
2111
- return candidates;
2112
- };
2113
-
2114
- /**
2115
- * @callback GetShadowRoot
2116
- * @param {Element} element to check for shadow root
2117
- * @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.
2118
- */
2119
-
2120
- /**
2121
- * @callback ShadowRootFilter
2122
- * @param {Element} shadowHostNode the element which contains shadow content
2123
- * @returns {boolean} true if a shadow root could potentially contain valid candidates.
2124
- */
2125
-
2126
- /**
2127
- * @typedef {Object} CandidateScope
2128
- * @property {Element} scopeParent contains inner candidates
2129
- * @property {Element[]} candidates list of candidates found in the scope parent
2130
- */
2131
-
2132
- /**
2133
- * @typedef {Object} IterativeOptions
2134
- * @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;
2135
- * if a function, implies shadow support is enabled and either returns the shadow root of an element
2136
- * or a boolean stating if it has an undisclosed shadow root
2137
- * @property {(node: Element) => boolean} filter filter candidates
2138
- * @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list
2139
- * @property {ShadowRootFilter} shadowRootFilter filter shadow roots;
2140
- */
2141
-
2142
- /**
2143
- * @param {Element[]} elements list of element containers to match candidates from
2144
- * @param {boolean} includeContainer add container list to check
2145
- * @param {IterativeOptions} options
2146
- * @returns {Array.<Element|CandidateScope>}
2147
- */
2148
- var _getCandidatesIteratively = function getCandidatesIteratively(elements, includeContainer, options) {
2149
- var candidates = [];
2150
- var elementsToCheck = Array.from(elements);
2151
- while (elementsToCheck.length) {
2152
- var element = elementsToCheck.shift();
2153
- if (_isInert(element, false)) {
2154
- // no need to look up since we're drilling down
2155
- // anything inside this container will also be inert
2156
- continue;
2157
- }
2158
- if (element.tagName === 'SLOT') {
2159
- // add shadow dom slot scope (slot itself cannot be focusable)
2160
- var assigned = element.assignedElements();
2161
- var content = assigned.length ? assigned : element.children;
2162
- var nestedCandidates = _getCandidatesIteratively(content, true, options);
2163
- if (options.flatten) {
2164
- candidates.push.apply(candidates, nestedCandidates);
2165
- } else {
2166
- candidates.push({
2167
- scopeParent: element,
2168
- candidates: nestedCandidates
2169
- });
2170
- }
2171
- } else {
2172
- // check candidate element
2173
- var validCandidate = matches.call(element, candidateSelector);
2174
- if (validCandidate && options.filter(element) && (includeContainer || !elements.includes(element))) {
2175
- candidates.push(element);
2176
- }
2177
-
2178
- // iterate over shadow content if possible
2179
- var shadowRoot = element.shadowRoot ||
2180
- // check for an undisclosed shadow
2181
- typeof options.getShadowRoot === 'function' && options.getShadowRoot(element);
2182
-
2183
- // no inert look up because we're already drilling down and checking for inertness
2184
- // on the way down, so all containers to this root node should have already been
2185
- // vetted as non-inert
2186
- var validShadowRoot = !_isInert(shadowRoot, false) && (!options.shadowRootFilter || options.shadowRootFilter(element));
2187
- if (shadowRoot && validShadowRoot) {
2188
- // add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed
2189
- // shadow exists, so look at light dom children as fallback BUT create a scope for any
2190
- // child candidates found because they're likely slotted elements (elements that are
2191
- // children of the web component element (which has the shadow), in the light dom, but
2192
- // slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below,
2193
- // _after_ we return from this recursive call
2194
- var _nestedCandidates = _getCandidatesIteratively(shadowRoot === true ? element.children : shadowRoot.children, true, options);
2195
- if (options.flatten) {
2196
- candidates.push.apply(candidates, _nestedCandidates);
2197
- } else {
2198
- candidates.push({
2199
- scopeParent: element,
2200
- candidates: _nestedCandidates
2201
- });
2202
- }
2203
- } else {
2204
- // there's not shadow so just dig into the element's (light dom) children
2205
- // __without__ giving the element special scope treatment
2206
- elementsToCheck.unshift.apply(elementsToCheck, element.children);
2207
- }
2208
- }
2104
+ if (typeof element.checkVisibility === 'function') {
2105
+ return element.checkVisibility();
2209
2106
  }
2210
- return candidates;
2211
- };
2107
+ return getComputedStyle(element).display !== 'none';
2108
+ }
2212
2109
 
2213
- /**
2214
- * @private
2215
- * Determines if the node has an explicitly specified `tabindex` attribute.
2216
- * @param {HTMLElement} node
2217
- * @returns {boolean} True if so; false if not.
2218
- */
2219
- var hasTabIndex = function hasTabIndex(node) {
2220
- return !isNaN(parseInt(node.getAttribute('tabindex'), 10));
2221
- };
2110
+ function ownerDocument(node) {
2111
+ return node?.ownerDocument || document;
2112
+ }
2222
2113
 
2223
- /**
2224
- * Determine the tab index of a given node.
2225
- * @param {HTMLElement} node
2226
- * @returns {number} Tab order (negative, 0, or positive number).
2227
- * @throws {Error} If `node` is falsy.
2228
- */
2229
- var getTabIndex = function getTabIndex(node) {
2230
- if (!node) {
2231
- throw new Error('No node provided');
2232
- }
2233
- if (node.tabIndex < 0) {
2234
- // in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default
2235
- // `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,
2236
- // yet they are still part of the regular tab order; in FF, they get a default
2237
- // `tabIndex` of 0; since Chrome still puts those elements in the regular tab
2238
- // order, consider their tab index to be 0.
2239
- // Also browsers do not return `tabIndex` correctly for contentEditable nodes;
2240
- // so if they don't have a tabindex attribute specifically set, assume it's 0.
2241
- if ((/^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || isContentEditable(node)) && !hasTabIndex(node)) {
2242
- return 0;
2243
- }
2114
+ const CANDIDATE_SELECTOR = 'a[href],button,input,select,textarea,summary,details,iframe,object,embed,[tabindex],[contenteditable]:not([contenteditable="false"]),audio[controls],video[controls]';
2115
+ function getParentElement(element) {
2116
+ const assignedSlot = element.assignedSlot;
2117
+ if (assignedSlot) {
2118
+ return assignedSlot;
2244
2119
  }
2245
- return node.tabIndex;
2246
- };
2247
-
2248
- /**
2249
- * Determine the tab index of a given node __for sort order purposes__.
2250
- * @param {HTMLElement} node
2251
- * @param {boolean} [isScope] True for a custom element with shadow root or slot that, by default,
2252
- * has tabIndex -1, but needs to be sorted by document order in order for its content to be
2253
- * inserted into the correct sort position.
2254
- * @returns {number} Tab order (negative, 0, or positive number).
2255
- */
2256
- var getSortOrderTabIndex = function getSortOrderTabIndex(node, isScope) {
2257
- var tabIndex = getTabIndex(node);
2258
- if (tabIndex < 0 && isScope && !hasTabIndex(node)) {
2259
- return 0;
2120
+ if (element.parentElement) {
2121
+ return element.parentElement;
2260
2122
  }
2261
- return tabIndex;
2262
- };
2263
- var sortOrderedTabbables = function sortOrderedTabbables(a, b) {
2264
- return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
2265
- };
2266
- var isInput = function isInput(node) {
2267
- return node.tagName === 'INPUT';
2268
- };
2269
- var isHiddenInput = function isHiddenInput(node) {
2270
- return isInput(node) && node.type === 'hidden';
2271
- };
2272
- var isDetailsWithSummary = function isDetailsWithSummary(node) {
2273
- var r = node.tagName === 'DETAILS' && Array.prototype.slice.apply(node.children).some(function (child) {
2274
- return child.tagName === 'SUMMARY';
2275
- });
2276
- return r;
2277
- };
2278
- var getCheckedRadio = function getCheckedRadio(nodes, form) {
2279
- for (var i = 0; i < nodes.length; i++) {
2280
- if (nodes[i].checked && nodes[i].form === form) {
2281
- return nodes[i];
2123
+ const rootNode = element.getRootNode();
2124
+ return isShadowRoot(rootNode) ? rootNode.host : null;
2125
+ }
2126
+ function getDetailsSummary(details) {
2127
+ for (const child of Array.from(details.children)) {
2128
+ if (getNodeName(child) === 'summary') {
2129
+ return child;
2282
2130
  }
2283
2131
  }
2284
- };
2285
- var isTabbableRadio = function isTabbableRadio(node) {
2286
- if (!node.name) {
2287
- return true;
2132
+ return null;
2133
+ }
2134
+ function isWithinOpenDetailsSummary(element, details) {
2135
+ const summary = getDetailsSummary(details);
2136
+ return !!summary && (element === summary || contains(summary, element));
2137
+ }
2138
+ function isFocusableCandidate(element) {
2139
+ const nodeName = element ? getNodeName(element) : '';
2140
+ return element != null && element.matches(CANDIDATE_SELECTOR) && (nodeName !== 'summary' || element.parentElement != null && getNodeName(element.parentElement) === 'details' && getDetailsSummary(element.parentElement) === element) && (nodeName !== 'details' || getDetailsSummary(element) == null) && (nodeName !== 'input' || element.type !== 'hidden');
2141
+ }
2142
+ function isFocusableElement(element) {
2143
+ if (!isFocusableCandidate(element) || !element.isConnected || element.matches(':disabled')) {
2144
+ return false;
2288
2145
  }
2289
- var radioScope = node.form || getRootNode(node);
2290
- var queryRadios = function queryRadios(name) {
2291
- return radioScope.querySelectorAll('input[type="radio"][name="' + name + '"]');
2292
- };
2293
- var radioSet;
2294
- if (typeof window !== 'undefined' && typeof window.CSS !== 'undefined' && typeof window.CSS.escape === 'function') {
2295
- radioSet = queryRadios(window.CSS.escape(node.name));
2296
- } else {
2297
- try {
2298
- radioSet = queryRadios(node.name);
2299
- } catch (err) {
2300
- // eslint-disable-next-line no-console
2301
- console.error('Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s', err.message);
2146
+ for (let current = element; current; current = getParentElement(current)) {
2147
+ const isSlot = getNodeName(current) === 'slot';
2148
+ if (current.hasAttribute('inert')) {
2302
2149
  return false;
2303
2150
  }
2304
- }
2305
- var checked = getCheckedRadio(radioSet, node.form);
2306
- return !checked || checked === node;
2307
- };
2308
- var isRadio = function isRadio(node) {
2309
- return isInput(node) && node.type === 'radio';
2310
- };
2311
- var isNonTabbableRadio = function isNonTabbableRadio(node) {
2312
- return isRadio(node) && !isTabbableRadio(node);
2313
- };
2314
-
2315
- // determines if a node is ultimately attached to the window's document
2316
- var isNodeAttached = function isNodeAttached(node) {
2317
- var _nodeRoot;
2318
- // The root node is the shadow root if the node is in a shadow DOM; some document otherwise
2319
- // (but NOT _the_ document; see second 'If' comment below for more).
2320
- // If rootNode is shadow root, it'll have a host, which is the element to which the shadow
2321
- // is attached, and the one we need to check if it's in the document or not (because the
2322
- // shadow, and all nodes it contains, is never considered in the document since shadows
2323
- // behave like self-contained DOMs; but if the shadow's HOST, which is part of the document,
2324
- // is hidden, or is not in the document itself but is detached, it will affect the shadow's
2325
- // visibility, including all the nodes it contains). The host could be any normal node,
2326
- // or a custom element (i.e. web component). Either way, that's the one that is considered
2327
- // part of the document, not the shadow root, nor any of its children (i.e. the node being
2328
- // tested).
2329
- // To further complicate things, we have to look all the way up until we find a shadow HOST
2330
- // that is attached (or find none) because the node might be in nested shadows...
2331
- // If rootNode is not a shadow root, it won't have a host, and so rootNode should be the
2332
- // document (per the docs) and while it's a Document-type object, that document does not
2333
- // appear to be the same as the node's `ownerDocument` for some reason, so it's safer
2334
- // to ignore the rootNode at this point, and use `node.ownerDocument`. Otherwise,
2335
- // using `rootNode.contains(node)` will _always_ be true we'll get false-positives when
2336
- // node is actually detached.
2337
- // NOTE: If `nodeRootHost` or `node` happens to be the `document` itself (which is possible
2338
- // if a tabbable/focusable node was quickly added to the DOM, focused, and then removed
2339
- // from the DOM as in https://github.com/focus-trap/focus-trap-react/issues/905), then
2340
- // `ownerDocument` will be `null`, hence the optional chaining on it.
2341
- var nodeRoot = node && getRootNode(node);
2342
- var nodeRootHost = (_nodeRoot = nodeRoot) === null || _nodeRoot === void 0 ? void 0 : _nodeRoot.host;
2343
-
2344
- // in some cases, a detached node will return itself as the root instead of a document or
2345
- // shadow root object, in which case, we shouldn't try to look further up the host chain
2346
- var attached = false;
2347
- if (nodeRoot && nodeRoot !== node) {
2348
- var _nodeRootHost, _nodeRootHost$ownerDo, _node$ownerDocument;
2349
- attached = !!((_nodeRootHost = nodeRootHost) !== null && _nodeRootHost !== void 0 && (_nodeRootHost$ownerDo = _nodeRootHost.ownerDocument) !== null && _nodeRootHost$ownerDo !== void 0 && _nodeRootHost$ownerDo.contains(nodeRootHost) || node !== null && node !== void 0 && (_node$ownerDocument = node.ownerDocument) !== null && _node$ownerDocument !== void 0 && _node$ownerDocument.contains(node));
2350
- while (!attached && nodeRootHost) {
2351
- var _nodeRoot2, _nodeRootHost2, _nodeRootHost2$ownerD;
2352
- // since it's not attached and we have a root host, the node MUST be in a nested shadow DOM,
2353
- // which means we need to get the host's host and check if that parent host is contained
2354
- // in (i.e. attached to) the document
2355
- nodeRoot = getRootNode(nodeRootHost);
2356
- nodeRootHost = (_nodeRoot2 = nodeRoot) === null || _nodeRoot2 === void 0 ? void 0 : _nodeRoot2.host;
2357
- attached = !!((_nodeRootHost2 = nodeRootHost) !== null && _nodeRootHost2 !== void 0 && (_nodeRootHost2$ownerD = _nodeRootHost2.ownerDocument) !== null && _nodeRootHost2$ownerD !== void 0 && _nodeRootHost2$ownerD.contains(nodeRootHost));
2358
- }
2359
- }
2360
- return attached;
2361
- };
2362
- var isZeroArea = function isZeroArea(node) {
2363
- var _node$getBoundingClie = node.getBoundingClientRect(),
2364
- width = _node$getBoundingClie.width,
2365
- height = _node$getBoundingClie.height;
2366
- return width === 0 && height === 0;
2367
- };
2368
- var isHidden = function isHidden(node, _ref) {
2369
- var displayCheck = _ref.displayCheck,
2370
- getShadowRoot = _ref.getShadowRoot;
2371
- if (displayCheck === 'full-native') {
2372
- if ('checkVisibility' in node) {
2373
- // Chrome >= 105, Edge >= 105, Firefox >= 106, Safari >= 17.4
2374
- // @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility#browser_compatibility
2375
- var visible = node.checkVisibility({
2376
- // Checking opacity might be desirable for some use cases, but natively,
2377
- // opacity zero elements _are_ focusable and tabbable.
2378
- checkOpacity: false,
2379
- opacityProperty: false,
2380
- contentVisibilityAuto: true,
2381
- visibilityProperty: true,
2382
- // This is an alias for `visibilityProperty`. Contemporary browsers
2383
- // support both. However, this alias has wider browser support (Chrome
2384
- // >= 105 and Firefox >= 106, vs. Chrome >= 121 and Firefox >= 122), so
2385
- // we include it anyway.
2386
- checkVisibilityCSS: true
2387
- });
2388
- return !visible;
2151
+ if (current !== element && getNodeName(current) === 'details' && !current.open && !isWithinOpenDetailsSummary(element, current) || current.hasAttribute('hidden') || !isSlot && !isElementVisible(current)) {
2152
+ return false;
2389
2153
  }
2390
- // Fall through to manual visibility checks
2391
- }
2392
-
2393
- // NOTE: visibility will be `undefined` if node is detached from the document
2394
- // (see notes about this further down), which means we will consider it visible
2395
- // (this is legacy behavior from a very long way back)
2396
- // NOTE: we check this regardless of `displayCheck="none"` because this is a
2397
- // _visibility_ check, not a _display_ check
2398
- if (getComputedStyle(node).visibility === 'hidden') {
2399
- return true;
2400
- }
2401
- var isDirectSummary = matches.call(node, 'details>summary:first-of-type');
2402
- var nodeUnderDetails = isDirectSummary ? node.parentElement : node;
2403
- if (matches.call(nodeUnderDetails, 'details:not([open]) *')) {
2404
- return true;
2405
2154
  }
2406
- if (!displayCheck || displayCheck === 'full' ||
2407
- // full-native can run this branch when it falls through in case
2408
- // Element#checkVisibility is unsupported
2409
- displayCheck === 'full-native' || displayCheck === 'legacy-full') {
2410
- if (typeof getShadowRoot === 'function') {
2411
- // figure out if we should consider the node to be in an undisclosed shadow and use the
2412
- // 'non-zero-area' fallback
2413
- var originalNode = node;
2414
- while (node) {
2415
- var parentElement = node.parentElement;
2416
- var rootNode = getRootNode(node);
2417
- if (parentElement && !parentElement.shadowRoot && getShadowRoot(parentElement) === true // check if there's an undisclosed shadow
2418
- ) {
2419
- // node has an undisclosed shadow which means we can only treat it as a black box, so we
2420
- // fall back to a non-zero-area test
2421
- return isZeroArea(node);
2422
- } else if (node.assignedSlot) {
2423
- // iterate up slot
2424
- node = node.assignedSlot;
2425
- } else if (!parentElement && rootNode !== node.ownerDocument) {
2426
- // cross shadow boundary
2427
- node = rootNode.host;
2428
- } else {
2429
- // iterate up normal dom
2430
- node = parentElement;
2431
- }
2432
- }
2433
- node = originalNode;
2434
- }
2435
- // else, `getShadowRoot` might be true, but all that does is enable shadow DOM support
2436
- // (i.e. it does not also presume that all nodes might have undisclosed shadows); or
2437
- // it might be a falsy value, which means shadow DOM support is disabled
2438
-
2439
- // Since we didn't find it sitting in an undisclosed shadow (or shadows are disabled)
2440
- // now we can just test to see if it would normally be visible or not, provided it's
2441
- // attached to the main document.
2442
- // NOTE: We must consider case where node is inside a shadow DOM and given directly to
2443
- // `isTabbable()` or `isFocusable()` -- regardless of `getShadowRoot` option setting.
2444
-
2445
- if (isNodeAttached(node)) {
2446
- // this works wherever the node is: if there's at least one client rect, it's
2447
- // somehow displayed; it also covers the CSS 'display: contents' case where the
2448
- // node itself is hidden in place of its contents; and there's no need to search
2449
- // up the hierarchy either
2450
- return !node.getClientRects().length;
2451
- }
2452
-
2453
- // Else, the node isn't attached to the document, which means the `getClientRects()`
2454
- // API will __always__ return zero rects (this can happen, for example, if React
2455
- // is used to render nodes onto a detached tree, as confirmed in this thread:
2456
- // https://github.com/facebook/react/issues/9117#issuecomment-284228870)
2457
- //
2458
- // It also means that even window.getComputedStyle(node).display will return `undefined`
2459
- // because styles are only computed for nodes that are in the document.
2460
- //
2461
- // NOTE: THIS HAS BEEN THE CASE FOR YEARS. It is not new, nor is it caused by tabbable
2462
- // somehow. Though it was never stated officially, anyone who has ever used tabbable
2463
- // APIs on nodes in detached containers has actually implicitly used tabbable in what
2464
- // was later (as of v5.2.0 on Apr 9, 2021) called `displayCheck="none"` mode -- essentially
2465
- // considering __everything__ to be visible because of the innability to determine styles.
2466
- //
2467
- // v6.0.0: As of this major release, the default 'full' option __no longer treats detached
2468
- // nodes as visible with the 'none' fallback.__
2469
- if (displayCheck !== 'legacy-full') {
2470
- return true; // hidden
2471
- }
2472
- // else, fallback to 'none' mode and consider the node visible
2473
- } else if (displayCheck === 'non-zero-area') {
2474
- // NOTE: Even though this tests that the node's client rect is non-zero to determine
2475
- // whether it's displayed, and that a detached node will __always__ have a zero-area
2476
- // client rect, we don't special-case for whether the node is attached or not. In
2477
- // this mode, we do want to consider nodes that have a zero area to be hidden at all
2478
- // times, and that includes attached or not.
2479
- return isZeroArea(node);
2480
- }
2481
-
2482
- // visible, as far as we can tell, or per current `displayCheck=none` mode, we assume
2483
- // it's visible
2484
- return false;
2485
- };
2486
-
2487
- // form fields (nested) inside a disabled fieldset are not focusable/tabbable
2488
- // unless they are in the _first_ <legend> element of the top-most disabled
2489
- // fieldset
2490
- var isDisabledFromFieldset = function isDisabledFromFieldset(node) {
2491
- if (/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)) {
2492
- var parentNode = node.parentElement;
2493
- // check if `node` is contained in a disabled <fieldset>
2494
- while (parentNode) {
2495
- if (parentNode.tagName === 'FIELDSET' && parentNode.disabled) {
2496
- // look for the first <legend> among the children of the disabled <fieldset>
2497
- for (var i = 0; i < parentNode.children.length; i++) {
2498
- var child = parentNode.children.item(i);
2499
- // when the first <legend> (in document order) is found
2500
- if (child.tagName === 'LEGEND') {
2501
- // if its parent <fieldset> is not nested in another disabled <fieldset>,
2502
- // return whether `node` is a descendant of its first <legend>
2503
- return matches.call(parentNode, 'fieldset[disabled] *') ? true : !child.contains(node);
2504
- }
2505
- }
2506
- // the disabled <fieldset> containing `node` has no <legend>
2507
- return true;
2508
- }
2509
- parentNode = parentNode.parentElement;
2155
+ return true;
2156
+ }
2157
+ function getTabIndex(element) {
2158
+ const tabIndex = element.tabIndex;
2159
+ if (tabIndex < 0) {
2160
+ const nodeName = getNodeName(element);
2161
+ if (nodeName === 'details' || nodeName === 'audio' || nodeName === 'video' || isHTMLElement(element) && element.isContentEditable) {
2162
+ return 0;
2510
2163
  }
2511
2164
  }
2512
-
2513
- // else, node's tabbable/focusable state should not be affected by a fieldset's
2514
- // enabled/disabled state
2515
- return false;
2516
- };
2517
- var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(options, node) {
2518
- if (node.disabled || isHiddenInput(node) || isHidden(node, options) ||
2519
- // For a details element with a summary, the summary element gets the focus
2520
- isDetailsWithSummary(node) || isDisabledFromFieldset(node)) {
2521
- return false;
2522
- }
2523
- return true;
2524
- };
2525
- var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable(options, node) {
2526
- if (isNonTabbableRadio(node) || getTabIndex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) {
2527
- return false;
2165
+ return tabIndex;
2166
+ }
2167
+ function getNamedRadioInput(element) {
2168
+ if (getNodeName(element) !== 'input') {
2169
+ return null;
2528
2170
  }
2529
- return true;
2530
- };
2531
- var isShadowRootTabbable = function isShadowRootTabbable(shadowHostNode) {
2532
- var tabIndex = parseInt(shadowHostNode.getAttribute('tabindex'), 10);
2533
- if (isNaN(tabIndex) || tabIndex >= 0) {
2171
+ const input = element;
2172
+ return input.type === 'radio' && input.name !== '' ? input : null;
2173
+ }
2174
+ function isTabbableRadio(element, candidates) {
2175
+ const input = getNamedRadioInput(element);
2176
+ if (!input) {
2534
2177
  return true;
2535
2178
  }
2536
- // If a custom element has an explicit negative tabindex,
2537
- // browsers will not allow tab targeting said element's children.
2538
- return false;
2539
- };
2540
-
2541
- /**
2542
- * @param {Array.<Element|CandidateScope>} candidates
2543
- * @returns Element[]
2544
- */
2545
- var _sortByOrder = function sortByOrder(candidates) {
2546
- var regularTabbables = [];
2547
- var orderedTabbables = [];
2548
- candidates.forEach(function (item, i) {
2549
- var isScope = !!item.scopeParent;
2550
- var element = isScope ? item.scopeParent : item;
2551
- var candidateTabindex = getSortOrderTabIndex(element, isScope);
2552
- var elements = isScope ? _sortByOrder(item.candidates) : element;
2553
- if (candidateTabindex === 0) {
2554
- isScope ? regularTabbables.push.apply(regularTabbables, elements) : regularTabbables.push(element);
2555
- } else {
2556
- orderedTabbables.push({
2557
- documentOrder: i,
2558
- tabIndex: candidateTabindex,
2559
- item: item,
2560
- isScope: isScope,
2561
- content: elements
2562
- });
2563
- }
2179
+ const checkedRadio = candidates.find(candidate => {
2180
+ const radio = getNamedRadioInput(candidate);
2181
+ return radio?.name === input.name && radio.form === input.form && radio.checked;
2564
2182
  });
2565
- return orderedTabbables.sort(sortOrderedTabbables).reduce(function (acc, sortable) {
2566
- sortable.isScope ? acc.push.apply(acc, sortable.content) : acc.push(sortable.content);
2567
- return acc;
2568
- }, []).concat(regularTabbables);
2569
- };
2570
- var tabbable = function tabbable(container, options) {
2571
- options = options || {};
2572
- var candidates;
2573
- if (options.getShadowRoot) {
2574
- candidates = _getCandidatesIteratively([container], options.includeContainer, {
2575
- filter: isNodeMatchingSelectorTabbable.bind(null, options),
2576
- flatten: false,
2577
- getShadowRoot: options.getShadowRoot,
2578
- shadowRootFilter: isShadowRootTabbable
2183
+ if (checkedRadio) {
2184
+ return checkedRadio === input;
2185
+ }
2186
+ return candidates.find(candidate => {
2187
+ const radio = getNamedRadioInput(candidate);
2188
+ return radio?.name === input.name && radio.form === input.form;
2189
+ }) === input;
2190
+ }
2191
+ function getComposedChildren(container) {
2192
+ if (isHTMLElement(container) && getNodeName(container) === 'slot') {
2193
+ const assignedElements = container.assignedElements({
2194
+ flatten: true
2579
2195
  });
2580
- } else {
2581
- candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorTabbable.bind(null, options));
2582
- }
2583
- return _sortByOrder(candidates);
2584
- };
2585
- var focusable = function focusable(container, options) {
2586
- options = options || {};
2587
- var candidates;
2588
- if (options.getShadowRoot) {
2589
- candidates = _getCandidatesIteratively([container], options.includeContainer, {
2590
- filter: isNodeMatchingSelectorFocusable.bind(null, options),
2591
- flatten: true,
2592
- getShadowRoot: options.getShadowRoot
2593
- });
2594
- } else {
2595
- candidates = getCandidates(container, options.includeContainer, isNodeMatchingSelectorFocusable.bind(null, options));
2596
- }
2597
- return candidates;
2598
- };
2599
- var isTabbable = function isTabbable(node, options) {
2600
- options = options || {};
2601
- if (!node) {
2602
- throw new Error('No node provided');
2196
+ if (assignedElements.length > 0) {
2197
+ return assignedElements;
2198
+ }
2603
2199
  }
2604
- if (matches.call(node, candidateSelector) === false) {
2605
- return false;
2200
+ if (isHTMLElement(container) && container.shadowRoot) {
2201
+ return Array.from(container.shadowRoot.children);
2606
2202
  }
2607
- return isNodeMatchingSelectorTabbable(options, node);
2608
- };
2609
-
2610
- function ownerDocument(node) {
2611
- return node?.ownerDocument || document;
2203
+ return Array.from(container.children);
2204
+ }
2205
+ function appendCandidates(container, list) {
2206
+ getComposedChildren(container).forEach(child => {
2207
+ if (isFocusableCandidate(child)) {
2208
+ list.push(child);
2209
+ }
2210
+ appendCandidates(child, list);
2211
+ });
2212
+ }
2213
+ function appendMatchingElements(container, selector, list) {
2214
+ getComposedChildren(container).forEach(child => {
2215
+ if (isHTMLElement(child) && child.matches(selector)) {
2216
+ list.push(child);
2217
+ }
2218
+ appendMatchingElements(child, selector, list);
2219
+ });
2220
+ }
2221
+ function isTabbable(element) {
2222
+ return isFocusableElement(element) && getTabIndex(element) >= 0;
2223
+ }
2224
+ function focusable(container) {
2225
+ const candidates = [];
2226
+ appendCandidates(container, candidates);
2227
+ return candidates.filter(isFocusableElement);
2228
+ }
2229
+ function tabbable(container) {
2230
+ const candidates = focusable(container);
2231
+ return candidates.filter(element => getTabIndex(element) >= 0 && isTabbableRadio(element, candidates));
2612
2232
  }
2613
-
2614
- const getTabbableOptions = () => ({
2615
- getShadowRoot: true,
2616
- displayCheck:
2617
- // JSDOM does not support the `tabbable` library. To solve this we can
2618
- // check if `ResizeObserver` is a real function (not polyfilled), which
2619
- // determines if the current environment is JSDOM-like.
2620
- typeof ResizeObserver === 'function' && ResizeObserver.toString().includes('[native code]') ? 'full' : 'none'
2621
- });
2622
2233
  function getTabbableIn(container, dir) {
2623
- const list = tabbable(container, getTabbableOptions());
2234
+ const list = tabbable(container);
2624
2235
  const len = list.length;
2625
2236
  if (len === 0) {
2626
2237
  return undefined;
@@ -2643,14 +2254,15 @@ function isOutsideEvent(event, container) {
2643
2254
  return !relatedTarget || !contains(containerElement, relatedTarget);
2644
2255
  }
2645
2256
  function disableFocusInside(container) {
2646
- const tabbableElements = tabbable(container, getTabbableOptions());
2257
+ const tabbableElements = tabbable(container);
2647
2258
  tabbableElements.forEach(element => {
2648
2259
  element.dataset.tabindex = element.getAttribute('tabindex') || '';
2649
2260
  element.setAttribute('tabindex', '-1');
2650
2261
  });
2651
2262
  }
2652
2263
  function enableFocusInside(container) {
2653
- const elements = container.querySelectorAll('[data-tabindex]');
2264
+ const elements = [];
2265
+ appendMatchingElements(container, '[data-tabindex]', elements);
2654
2266
  elements.forEach(element => {
2655
2267
  const tabindex = element.dataset.tabindex;
2656
2268
  delete element.dataset.tabindex;
@@ -2662,6 +2274,17 @@ function enableFocusInside(container) {
2662
2274
  });
2663
2275
  }
2664
2276
 
2277
+ /**
2278
+ * Adds an event listener and returns a cleanup function to remove it.
2279
+ */
2280
+
2281
+ function addEventListener(target, type, listener, options) {
2282
+ target.addEventListener(type, listener, options);
2283
+ return () => {
2284
+ target.removeEventListener(type, listener, options);
2285
+ };
2286
+ }
2287
+
2665
2288
  /**
2666
2289
  * Calls the provided function when the CSS open/close animation or transition completes.
2667
2290
  */
@@ -2686,6 +2309,14 @@ function useOpenChangeComplete(parameters) {
2686
2309
  }, [enabled, open, onComplete, runOnceAnimationsFinish]);
2687
2310
  }
2688
2311
 
2312
+ function useOnFirstRender(fn) {
2313
+ const ref = React.useRef(true);
2314
+ if (ref.current) {
2315
+ ref.current = false;
2316
+ fn();
2317
+ }
2318
+ }
2319
+
2689
2320
  const EMPTY = 0;
2690
2321
  class Timeout {
2691
2322
  static create() {
@@ -2884,16 +2515,15 @@ function preventScrollInsetScrollbars(referenceElement) {
2884
2515
  resizeFrame.request(lockScroll);
2885
2516
  }
2886
2517
  lockScroll();
2887
- win.addEventListener('resize', handleResize);
2518
+ const unsubscribeResize = addEventListener(win, 'resize', handleResize);
2888
2519
  return () => {
2889
2520
  resizeFrame.cancel();
2890
2521
  cleanup();
2891
- // Sometimes this cleanup can be run after test teardown
2892
- // because it is called in a `setTimeout(fn, 0)`,
2893
- // in which case `removeEventListener` wouldn't be available,
2894
- // so we check for it to avoid test failures.
2522
+ // Sometimes this cleanup can run after test teardown because it is called
2523
+ // in a `setTimeout(fn, 0)`. Guard the returned cleanup to avoid calling
2524
+ // `removeEventListener` when it is no longer available in tests.
2895
2525
  if (typeof win.removeEventListener === 'function') {
2896
- win.removeEventListener('resize', handleResize);
2526
+ unsubscribeResize();
2897
2527
  }
2898
2528
  };
2899
2529
  }
@@ -2962,6 +2592,20 @@ function useScrollLock(enabled = true, referenceElement = null) {
2962
2592
  }, [enabled, referenceElement]);
2963
2593
  }
2964
2594
 
2595
+ /**
2596
+ * Combines multiple cleanup functions into a single cleanup function.
2597
+ */
2598
+ function mergeCleanups(...cleanups) {
2599
+ return () => {
2600
+ for (let i = 0; i < cleanups.length; i += 1) {
2601
+ const cleanup = cleanups[i];
2602
+ if (cleanup) {
2603
+ cleanup();
2604
+ }
2605
+ }
2606
+ };
2607
+ }
2608
+
2965
2609
  /**
2966
2610
  * Untracks the provided value by turning it into a ref to remove its reactivity.
2967
2611
  *
@@ -3051,9 +2695,16 @@ function enqueueFocus(el, options = {}) {
3051
2695
  });
3052
2696
  if (sync) {
3053
2697
  exec();
3054
- } else {
3055
- rafId = requestAnimationFrame(exec);
2698
+ return NOOP;
3056
2699
  }
2700
+ const currentRafId = requestAnimationFrame(exec);
2701
+ rafId = currentRafId;
2702
+ return () => {
2703
+ if (rafId === currentRafId) {
2704
+ cancelAnimationFrame(currentRafId);
2705
+ rafId = 0;
2706
+ }
2707
+ };
3057
2708
  }
3058
2709
 
3059
2710
  // Modified to add conditional `aria-hidden` support:
@@ -3300,6 +2951,7 @@ const FloatingPortal = /*#__PURE__*/React.forwardRef(function FloatingPortal(com
3300
2951
  className,
3301
2952
  render,
3302
2953
  renderGuards,
2954
+ style,
3303
2955
  ...elementProps
3304
2956
  } = componentProps;
3305
2957
  const {
@@ -3316,6 +2968,7 @@ const FloatingPortal = /*#__PURE__*/React.forwardRef(function FloatingPortal(com
3316
2968
  const beforeInsideRef = React.useRef(null);
3317
2969
  const afterInsideRef = React.useRef(null);
3318
2970
  const [focusManagerState, setFocusManagerState] = React.useState(null);
2971
+ const focusInsideDisabledRef = React.useRef(false);
3319
2972
  const modal = focusManagerState?.modal;
3320
2973
  const open = focusManagerState?.open;
3321
2974
  const shouldRenderGuards = typeof renderGuards === 'boolean' ? renderGuards : !!focusManagerState && !focusManagerState.modal && focusManagerState.open && !!portalNode;
@@ -3331,26 +2984,28 @@ const FloatingPortal = /*#__PURE__*/React.forwardRef(function FloatingPortal(com
3331
2984
  // element outside or using the mouse.
3332
2985
  function onFocus(event) {
3333
2986
  if (portalNode && event.relatedTarget && isOutsideEvent(event)) {
3334
- const focusing = event.type === 'focusin';
3335
- const manageFocus = focusing ? enableFocusInside : disableFocusInside;
3336
- manageFocus(portalNode);
2987
+ if (event.type === 'focusin') {
2988
+ if (focusInsideDisabledRef.current) {
2989
+ enableFocusInside(portalNode);
2990
+ focusInsideDisabledRef.current = false;
2991
+ }
2992
+ } else {
2993
+ disableFocusInside(portalNode);
2994
+ focusInsideDisabledRef.current = true;
2995
+ }
3337
2996
  }
3338
2997
  }
3339
2998
 
3340
2999
  // Listen to the event on the capture phase so they run before the focus
3341
3000
  // trap elements onFocus prop is called.
3342
- portalNode.addEventListener('focusin', onFocus, true);
3343
- portalNode.addEventListener('focusout', onFocus, true);
3344
- return () => {
3345
- portalNode.removeEventListener('focusin', onFocus, true);
3346
- portalNode.removeEventListener('focusout', onFocus, true);
3347
- };
3001
+ return mergeCleanups(addEventListener(portalNode, 'focusin', onFocus, true), addEventListener(portalNode, 'focusout', onFocus, true));
3348
3002
  }, [portalNode, modal]);
3349
3003
  React.useEffect(() => {
3350
- if (!portalNode || open) {
3004
+ if (!portalNode || open !== false) {
3351
3005
  return;
3352
3006
  }
3353
3007
  enableFocusInside(portalNode);
3008
+ focusInsideDisabledRef.current = false;
3354
3009
  }, [open, portalNode]);
3355
3010
  const portalContextValue = React.useMemo(() => ({
3356
3011
  beforeOutsideRef,
@@ -3429,7 +3084,7 @@ const useFloatingTree = externalTree => {
3429
3084
  };
3430
3085
 
3431
3086
  function getEventType(event, lastInteractionType) {
3432
- const win = getWindow(event.target);
3087
+ const win = getWindow(getTarget(event));
3433
3088
  if (event instanceof win.KeyboardEvent) {
3434
3089
  return 'keyboard';
3435
3090
  }
@@ -3474,11 +3129,10 @@ function getFirstTabbableElement(container) {
3474
3129
  if (!container) {
3475
3130
  return null;
3476
3131
  }
3477
- const tabbableOptions = getTabbableOptions();
3478
- if (isTabbable(container, tabbableOptions)) {
3132
+ if (isTabbable(container)) {
3479
3133
  return container;
3480
3134
  }
3481
- return tabbable(container, tabbableOptions)[0] || container;
3135
+ return tabbable(container)[0] || container;
3482
3136
  }
3483
3137
  function isFocusable(element) {
3484
3138
  if (!element || !element.isConnected) {
@@ -3490,14 +3144,16 @@ function isFocusable(element) {
3490
3144
  return isElementVisible(element);
3491
3145
  }
3492
3146
  function handleTabIndex(floatingFocusElement, orderRef) {
3147
+ if (floatingFocusElement.hasAttribute('tabindex') && !floatingFocusElement.hasAttribute('data-tabindex')) {
3148
+ return;
3149
+ }
3493
3150
  if (!orderRef.current.includes('floating') && !floatingFocusElement.getAttribute('role')?.includes('dialog')) {
3494
3151
  return;
3495
3152
  }
3496
- const options = getTabbableOptions();
3497
- const focusableElements = focusable(floatingFocusElement, options);
3153
+ const focusableElements = focusable(floatingFocusElement);
3498
3154
  const tabbableContent = focusableElements.filter(element => {
3499
3155
  const dataTabIndex = element.getAttribute('data-tabindex') || '';
3500
- return isTabbable(element, options) || element.hasAttribute('data-tabindex') && !dataTabIndex.startsWith('-');
3156
+ return isTabbable(element) || element.hasAttribute('data-tabindex') && !dataTabIndex.startsWith('-');
3501
3157
  });
3502
3158
  const tabIndex = floatingFocusElement.getAttribute('tabindex');
3503
3159
  if (orderRef.current.includes('floating') || tabbableContent.length === 0) {
@@ -3556,7 +3212,7 @@ function FloatingFocusManager(props) {
3556
3212
  const preventReturnFocusRef = React.useRef(false);
3557
3213
  const isPointerDownRef = React.useRef(false);
3558
3214
  const pointerDownOutsideRef = React.useRef(false);
3559
- const tabbableIndexRef = React.useRef(-1);
3215
+ const lastFocusedTabbableRef = React.useRef(null);
3560
3216
  const closeTypeRef = React.useRef('');
3561
3217
  const lastInteractionTypeRef = React.useRef('');
3562
3218
  const beforeGuardRef = React.useRef(null);
@@ -3569,13 +3225,9 @@ function FloatingFocusManager(props) {
3569
3225
  const isInsidePortal = portalContext != null;
3570
3226
  const floatingFocusElement = getFloatingFocusElement(floating);
3571
3227
  const getTabbableContent = useStableCallback((container = floatingFocusElement) => {
3572
- return container ? tabbable(container, getTabbableOptions()) : [];
3228
+ return container ? tabbable(container) : [];
3573
3229
  });
3574
3230
  const getResolvedInsideElements = useStableCallback(() => getInsideElements?.().filter(element => element != null) ?? []);
3575
- const getTabbableElements = useStableCallback(container => {
3576
- const content = getTabbableContent(container);
3577
- return orderRef.current.map(() => content).filter(Boolean).flat();
3578
- });
3579
3231
 
3580
3232
  // Prevent Tab from escaping the modal when there are no tabbable elements.
3581
3233
  React.useEffect(() => {
@@ -3590,12 +3242,9 @@ function FloatingFocusManager(props) {
3590
3242
  }
3591
3243
  }
3592
3244
  }
3593
- const doc = ownerDocument(floatingFocusElement);
3594
- doc.addEventListener('keydown', onKeyDown);
3595
- return () => {
3596
- doc.removeEventListener('keydown', onKeyDown);
3597
- };
3598
- }, [disabled, domReference, floatingFocusElement, modal, orderRef, isUntrappedTypeableCombobox, getTabbableContent, getTabbableElements]);
3245
+ const doc = ownerDocument(floatingFocusElement);
3246
+ return addEventListener(doc, 'keydown', onKeyDown);
3247
+ }, [disabled, domReference, floatingFocusElement, modal, orderRef, isUntrappedTypeableCombobox, getTabbableContent]);
3599
3248
 
3600
3249
  // Track pointer/keyboard interactions to disambiguate focus and outside presses.
3601
3250
  React.useEffect(() => {
@@ -3619,16 +3268,7 @@ function FloatingFocusManager(props) {
3619
3268
  function onKeyDown() {
3620
3269
  lastInteractionTypeRef.current = 'keyboard';
3621
3270
  }
3622
- doc.addEventListener('pointerdown', onPointerDown, true);
3623
- doc.addEventListener('pointerup', clearPointerDownOutside, true);
3624
- doc.addEventListener('pointercancel', clearPointerDownOutside, true);
3625
- doc.addEventListener('keydown', onKeyDown, true);
3626
- return () => {
3627
- doc.removeEventListener('pointerdown', onPointerDown, true);
3628
- doc.removeEventListener('pointerup', clearPointerDownOutside, true);
3629
- doc.removeEventListener('pointercancel', clearPointerDownOutside, true);
3630
- doc.removeEventListener('keydown', onKeyDown, true);
3631
- };
3271
+ return mergeCleanups(addEventListener(doc, 'pointerdown', onPointerDown, true), addEventListener(doc, 'pointerup', clearPointerDownOutside, true), addEventListener(doc, 'pointercancel', clearPointerDownOutside, true), addEventListener(doc, 'keydown', onKeyDown, true));
3632
3272
  }, [disabled, floating, domReference, floatingFocusElement, open, portalContext, getResolvedInsideElements]);
3633
3273
 
3634
3274
  // Close on focus out and restore focus within the floating tree when needed.
@@ -3647,10 +3287,8 @@ function FloatingFocusManager(props) {
3647
3287
  }
3648
3288
  function handleFocusIn(event) {
3649
3289
  const target = getTarget(event);
3650
- const tabbableContent = getTabbableContent();
3651
- const tabbableIndex = tabbableContent.indexOf(target);
3652
- if (tabbableIndex !== -1) {
3653
- tabbableIndexRef.current = tabbableIndex;
3290
+ if (isTabbable(target)) {
3291
+ lastFocusedTabbableRef.current = target;
3654
3292
  }
3655
3293
  }
3656
3294
  function handleFocusOutside(event) {
@@ -3687,9 +3325,9 @@ function FloatingFocusManager(props) {
3687
3325
  return;
3688
3326
  }
3689
3327
  }
3690
- const prevTabbableIndex = tabbableIndexRef.current;
3691
3328
  const tabbableContent = getTabbableContent();
3692
- const nodeToFocus = tabbableContent[prevTabbableIndex] || tabbableContent[tabbableContent.length - 1] || floatingFocusElement;
3329
+ const prevTabbable = lastFocusedTabbableRef.current;
3330
+ const nodeToFocus = (prevTabbable && tabbableContent.includes(prevTabbable) ? prevTabbable : null) || tabbableContent[tabbableContent.length - 1] || floatingFocusElement;
3693
3331
  if (isHTMLElement(nodeToFocus)) {
3694
3332
  nodeToFocus.focus();
3695
3333
  }
@@ -3727,37 +3365,10 @@ function FloatingFocusManager(props) {
3727
3365
  });
3728
3366
  }
3729
3367
  const domReferenceElement = isHTMLElement(domReference) ? domReference : null;
3730
- const cleanups = [];
3731
3368
  if (!floating && !domReferenceElement) {
3732
3369
  return undefined;
3733
3370
  }
3734
- if (domReferenceElement) {
3735
- domReferenceElement.addEventListener('focusout', handleFocusOutside);
3736
- domReferenceElement.addEventListener('pointerdown', handlePointerDown);
3737
- cleanups.push(() => {
3738
- domReferenceElement.removeEventListener('focusout', handleFocusOutside);
3739
- domReferenceElement.removeEventListener('pointerdown', handlePointerDown);
3740
- });
3741
- }
3742
- if (floating) {
3743
- floating.addEventListener('focusin', handleFocusIn);
3744
- floating.addEventListener('focusout', handleFocusOutside);
3745
- if (portalContext) {
3746
- floating.addEventListener('focusout', markInsideReactTree, true);
3747
- cleanups.push(() => {
3748
- floating.removeEventListener('focusout', markInsideReactTree, true);
3749
- });
3750
- }
3751
- cleanups.push(() => {
3752
- floating.removeEventListener('focusin', handleFocusIn);
3753
- floating.removeEventListener('focusout', handleFocusOutside);
3754
- });
3755
- }
3756
- return () => {
3757
- cleanups.forEach(cleanup => {
3758
- cleanup();
3759
- });
3760
- };
3371
+ return mergeCleanups(domReferenceElement && addEventListener(domReferenceElement, 'focusout', handleFocusOutside), domReferenceElement && addEventListener(domReferenceElement, 'pointerdown', handlePointerDown), floating && addEventListener(floating, 'focusin', handleFocusIn), floating && addEventListener(floating, 'focusout', handleFocusOutside), floating && portalContext && addEventListener(floating, 'focusout', markInsideReactTree, true));
3761
3372
  }, [disabled, domReference, floating, floatingFocusElement, modal, tree, portalContext, store, closeOnFocusOut, restoreFocus, getTabbableContent, isUntrappedTypeableCombobox, getNodeId, orderRef, dataRef, blurTimeout, pointerDownTimeout, restoreFocusFrame, nextFocusableElement, previousFocusableElement, getResolvedInsideElements]);
3762
3373
 
3763
3374
  // Hide everything outside the floating tree from assistive tech while open.
@@ -3794,7 +3405,6 @@ function FloatingFocusManager(props) {
3794
3405
 
3795
3406
  // Wait for any layout effect state setters to execute to set `tabIndex`.
3796
3407
  queueMicrotask(() => {
3797
- const focusableElements = getTabbableElements(floatingFocusElement);
3798
3408
  const initialFocusValueOrFn = initialFocusRef.current;
3799
3409
  const resolvedInitialFocus = typeof initialFocusValueOrFn === 'function' ? initialFocusValueOrFn(openInteractionTypeRef.current || '') : initialFocusValueOrFn;
3800
3410
 
@@ -3802,22 +3412,29 @@ function FloatingFocusManager(props) {
3802
3412
  if (resolvedInitialFocus === undefined || resolvedInitialFocus === false) {
3803
3413
  return;
3804
3414
  }
3415
+ const focusAlreadyInsideFloatingEl = contains(floatingFocusElement, previouslyFocusedElement);
3416
+ if (focusAlreadyInsideFloatingEl) {
3417
+ return;
3418
+ }
3419
+ let focusableElements = null;
3420
+ const getDefaultFocusElement = () => {
3421
+ if (focusableElements == null) {
3422
+ focusableElements = getTabbableContent(floatingFocusElement);
3423
+ }
3424
+ return focusableElements[0] || floatingFocusElement;
3425
+ };
3805
3426
  let elToFocus;
3806
3427
  if (resolvedInitialFocus === true || resolvedInitialFocus === null) {
3807
- elToFocus = focusableElements[0] || floatingFocusElement;
3428
+ elToFocus = getDefaultFocusElement();
3808
3429
  } else {
3809
3430
  elToFocus = resolveRef(resolvedInitialFocus);
3810
3431
  }
3811
- elToFocus = elToFocus || focusableElements[0] || floatingFocusElement;
3812
- const focusAlreadyInsideFloatingEl = contains(floatingFocusElement, previouslyFocusedElement);
3813
- if (focusAlreadyInsideFloatingEl) {
3814
- return;
3815
- }
3432
+ elToFocus = elToFocus || getDefaultFocusElement();
3816
3433
  enqueueFocus(elToFocus, {
3817
3434
  preventScroll: elToFocus === floatingFocusElement
3818
3435
  });
3819
3436
  });
3820
- }, [disabled, open, floatingFocusElement, ignoreInitialFocus, getTabbableElements, initialFocusRef, openInteractionTypeRef]);
3437
+ }, [disabled, open, floatingFocusElement, ignoreInitialFocus, getTabbableContent, initialFocusRef, openInteractionTypeRef]);
3821
3438
 
3822
3439
  // Track return focus targets and restore focus on unmount/close.
3823
3440
  useIsoLayoutEffect(() => {
@@ -3846,7 +3463,7 @@ function FloatingFocusManager(props) {
3846
3463
  preventReturnFocusRef.current = false;
3847
3464
  } else {
3848
3465
  let isPreventScrollSupported = false;
3849
- document.createElement('div').focus({
3466
+ ownerDocument(floatingFocusElement).createElement('div').focus({
3850
3467
  get preventScroll() {
3851
3468
  isPreventScrollSupported = true;
3852
3469
  return false;
@@ -3883,14 +3500,15 @@ function FloatingFocusManager(props) {
3883
3500
  const activeEl = activeElement(doc);
3884
3501
  const insideElements = getResolvedInsideElements();
3885
3502
  const isFocusInsideFloatingTree = contains(floating, activeEl) || insideElements.some(element => element === activeEl || contains(element, activeEl)) || tree && getNodeChildren(tree.nodesRef.current, getNodeId(), false).some(node => contains(node.context?.elements.floating, activeEl));
3503
+
3504
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3505
+ const returnFocusValueOrFn = returnFocusRef.current;
3886
3506
  const returnElement = getReturnElement();
3887
3507
  queueMicrotask(() => {
3888
3508
  // This is `returnElement`, if it's tabbable, or its first tabbable child.
3889
3509
  const tabbableReturnElement = getFirstTabbableElement(returnElement);
3890
- const hasExplicitReturnFocus = typeof returnFocusRef.current !== 'boolean';
3891
- if (
3892
- // eslint-disable-next-line react-hooks/exhaustive-deps
3893
- returnFocusRef.current && !preventReturnFocusRef.current && isHTMLElement(tabbableReturnElement) && (
3510
+ const hasExplicitReturnFocus = typeof returnFocusValueOrFn !== 'boolean';
3511
+ if (returnFocusValueOrFn && !preventReturnFocusRef.current && isHTMLElement(tabbableReturnElement) && (
3894
3512
  // If the focus moved somewhere else after mount, avoid returning focus
3895
3513
  // since it likely entered a different element which should be
3896
3514
  // respected: https://github.com/floating-ui/floating-ui/issues/2607
@@ -3954,7 +3572,7 @@ function FloatingFocusManager(props) {
3954
3572
  ref: mergedBeforeGuardRef,
3955
3573
  onFocus: event => {
3956
3574
  if (modal) {
3957
- const els = getTabbableElements();
3575
+ const els = getTabbableContent();
3958
3576
  enqueueFocus(els[els.length - 1]);
3959
3577
  } else if (portalContext?.portalNode) {
3960
3578
  preventReturnFocusRef.current = false;
@@ -3971,7 +3589,7 @@ function FloatingFocusManager(props) {
3971
3589
  ref: mergedAfterGuardRef,
3972
3590
  onFocus: event => {
3973
3591
  if (modal) {
3974
- enqueueFocus(getTabbableElements()[0]);
3592
+ enqueueFocus(getTabbableContent()[0]);
3975
3593
  } else if (portalContext?.portalNode) {
3976
3594
  if (closeOnFocusOut) {
3977
3595
  preventReturnFocusRef.current = true;
@@ -4028,8 +3646,9 @@ function useClick(context, props = {}) {
4028
3646
 
4029
3647
  // Animations sometimes won't run on a typeable element if using a rAF.
4030
3648
  // Focus is always set on these elements. For touch, we may delay opening.
4031
- if (isTypeableElement(nativeEvent.target)) {
4032
- const details = createChangeEventDetails(reason, nativeEvent, nativeEvent.target);
3649
+ const target = getTarget(nativeEvent);
3650
+ if (isTypeableElement(target)) {
3651
+ const details = createChangeEventDetails(reason, nativeEvent, target);
4033
3652
  if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
4034
3653
  touchOpenTimeout.start(touchOpenDelay, () => {
4035
3654
  store.setOpen(true, details);
@@ -4250,11 +3869,8 @@ function useDismiss(context, props = {}) {
4250
3869
  }
4251
3870
  const target = getTarget(event);
4252
3871
  const inertSelector = `[${createAttribute('inert')}]`;
4253
- let markers = Array.from(ownerDocument(store.select('floatingElement')).querySelectorAll(inertSelector));
4254
3872
  const targetRoot = isElement(target) ? target.getRootNode() : null;
4255
- if (isShadowRoot(targetRoot)) {
4256
- markers = markers.concat(Array.from(targetRoot.querySelectorAll(inertSelector)));
4257
- }
3873
+ const markers = Array.from((isShadowRoot(targetRoot) ? targetRoot : ownerDocument(store.select('floatingElement'))).querySelectorAll(inertSelector));
4258
3874
  const triggers = store.context.triggerElements;
4259
3875
 
4260
3876
  // If another trigger is clicked, don't close the floating element.
@@ -4285,7 +3901,7 @@ function useDismiss(context, props = {}) {
4285
3901
  // Skip for touch events: scrollbars don't receive touch events on most platforms
4286
3902
  if (isHTMLElement(target) && !('touches' in event)) {
4287
3903
  const lastTraversableNode = isLastTraversableNode(target);
4288
- const style = getComputedStyle$1(target);
3904
+ const style = getComputedStyle(target);
4289
3905
  const scrollRe = /auto|scroll/;
4290
3906
  const isScrollableX = lastTraversableNode || scrollRe.test(style.overflowX);
4291
3907
  const isScrollableY = lastTraversableNode || scrollRe.test(style.overflowY);
@@ -4362,14 +3978,19 @@ function useDismiss(context, props = {}) {
4362
3978
  });
4363
3979
  }
4364
3980
  }
4365
- function handleTouchStartCapture(event) {
4366
- currentPointerTypeRef.current = 'touch';
3981
+ function addTargetEventListenerOnce(event, listener) {
4367
3982
  const target = getTarget(event);
4368
- function callback() {
4369
- handleTouchStart(event);
4370
- target?.removeEventListener(event.type, callback);
3983
+ if (!target) {
3984
+ return;
4371
3985
  }
4372
- target?.addEventListener(event.type, callback);
3986
+ const unsubscribe = addEventListener(target, event.type, () => {
3987
+ listener(event);
3988
+ unsubscribe();
3989
+ });
3990
+ }
3991
+ function handleTouchStartCapture(event) {
3992
+ currentPointerTypeRef.current = 'touch';
3993
+ addTargetEventListenerOnce(event, handleTouchStart);
4373
3994
  }
4374
3995
  function closeOnPressOutsideCapture(event) {
4375
3996
  cancelDismissOnEndTimeout.clear();
@@ -4379,16 +4000,13 @@ function useDismiss(context, props = {}) {
4379
4000
  if (event.type === 'mousedown' && touchStateRef.current && !touchStateRef.current.dismissOnMouseDown) {
4380
4001
  return;
4381
4002
  }
4382
- const target = getTarget(event);
4383
- function callback() {
4384
- if (event.type === 'pointerdown') {
4385
- handlePointerDown(event);
4003
+ addTargetEventListenerOnce(event, targetEvent => {
4004
+ if (targetEvent.type === 'pointerdown') {
4005
+ handlePointerDown(targetEvent);
4386
4006
  } else {
4387
- closeOnPressOutside(event);
4007
+ closeOnPressOutside(targetEvent);
4388
4008
  }
4389
- target?.removeEventListener(event.type, callback);
4390
- }
4391
- target?.addEventListener(event.type, callback);
4009
+ });
4392
4010
  }
4393
4011
  function handlePressEndCapture(event) {
4394
4012
  if (!pressStartedInsideRef.current) {
@@ -4447,12 +4065,7 @@ function useDismiss(context, props = {}) {
4447
4065
  }
4448
4066
  }
4449
4067
  function handleTouchMoveCapture(event) {
4450
- const target = getTarget(event);
4451
- function callback() {
4452
- handleTouchMove(event);
4453
- target?.removeEventListener(event.type, callback);
4454
- }
4455
- target?.addEventListener(event.type, callback);
4068
+ addTargetEventListenerOnce(event, handleTouchMove);
4456
4069
  }
4457
4070
  function handleTouchEnd(event) {
4458
4071
  if (getOutsidePressEvent() !== 'sloppy' || !touchStateRef.current || isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'))) {
@@ -4465,47 +4078,12 @@ function useDismiss(context, props = {}) {
4465
4078
  touchStateRef.current = null;
4466
4079
  }
4467
4080
  function handleTouchEndCapture(event) {
4468
- const target = getTarget(event);
4469
- function callback() {
4470
- handleTouchEnd(event);
4471
- target?.removeEventListener(event.type, callback);
4472
- }
4473
- target?.addEventListener(event.type, callback);
4081
+ addTargetEventListenerOnce(event, handleTouchEnd);
4474
4082
  }
4475
4083
  const doc = ownerDocument(floatingElement);
4476
- if (escapeKey$1) {
4477
- doc.addEventListener('keydown', closeOnEscapeKeyDown);
4478
- doc.addEventListener('compositionstart', handleCompositionStart);
4479
- doc.addEventListener('compositionend', handleCompositionEnd);
4480
- }
4481
- if (outsidePressEnabled) {
4482
- doc.addEventListener('click', closeOnPressOutsideCapture, true);
4483
- doc.addEventListener('pointerdown', closeOnPressOutsideCapture, true);
4484
- doc.addEventListener('pointerup', handlePressEndCapture, true);
4485
- doc.addEventListener('pointercancel', handlePressEndCapture, true);
4486
- doc.addEventListener('mousedown', closeOnPressOutsideCapture, true);
4487
- doc.addEventListener('mouseup', handlePressEndCapture, true);
4488
- doc.addEventListener('touchstart', handleTouchStartCapture, true);
4489
- doc.addEventListener('touchmove', handleTouchMoveCapture, true);
4490
- doc.addEventListener('touchend', handleTouchEndCapture, true);
4491
- }
4084
+ const unsubscribe = mergeCleanups(escapeKey$1 && mergeCleanups(addEventListener(doc, 'keydown', closeOnEscapeKeyDown), addEventListener(doc, 'compositionstart', handleCompositionStart), addEventListener(doc, 'compositionend', handleCompositionEnd)), outsidePressEnabled && mergeCleanups(addEventListener(doc, 'click', closeOnPressOutsideCapture, true), addEventListener(doc, 'pointerdown', closeOnPressOutsideCapture, true), addEventListener(doc, 'pointerup', handlePressEndCapture, true), addEventListener(doc, 'pointercancel', handlePressEndCapture, true), addEventListener(doc, 'mousedown', closeOnPressOutsideCapture, true), addEventListener(doc, 'mouseup', handlePressEndCapture, true), addEventListener(doc, 'touchstart', handleTouchStartCapture, true), addEventListener(doc, 'touchmove', handleTouchMoveCapture, true), addEventListener(doc, 'touchend', handleTouchEndCapture, true)));
4492
4085
  return () => {
4493
- if (escapeKey$1) {
4494
- doc.removeEventListener('keydown', closeOnEscapeKeyDown);
4495
- doc.removeEventListener('compositionstart', handleCompositionStart);
4496
- doc.removeEventListener('compositionend', handleCompositionEnd);
4497
- }
4498
- if (outsidePressEnabled) {
4499
- doc.removeEventListener('click', closeOnPressOutsideCapture, true);
4500
- doc.removeEventListener('pointerdown', closeOnPressOutsideCapture, true);
4501
- doc.removeEventListener('pointerup', handlePressEndCapture, true);
4502
- doc.removeEventListener('pointercancel', handlePressEndCapture, true);
4503
- doc.removeEventListener('mousedown', closeOnPressOutsideCapture, true);
4504
- doc.removeEventListener('mouseup', handlePressEndCapture, true);
4505
- doc.removeEventListener('touchstart', handleTouchStartCapture, true);
4506
- doc.removeEventListener('touchmove', handleTouchMoveCapture, true);
4507
- doc.removeEventListener('touchend', handleTouchEndCapture, true);
4508
- }
4086
+ unsubscribe();
4509
4087
  compositionTimeout.clear();
4510
4088
  preventedPressSuppressionTimeout.clear();
4511
4089
  resetPressStartState();
@@ -4583,20 +4161,24 @@ function useDismiss(context, props = {}) {
4583
4161
  } : {}, [enabled, reference, floating]);
4584
4162
  }
4585
4163
 
4586
- /* eslint-disable no-underscore-dangle */ // __cacheKey__
4164
+ /**
4165
+ * The NoOptionalParams type is a utility type that checks if a function has optional or default parameters.
4166
+ * If the function has optional or default parameters, it returns a string literal type with an error message.
4167
+ * Otherwise, it returns the original function type.
4168
+ *
4169
+ * This is used to enforce that the combiner function passed to createSelector does not have optional or default parameters,
4170
+ * as memoization relies on the Function.length property, which does not account for optional or default parameters.
4171
+ */
4587
4172
 
4588
- createSelectorCreator({
4589
- memoize: lruMemoize,
4590
- memoizeOptions: {
4591
- maxSize: 1,
4592
- equalityCheck: Object.is
4593
- }
4594
- });
4595
4173
  /**
4596
4174
  * Creates a selector function that can be used to derive values from the store's state.
4597
- * The selector can take up to three additional arguments that can be used in the selector logic.
4175
+ *
4176
+ * The combiner function can have up to three additional parameters, but it **cannot have optional or default parameters**.
4177
+ *
4598
4178
  * This function accepts up to six functions and combines them into a single selector function.
4599
- * The last parameter is the combiner function that combines the results of the previous selectors.
4179
+ * The resulting selector will take the state from the combined selectors and any additional parameters required by the combiner.
4180
+ *
4181
+ * The return type of the resulting selector is determined by the return type of the combiner function.
4600
4182
  *
4601
4183
  * @example
4602
4184
  * const selector = createSelector(
@@ -4609,7 +4191,6 @@ createSelectorCreator({
4609
4191
  * (state) => state.open,
4610
4192
  * (disabled, open) => ({ disabled, open })
4611
4193
  * );
4612
- *
4613
4194
  */
4614
4195
  /* eslint-disable id-denylist */
4615
4196
  const createSelector = (a, b, c, d, e, f, ...other) => {
@@ -4624,6 +4205,7 @@ const createSelector = (a, b, c, d, e, f, ...other) => {
4624
4205
  }
4625
4206
  return selector;
4626
4207
  };
4208
+ /* eslint-enable id-denylist */
4627
4209
 
4628
4210
  /* Some tests fail in R18 with the raw useSyncExternalStore. It may be possible to make it work
4629
4211
  * but for now we only enable it for R19+. */
@@ -4931,6 +4513,7 @@ class ReactStore extends Store {
4931
4513
 
4932
4514
  const selectors$1 = {
4933
4515
  open: createSelector(state => state.open),
4516
+ transitionStatus: createSelector(state => state.transitionStatus),
4934
4517
  domReferenceElement: createSelector(state => state.domReferenceElement),
4935
4518
  referenceElement: createSelector(state => state.positionReference ?? state.referenceElement),
4936
4519
  floatingElement: createSelector(state => state.floatingElement),
@@ -4939,8 +4522,8 @@ const selectors$1 = {
4939
4522
  class FloatingRootStore extends ReactStore {
4940
4523
  constructor(options) {
4941
4524
  const {
4525
+ syncOnly,
4942
4526
  nested,
4943
- noEmit,
4944
4527
  onOpenChange,
4945
4528
  triggerElements,
4946
4529
  ...initialState
@@ -4956,11 +4539,38 @@ class FloatingRootStore extends ReactStore {
4956
4539
  },
4957
4540
  events: createEventEmitter(),
4958
4541
  nested,
4959
- noEmit,
4960
4542
  triggerElements
4961
4543
  }, selectors$1);
4544
+ this.syncOnly = syncOnly;
4962
4545
  }
4963
4546
 
4547
+ /**
4548
+ * Syncs the event used by hover logic to distinguish hover-open from click-like interaction.
4549
+ */
4550
+ syncOpenEvent = (newOpen, event) => {
4551
+ if (!newOpen || !this.state.open ||
4552
+ // Prevent a pending hover-open from overwriting a click-open event, while allowing
4553
+ // click events to upgrade a hover-open.
4554
+ event != null && isClickLikeEvent(event)) {
4555
+ this.context.dataRef.current.openEvent = newOpen ? event : undefined;
4556
+ }
4557
+ };
4558
+
4559
+ /**
4560
+ * Runs the root-owned side effects for an open state change.
4561
+ */
4562
+ dispatchOpenChange = (newOpen, eventDetails) => {
4563
+ this.syncOpenEvent(newOpen, eventDetails.event);
4564
+ const details = {
4565
+ open: newOpen,
4566
+ reason: eventDetails.reason,
4567
+ nativeEvent: eventDetails.event,
4568
+ nested: this.context.nested,
4569
+ triggerElement: eventDetails.trigger
4570
+ };
4571
+ this.context.events.emit('openchange', details);
4572
+ };
4573
+
4964
4574
  /**
4965
4575
  * Emits the `openchange` event through the internal event emitter and calls the `onOpenChange` handler with the provided arguments.
4966
4576
  *
@@ -4968,22 +4578,11 @@ class FloatingRootStore extends ReactStore {
4968
4578
  * @param eventDetails Details about the event that triggered the open state change.
4969
4579
  */
4970
4580
  setOpen = (newOpen, eventDetails) => {
4971
- if (!newOpen || !this.state.open ||
4972
- // Prevent a pending hover-open from overwriting a click-open event, while allowing
4973
- // click events to upgrade a hover-open.
4974
- isClickLikeEvent(eventDetails.event)) {
4975
- this.context.dataRef.current.openEvent = newOpen ? eventDetails.event : undefined;
4976
- }
4977
- if (!this.context.noEmit) {
4978
- const details = {
4979
- open: newOpen,
4980
- reason: eventDetails.reason,
4981
- nativeEvent: eventDetails.event,
4982
- nested: this.context.nested,
4983
- triggerElement: eventDetails.trigger
4984
- };
4985
- this.context.events.emit('openchange', details);
4581
+ if (this.syncOnly) {
4582
+ this.context.onOpenChange?.(newOpen, eventDetails);
4583
+ return;
4986
4584
  }
4585
+ this.dispatchOpenChange(newOpen, eventDetails);
4987
4586
  this.context.onOpenChange?.(newOpen, eventDetails);
4988
4587
  };
4989
4588
  }
@@ -5086,13 +4685,14 @@ function useFloatingRootContext(options) {
5086
4685
  const nested = useFloatingParentNodeId() != null;
5087
4686
  const store = useRefWithInit(() => new FloatingRootStore({
5088
4687
  open,
4688
+ transitionStatus: undefined,
5089
4689
  onOpenChange,
5090
4690
  referenceElement: elements.reference ?? null,
5091
4691
  floatingElement: elements.floating ?? null,
5092
4692
  triggerElements: new PopupTriggerMap(),
5093
4693
  floatingId,
5094
- nested,
5095
- noEmit: false
4694
+ syncOnly: false,
4695
+ nested
5096
4696
  })).current;
5097
4697
  useIsoLayoutEffect(() => {
5098
4698
  const valuesToSync = {
@@ -5112,7 +4712,6 @@ function useFloatingRootContext(options) {
5112
4712
  }, [open, floatingId, elements.reference, elements.floating, store]);
5113
4713
  store.context.onOpenChange = onOpenChange;
5114
4714
  store.context.nested = nested;
5115
- store.context.noEmit = false;
5116
4715
  return store;
5117
4716
  }
5118
4717
 
@@ -5160,10 +4759,11 @@ function useFloating(options = {}) {
5160
4759
  setPositionReferenceRaw(computedPositionReference);
5161
4760
  position.refs.setReference(computedPositionReference);
5162
4761
  }, [position.refs]);
5163
- const [localDomReference, setLocalDomReference] = React.useState(null);
4762
+ const [localDomReference, setLocalDomReference] = React.useState(undefined);
5164
4763
  const [localFloatingElement, setLocalFloatingElement] = React.useState(null);
5165
- rootContext.useSyncedValue('referenceElement', localDomReference);
5166
- rootContext.useSyncedValue('domReferenceElement', isElement(localDomReference) ? localDomReference : null);
4764
+ rootContext.useSyncedValue('referenceElement', localDomReference ?? null);
4765
+ const localDomReferenceElement = isElement(localDomReference) ? localDomReference : null;
4766
+ rootContext.useSyncedValue('domReferenceElement', localDomReference === undefined ? rootContextElements.domReference : localDomReferenceElement);
5167
4767
  rootContext.useSyncedValue('floatingElement', localFloatingElement);
5168
4768
  const setReference = React.useCallback(node => {
5169
4769
  if (isElement(node) || node === null) {
@@ -5313,6 +4913,17 @@ function mutablyMergeProps(outputProps, props, isItem, eventHandlers) {
5313
4913
  }
5314
4914
  }
5315
4915
 
4916
+ function isMouseWithinBounds(event) {
4917
+ const targetRect = event.currentTarget.getBoundingClientRect();
4918
+
4919
+ // Safari randomly fires `mouseleave` incorrectly when the item is
4920
+ // aligned to the trigger. This is a workaround to prevent the highlight
4921
+ // from being removed while the cursor is still within the bounds of the item.
4922
+ // https://github.com/mui/base-ui/issues/869
4923
+ const isWithinBounds = targetRect.top + 1 <= event.clientY && event.clientY <= targetRect.bottom - 1 && targetRect.left + 1 <= event.clientX && event.clientX <= targetRect.right - 1;
4924
+ return isWithinBounds;
4925
+ }
4926
+
5316
4927
  const ESCAPE = 'Escape';
5317
4928
  function doSwitch(orientation, vertical, horizontal) {
5318
4929
  switch (orientation) {
@@ -5400,6 +5011,7 @@ function useListNavigation(context, props) {
5400
5011
  const previousOpenRef = React.useRef(open);
5401
5012
  const forceSyncFocusRef = React.useRef(false);
5402
5013
  const forceScrollIntoViewRef = React.useRef(false);
5014
+ const cancelQueuedFocusRef = React.useRef(null);
5403
5015
  const disabledIndicesRef = useValueAsRef(disabledIndices);
5404
5016
  const latestOpenRef = useValueAsRef(open);
5405
5017
  const selectedIndexRef = useValueAsRef(selectedIndex);
@@ -5409,7 +5021,7 @@ function useListNavigation(context, props) {
5409
5021
  if (virtual) {
5410
5022
  tree?.events.emit('virtualfocus', item);
5411
5023
  } else {
5412
- enqueueFocus(item, {
5024
+ cancelQueuedFocusRef.current = enqueueFocus(item, {
5413
5025
  sync: forceSyncFocusRef.current,
5414
5026
  preventScroll: true
5415
5027
  });
@@ -5513,7 +5125,7 @@ function useListNavigation(context, props) {
5513
5125
  };
5514
5126
  waitForListPopulated();
5515
5127
  }
5516
- } else if (!isIndexOutOfListBounds(listRef, activeIndex)) {
5128
+ } else if (!isIndexOutOfListBounds(listRef.current, activeIndex)) {
5517
5129
  indexRef.current = activeIndex;
5518
5130
  focusItem();
5519
5131
  forceScrollIntoViewRef.current = false;
@@ -5548,17 +5160,17 @@ function useListNavigation(context, props) {
5548
5160
  }
5549
5161
  }, [open, focusItemOnOpen]);
5550
5162
  const hasActiveIndex = activeIndex != null;
5551
- const item = React.useMemo(() => {
5552
- function syncCurrentTarget(event) {
5553
- if (!latestOpenRef.current) {
5554
- return;
5555
- }
5556
- const index = listRef.current.indexOf(event.currentTarget);
5557
- if (index !== -1 && indexRef.current !== index) {
5558
- indexRef.current = index;
5559
- onNavigate(event);
5560
- }
5163
+ const syncCurrentTarget = useStableCallback(event => {
5164
+ if (!latestOpenRef.current) {
5165
+ return;
5166
+ }
5167
+ const index = listRef.current.indexOf(event.currentTarget);
5168
+ if (index !== -1 && (indexRef.current !== index || activeIndex !== index)) {
5169
+ indexRef.current = index;
5170
+ onNavigate(event);
5561
5171
  }
5172
+ });
5173
+ const item = React.useMemo(() => {
5562
5174
  const itemProps = {
5563
5175
  onFocus(event) {
5564
5176
  forceSyncFocusRef.current = true;
@@ -5583,15 +5195,17 @@ function useListNavigation(context, props) {
5583
5195
  }
5584
5196
  forceSyncFocusRef.current = true;
5585
5197
  const relatedTarget = event.relatedTarget;
5198
+ if (isMouseWithinBounds(event)) {
5199
+ return;
5200
+ }
5586
5201
  if (!focusItemOnHover || listRef.current.includes(relatedTarget)) {
5587
5202
  return;
5588
5203
  }
5589
5204
  if (!resetOnPointerLeaveRef.current) {
5590
5205
  return;
5591
5206
  }
5592
- enqueueFocus(null, {
5593
- sync: true
5594
- });
5207
+ cancelQueuedFocusRef.current?.();
5208
+ cancelQueuedFocusRef.current = null;
5595
5209
  indexRef.current = -1;
5596
5210
  onNavigate(event);
5597
5211
  if (!virtual) {
@@ -5606,7 +5220,7 @@ function useListNavigation(context, props) {
5606
5220
  }
5607
5221
  };
5608
5222
  return itemProps;
5609
- }, [latestOpenRef, floatingFocusElementRef, focusItemOnHover, listRef, onNavigate, resetOnPointerLeaveRef, virtual]);
5223
+ }, [syncCurrentTarget, latestOpenRef, floatingFocusElementRef, focusItemOnHover, listRef, onNavigate, resetOnPointerLeaveRef, virtual]);
5610
5224
  const getParentOrientation = React.useCallback(() => {
5611
5225
  return parentOrientation ?? tree?.nodesRef.current.find(node => node.id === parentId)?.context?.dataRef?.current.orientation;
5612
5226
  }, [parentId, tree, parentOrientation]);
@@ -5671,12 +5285,10 @@ function useListNavigation(context, props) {
5671
5285
  // To calculate movements on the grid, we use hypothetical cell indices
5672
5286
  // as if every item was 1x1, then convert back to real indices.
5673
5287
  const cellMap = createGridCellMap(sizes, cols);
5674
- const minGridIndex = cellMap.findIndex(index => index != null && !isListIndexDisabled(listRef, index, disabledIndices));
5288
+ const minGridIndex = cellMap.findIndex(index => index != null && !isListIndexDisabled(listRef.current, index, disabledIndices));
5675
5289
  // last enabled index
5676
- const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(listRef, index, disabledIndices) ? cellIndex : foundIndex, -1);
5677
- const index = cellMap[getGridNavigatedIndex({
5678
- current: cellMap.map(itemIndex => itemIndex != null ? listRef.current[itemIndex] : null)
5679
- }, {
5290
+ const maxGridIndex = cellMap.reduce((foundIndex, index, cellIndex) => index != null && !isListIndexDisabled(listRef.current, index, disabledIndices) ? cellIndex : foundIndex, -1);
5291
+ const index = cellMap[getGridNavigatedIndex(cellMap.map(itemIndex => itemIndex != null ? listRef.current[itemIndex] : null), {
5680
5292
  event,
5681
5293
  orientation,
5682
5294
  loopFocus,
@@ -5684,7 +5296,7 @@ function useListNavigation(context, props) {
5684
5296
  cols,
5685
5297
  // treat undefined (empty grid spaces) as disabled indices so we
5686
5298
  // don't end up in them
5687
- disabledIndices: getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || listRef.current.map((_, listIndex) => isListIndexDisabled(listRef, listIndex, disabledIndices) ? listIndex : undefined)), undefined], cellMap),
5299
+ disabledIndices: getGridCellIndices([...((typeof disabledIndices !== 'function' ? disabledIndices : null) || listRef.current.map((_, listIndex) => isListIndexDisabled(listRef.current, listIndex, disabledIndices) ? listIndex : undefined)), undefined], cellMap),
5688
5300
  minIndex: minGridIndex,
5689
5301
  maxIndex: maxGridIndex,
5690
5302
  prevIndex: getGridCellIndexOfCorner(indexRef.current > maxIndex ? minIndex : indexRef.current, sizes, cellMap, cols,
@@ -5723,13 +5335,13 @@ function useListNavigation(context, props) {
5723
5335
  indexRef.current = minIndex;
5724
5336
  }
5725
5337
  } else {
5726
- indexRef.current = findNonDisabledListIndex(listRef, {
5338
+ indexRef.current = findNonDisabledListIndex(listRef.current, {
5727
5339
  startingIndex: currentIndex,
5728
5340
  disabledIndices
5729
5341
  });
5730
5342
  }
5731
5343
  } else {
5732
- indexRef.current = Math.min(maxIndex, findNonDisabledListIndex(listRef, {
5344
+ indexRef.current = Math.min(maxIndex, findNonDisabledListIndex(listRef.current, {
5733
5345
  startingIndex: currentIndex,
5734
5346
  disabledIndices
5735
5347
  }));
@@ -5744,20 +5356,20 @@ function useListNavigation(context, props) {
5744
5356
  indexRef.current = maxIndex;
5745
5357
  }
5746
5358
  } else {
5747
- indexRef.current = findNonDisabledListIndex(listRef, {
5359
+ indexRef.current = findNonDisabledListIndex(listRef.current, {
5748
5360
  startingIndex: currentIndex,
5749
5361
  decrement: true,
5750
5362
  disabledIndices
5751
5363
  });
5752
5364
  }
5753
5365
  } else {
5754
- indexRef.current = Math.max(minIndex, findNonDisabledListIndex(listRef, {
5366
+ indexRef.current = Math.max(minIndex, findNonDisabledListIndex(listRef.current, {
5755
5367
  startingIndex: currentIndex,
5756
5368
  decrement: true,
5757
5369
  disabledIndices
5758
5370
  }));
5759
5371
  }
5760
- if (isIndexOutOfListBounds(listRef, indexRef.current)) {
5372
+ if (isIndexOutOfListBounds(listRef.current, indexRef.current)) {
5761
5373
  indexRef.current = -1;
5762
5374
  }
5763
5375
  onNavigate(event);
@@ -6240,19 +5852,8 @@ const InternalBackdrop = /*#__PURE__*/React.forwardRef(function InternalBackdrop
6240
5852
  } = props;
6241
5853
  let clipPath;
6242
5854
  if (cutout) {
6243
- const rect = cutout?.getBoundingClientRect();
6244
- clipPath = `polygon(
6245
- 0% 0%,
6246
- 100% 0%,
6247
- 100% 100%,
6248
- 0% 100%,
6249
- 0% 0%,
6250
- ${rect.left}px ${rect.top}px,
6251
- ${rect.left}px ${rect.bottom}px,
6252
- ${rect.right}px ${rect.bottom}px,
6253
- ${rect.right}px ${rect.top}px,
6254
- ${rect.left}px ${rect.top}px
6255
- )`;
5855
+ const rect = cutout.getBoundingClientRect();
5856
+ clipPath = `polygon(0% 0%,100% 0%,100% 100%,0% 100%,0% 0%,${rect.left}px ${rect.top}px,${rect.left}px ${rect.bottom}px,${rect.right}px ${rect.bottom}px,${rect.right}px ${rect.top}px,${rect.left}px ${rect.top}px)`;
6256
5857
  }
6257
5858
  return /*#__PURE__*/jsx("div", {
6258
5859
  ref: ref,
@@ -6272,14 +5873,6 @@ const InternalBackdrop = /*#__PURE__*/React.forwardRef(function InternalBackdrop
6272
5873
  });
6273
5874
  });
6274
5875
 
6275
- function useOnFirstRender(fn) {
6276
- const ref = React.useRef(true);
6277
- if (ref.current) {
6278
- ref.current = false;
6279
- fn();
6280
- }
6281
- }
6282
-
6283
5876
  const ComboboxRootContext = /*#__PURE__*/React.createContext(undefined);
6284
5877
  const ComboboxFloatingContext = /*#__PURE__*/React.createContext(undefined);
6285
5878
  const ComboboxDerivedItemsContext = /*#__PURE__*/React.createContext(undefined);
@@ -6463,7 +6056,6 @@ function resolveMultipleLabels(values, items, itemToStringLabel) {
6463
6056
  const selectors = {
6464
6057
  id: createSelector(state => state.id),
6465
6058
  labelId: createSelector(state => state.labelId),
6466
- query: createSelector(state => state.query),
6467
6059
  items: createSelector(state => state.items),
6468
6060
  selectedValue: createSelector(state => state.selectedValue),
6469
6061
  hasSelectionChips: createSelector(state => {
@@ -6515,25 +6107,13 @@ const selectors = {
6515
6107
  openMethod: createSelector(state => state.openMethod),
6516
6108
  inputInsidePopup: createSelector(state => state.inputInsidePopup),
6517
6109
  selectionMode: createSelector(state => state.selectionMode),
6518
- listRef: createSelector(state => state.listRef),
6519
- labelsRef: createSelector(state => state.labelsRef),
6520
- popupRef: createSelector(state => state.popupRef),
6521
- emptyRef: createSelector(state => state.emptyRef),
6522
- inputRef: createSelector(state => state.inputRef),
6523
- keyboardActiveRef: createSelector(state => state.keyboardActiveRef),
6524
- chipsContainerRef: createSelector(state => state.chipsContainerRef),
6525
- clearRef: createSelector(state => state.clearRef),
6526
- valuesRef: createSelector(state => state.valuesRef),
6527
- allValuesRef: createSelector(state => state.allValuesRef),
6528
6110
  name: createSelector(state => state.name),
6111
+ form: createSelector(state => state.form),
6529
6112
  disabled: createSelector(state => state.disabled),
6530
6113
  readOnly: createSelector(state => state.readOnly),
6531
6114
  required: createSelector(state => state.required),
6532
6115
  grid: createSelector(state => state.grid),
6533
- isGrouped: createSelector(state => state.isGrouped),
6534
6116
  virtualized: createSelector(state => state.virtualized),
6535
- onOpenChangeComplete: createSelector(state => state.onOpenChangeComplete),
6536
- openOnInputClick: createSelector(state => state.openOnInputClick),
6537
6117
  itemToStringLabel: createSelector(state => state.itemToStringLabel),
6538
6118
  isItemEqualToValue: createSelector(state => state.isItemEqualToValue),
6539
6119
  modal: createSelector(state => state.modal),
@@ -6641,6 +6221,7 @@ const FieldRootContext = /*#__PURE__*/React.createContext({
6641
6221
  markedDirtyRef: {
6642
6222
  current: false
6643
6223
  },
6224
+ registerFieldControl: NOOP,
6644
6225
  validation: {
6645
6226
  getValidationProps: (props = EMPTY_OBJECT) => props,
6646
6227
  getInputValidationProps: (props = EMPTY_OBJECT) => props,
@@ -6658,18 +6239,35 @@ function useFieldRootContext(optional = true) {
6658
6239
  return context;
6659
6240
  }
6660
6241
 
6661
- /**
6662
- * Combines the field's client-side, stateful validity data with the external invalid state to
6663
- * determine the field's true validity.
6664
- */
6665
- function getCombinedFieldValidityData(validityData, invalid) {
6666
- return {
6667
- ...validityData,
6668
- state: {
6669
- ...validityData.state,
6670
- valid: !invalid && validityData.state.valid
6242
+ function useRegisterFieldControl(controlRef, params) {
6243
+ const {
6244
+ enabled = true,
6245
+ getValue,
6246
+ id,
6247
+ value
6248
+ } = params;
6249
+ const {
6250
+ registerFieldControl
6251
+ } = useFieldRootContext();
6252
+ const sourceRef = React.useRef(null);
6253
+ if (!sourceRef.current) {
6254
+ sourceRef.current = Symbol();
6255
+ }
6256
+ useIsoLayoutEffect(() => {
6257
+ const source = sourceRef.current;
6258
+ if (!source || !enabled) {
6259
+ return undefined;
6671
6260
  }
6672
- };
6261
+ registerFieldControl(source, {
6262
+ controlRef,
6263
+ getValue,
6264
+ id,
6265
+ value
6266
+ });
6267
+ return () => {
6268
+ registerFieldControl(source, undefined);
6269
+ };
6270
+ }, [controlRef, enabled, getValue, id, registerFieldControl, value]);
6673
6271
  }
6674
6272
 
6675
6273
  const FormContext = /*#__PURE__*/React.createContext({
@@ -6689,74 +6287,6 @@ function useFormContext() {
6689
6287
  return React.useContext(FormContext);
6690
6288
  }
6691
6289
 
6692
- function useField(params) {
6693
- const {
6694
- enabled = true,
6695
- value,
6696
- id,
6697
- name,
6698
- controlRef,
6699
- commit
6700
- } = params;
6701
- const {
6702
- formRef
6703
- } = useFormContext();
6704
- const {
6705
- invalid,
6706
- markedDirtyRef,
6707
- validityData,
6708
- setValidityData
6709
- } = useFieldRootContext();
6710
- const getValue = useStableCallback(params.getValue);
6711
- useIsoLayoutEffect(() => {
6712
- if (!enabled) {
6713
- return;
6714
- }
6715
- let initialValue = value;
6716
- if (initialValue === undefined) {
6717
- initialValue = getValue();
6718
- }
6719
- if (validityData.initialValue === null && initialValue !== null) {
6720
- setValidityData(prev => ({
6721
- ...prev,
6722
- initialValue
6723
- }));
6724
- }
6725
- }, [enabled, setValidityData, value, validityData.initialValue, getValue]);
6726
- useIsoLayoutEffect(() => {
6727
- if (!enabled || !id) {
6728
- return;
6729
- }
6730
- formRef.current.fields.set(id, {
6731
- getValue,
6732
- name,
6733
- controlRef,
6734
- validityData: getCombinedFieldValidityData(validityData, invalid),
6735
- validate(flushSync = true) {
6736
- let nextValue = value;
6737
- if (nextValue === undefined) {
6738
- nextValue = getValue();
6739
- }
6740
- markedDirtyRef.current = true;
6741
- if (!flushSync) {
6742
- commit(nextValue);
6743
- } else {
6744
- // Synchronously update the validity state so the submit event can be prevented.
6745
- ReactDOM.flushSync(() => commit(nextValue));
6746
- }
6747
- }
6748
- });
6749
- }, [commit, controlRef, enabled, formRef, getValue, id, invalid, markedDirtyRef, name, validityData, value]);
6750
- useIsoLayoutEffect(() => {
6751
- const fields = formRef.current.fields;
6752
- return () => {
6753
- if (id) {
6754
- fields.delete(id);
6755
- }
6756
- };
6757
- }, [formRef, id]);
6758
- }
6759
-
6760
6290
  /**
6761
6291
  * A context for providing [labelable elements](https://html.spec.whatwg.org/multipage/forms.html#category-label)\
6762
6292
  * with an accessible name (label) and description.
@@ -6946,9 +6476,12 @@ function AriaCombobox(props) {
6946
6476
  onSelectedValueChange,
6947
6477
  defaultInputValue: defaultInputValueProp,
6948
6478
  inputValue: inputValueProp,
6479
+ open: openProp,
6480
+ defaultOpen = false,
6949
6481
  selectionMode = 'none',
6950
6482
  onItemHighlighted: onItemHighlightedProp,
6951
6483
  name: nameProp,
6484
+ form,
6952
6485
  disabled: disabledProp = false,
6953
6486
  readOnly = false,
6954
6487
  required = false,
@@ -7074,8 +6607,8 @@ function AriaCombobox(props) {
7074
6607
  state: 'inputValue'
7075
6608
  });
7076
6609
  const [open, setOpenUnwrapped] = useControlled({
7077
- controlled: props.open,
7078
- default: props.defaultOpen,
6610
+ controlled: openProp,
6611
+ default: defaultOpen,
7079
6612
  name: 'Combobox',
7080
6613
  state: 'open'
7081
6614
  });
@@ -7177,6 +6710,7 @@ function AriaCombobox(props) {
7177
6710
  allValuesRef,
7178
6711
  selectionEventRef,
7179
6712
  name,
6713
+ form,
7180
6714
  disabled,
7181
6715
  readOnly,
7182
6716
  required,
@@ -7250,13 +6784,11 @@ function AriaCombobox(props) {
7250
6784
  openMethod,
7251
6785
  triggerProps
7252
6786
  } = useOpenInteractionType(open);
7253
- useField({
6787
+ const getFieldValue = useStableCallback(() => fieldStringValue);
6788
+ useRegisterFieldControl(inputInsidePopup ? triggerRef : inputRef, {
7254
6789
  id,
7255
- name,
7256
- commit: validation.commit,
7257
6790
  value: fieldRawValue,
7258
- controlRef: inputInsidePopup ? triggerRef : inputRef,
7259
- getValue: () => fieldStringValue
6791
+ getValue: getFieldValue
7260
6792
  });
7261
6793
  const forceMount = useStableCallback(() => {
7262
6794
  if (items) {
@@ -7437,9 +6969,9 @@ function AriaCombobox(props) {
7437
6969
  if (!store.state.submitOnItemClick) {
7438
6970
  return;
7439
6971
  }
7440
- const form = store.state.inputElement?.form;
7441
- if (form && typeof form.requestSubmit === 'function') {
7442
- form.requestSubmit();
6972
+ const formElement = validation.inputRef.current?.form ?? store.state.inputElement?.form;
6973
+ if (formElement && typeof formElement.requestSubmit === 'function') {
6974
+ formElement.requestSubmit();
7443
6975
  }
7444
6976
  });
7445
6977
  const handleUnmount = useStableCallback(() => {
@@ -7694,9 +7226,9 @@ function AriaCombobox(props) {
7694
7226
  enabled: !readOnly && !disabled && openOnInputClick,
7695
7227
  event: 'mousedown-only',
7696
7228
  toggle: false,
7697
- // Apply a small delay for touch to let iOS viewport centering settle.
7229
+ // Apply a small delay for touch to let mobile viewport/keyboard positioning settle.
7698
7230
  // This avoids top-bottom flip flickers if the preferred position is "top" when first tapping.
7699
- touchOpenDelay: inputInsidePopup ? 0 : 50,
7231
+ touchOpenDelay: inputInsidePopup ? 0 : 100,
7700
7232
  reason: inputPress
7701
7233
  });
7702
7234
  const dismiss = useDismiss(floatingRootContext, {
@@ -7789,6 +7321,7 @@ function AriaCombobox(props) {
7789
7321
  getItemProps,
7790
7322
  selectionMode,
7791
7323
  name,
7324
+ form,
7792
7325
  disabled,
7793
7326
  readOnly,
7794
7327
  required,
@@ -7805,7 +7338,7 @@ function AriaCombobox(props) {
7805
7338
  hasInputValue,
7806
7339
  requestSubmit
7807
7340
  });
7808
- }, [store, id, selectedValue, open, mounted, transitionStatus, items, getFloatingProps, getReferenceProps, getItemProps, openMethod, triggerProps, selectionMode, name, disabled, readOnly, required, validation, grid, isGrouped, virtualized, onOpenChangeComplete, openOnInputClick, itemToStringLabel, modal, isItemEqualToValue, submitOnItemClick, hasInputValue, inlineProp, requestSubmit, autoHighlightMode]);
7341
+ }, [store, id, selectedValue, open, mounted, transitionStatus, items, getFloatingProps, getReferenceProps, getItemProps, openMethod, triggerProps, selectionMode, name, disabled, readOnly, required, validation, grid, isGrouped, virtualized, onOpenChangeComplete, openOnInputClick, itemToStringLabel, modal, isItemEqualToValue, submitOnItemClick, hasInputValue, inlineProp, requestSubmit, autoHighlightMode, form]);
7809
7342
  const hiddenInputRef = useMergedRefs(inputRefProp, validation.inputRef);
7810
7343
  const itemsContextValue = React.useMemo(() => ({
7811
7344
  query,
@@ -7829,11 +7362,12 @@ function AriaCombobox(props) {
7829
7362
  const currentSerializedValue = stringifyAsValue(value, itemToStringValue);
7830
7363
  return /*#__PURE__*/jsx("input", {
7831
7364
  type: "hidden",
7365
+ form: form,
7832
7366
  name: name,
7833
7367
  value: currentSerializedValue
7834
7368
  }, currentSerializedValue);
7835
7369
  });
7836
- }, [multiple, selectedValue, name, itemToStringValue]);
7370
+ }, [multiple, selectedValue, form, name, itemToStringValue]);
7837
7371
  const children = /*#__PURE__*/jsxs(React.Fragment, {
7838
7372
  children: [props.children, /*#__PURE__*/jsx("input", {
7839
7373
  ...validation.getInputValidationProps({
@@ -7851,7 +7385,7 @@ function AriaCombobox(props) {
7851
7385
  if (event.nativeEvent.defaultPrevented) {
7852
7386
  return;
7853
7387
  }
7854
- const nextValue = event.target.value;
7388
+ const nextValue = event.currentTarget.value;
7855
7389
  const details = createChangeEventDetails(none, event.nativeEvent);
7856
7390
  function handleChange() {
7857
7391
  // Browser autofill only writes a single scalar value.
@@ -7867,8 +7401,15 @@ function AriaCombobox(props) {
7867
7401
  return;
7868
7402
  }
7869
7403
  const matchingValue = valuesRef.current.find(v => {
7870
- const candidate = stringifyAsValue(v, itemToStringValue);
7871
- if (candidate.toLowerCase() === nextValue.toLowerCase()) {
7404
+ // Try matching by value first (e.g., "US" for country code)
7405
+ const candidateValue = stringifyAsValue(v, itemToStringValue);
7406
+ if (candidateValue.toLowerCase() === nextValue.toLowerCase()) {
7407
+ return true;
7408
+ }
7409
+ // Also try matching by label for browser autofill compatibility
7410
+ // (browsers autofill with displayed text like "United States", not the underlying value)
7411
+ const candidateLabel = stringifyAsLabel(v, itemToStringLabel);
7412
+ if (candidateLabel.toLowerCase() === nextValue.toLowerCase()) {
7872
7413
  return true;
7873
7414
  }
7874
7415
  return false;
@@ -7890,6 +7431,7 @@ function AriaCombobox(props) {
7890
7431
  }
7891
7432
  }),
7892
7433
  id: id && hiddenInputName == null ? `${id}-hidden-input` : undefined,
7434
+ form: form,
7893
7435
  name: hiddenInputName,
7894
7436
  autoComplete: formAutoComplete,
7895
7437
  disabled: disabled,
@@ -7899,7 +7441,8 @@ function AriaCombobox(props) {
7899
7441
  ref: hiddenInputRef,
7900
7442
  style: hiddenInputName ? visuallyHiddenInput : visuallyHidden,
7901
7443
  tabIndex: -1,
7902
- "aria-hidden": true
7444
+ "aria-hidden": true,
7445
+ suppressHydrationWarning: true
7903
7446
  }), hiddenInputs]
7904
7447
  });
7905
7448
  return /*#__PURE__*/jsx(ComboboxRootContext.Provider, {
@@ -7930,8 +7473,9 @@ const triggerStateAttributesMapping = {
7930
7473
 
7931
7474
  function getPseudoElementBounds(element) {
7932
7475
  const elementRect = element.getBoundingClientRect();
7933
- const beforeStyles = window.getComputedStyle(element, '::before');
7934
- const afterStyles = window.getComputedStyle(element, '::after');
7476
+ const win = getWindow(element);
7477
+ const beforeStyles = win.getComputedStyle(element, '::before');
7478
+ const afterStyles = win.getComputedStyle(element, '::after');
7935
7479
  const hasPseudoElements = beforeStyles.content !== 'none' || afterStyles.content !== 'none';
7936
7480
  if (!hasPseudoElements) {
7937
7481
  return elementRect;
@@ -7967,6 +7511,8 @@ const BOUNDARY_OFFSET = 2;
7967
7511
  /**
7968
7512
  * A button that opens the popup.
7969
7513
  * Renders a `<button>` element.
7514
+ *
7515
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
7970
7516
  */
7971
7517
  const ComboboxTrigger$2 = /*#__PURE__*/React.forwardRef(function ComboboxTrigger(componentProps, forwardedRef) {
7972
7518
  const {
@@ -7975,6 +7521,7 @@ const ComboboxTrigger$2 = /*#__PURE__*/React.forwardRef(function ComboboxTrigger
7975
7521
  nativeButton = true,
7976
7522
  disabled: disabledProp = false,
7977
7523
  id: idProp,
7524
+ style,
7978
7525
  ...elementProps
7979
7526
  } = componentProps;
7980
7527
  const {
@@ -8070,7 +7617,7 @@ const ComboboxTrigger$2 = /*#__PURE__*/React.forwardRef(function ComboboxTrigger
8070
7617
  disabled,
8071
7618
  popupSide,
8072
7619
  listEmpty,
8073
- placeholder: !hasSelectedValue
7620
+ placeholder: selectionMode === 'none' ? false : !hasSelectedValue
8074
7621
  };
8075
7622
  const setTriggerElement = useStableCallback(element => {
8076
7623
  store.set('triggerElement', element);
@@ -8215,6 +7762,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8215
7762
  className,
8216
7763
  disabled: disabledProp = false,
8217
7764
  id: idProp,
7765
+ style,
8218
7766
  ...elementProps
8219
7767
  } = componentProps;
8220
7768
  const {
@@ -8243,6 +7791,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8243
7791
  const comboboxDisabled = useStore(store, selectors.disabled);
8244
7792
  const readOnly = useStore(store, selectors.readOnly);
8245
7793
  const name = useStore(store, selectors.name);
7794
+ const form = useStore(store, selectors.form);
8246
7795
  const selectionMode = useStore(store, selectors.selectionMode);
8247
7796
  const autoHighlightMode = useStore(store, selectors.autoHighlight);
8248
7797
  const inputProps = useStore(store, selectors.inputProps);
@@ -8295,6 +7844,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8295
7844
  const {
8296
7845
  highlightedChipIndex
8297
7846
  } = comboboxChipsContext;
7847
+ const renderedChipsCount = comboboxChipsContext.chipsRef.current.length;
8298
7848
  if (highlightedChipIndex !== undefined) {
8299
7849
  if (event.key === 'ArrowLeft') {
8300
7850
  event.preventDefault();
@@ -8305,7 +7855,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8305
7855
  }
8306
7856
  } else if (event.key === 'ArrowRight') {
8307
7857
  event.preventDefault();
8308
- if (highlightedChipIndex < selectedValue.length - 1) {
7858
+ if (highlightedChipIndex < renderedChipsCount - 1) {
8309
7859
  nextIndex = highlightedChipIndex + 1;
8310
7860
  } else {
8311
7861
  nextIndex = undefined;
@@ -8328,8 +7878,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8328
7878
  // Handle navigation when no chip is highlighted
8329
7879
  if (event.key === 'ArrowLeft' && (event.currentTarget.selectionStart ?? 0) === 0 && selectedValue.length > 0) {
8330
7880
  event.preventDefault();
8331
- const lastChipIndex = Math.max(selectedValue.length - 1, 0);
8332
- nextIndex = lastChipIndex;
7881
+ nextIndex = renderedChipsCount > 0 ? renderedChipsCount - 1 : undefined;
8333
7882
  } else if (event.key === 'Backspace' && event.currentTarget.value === '' && selectedValue.length > 0) {
8334
7883
  store.state.setIndices({
8335
7884
  activeIndex: null,
@@ -8352,6 +7901,7 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8352
7901
  disabled,
8353
7902
  readOnly,
8354
7903
  required: selectionMode === 'none' ? required : undefined,
7904
+ form,
8355
7905
  ...(selectionMode === 'none' && name && {
8356
7906
  name
8357
7907
  }),
@@ -8519,7 +8069,9 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8519
8069
 
8520
8070
  // Handle deletion when no chip is highlighted and the input is empty.
8521
8071
  if (comboboxChipsContext && event.key === 'Backspace' && input.value === '' && comboboxChipsContext.highlightedChipIndex === undefined && Array.isArray(selectedValue) && selectedValue.length > 0) {
8522
- const newValue = selectedValue.slice(0, -1);
8072
+ const renderedChipsCount = comboboxChipsContext.chipsRef.current.length;
8073
+ const removalIndex = renderedChipsCount > 0 ? renderedChipsCount - 1 : selectedValue.length - 1;
8074
+ const newValue = selectedValue.filter((_, index) => index !== removalIndex);
8523
8075
  // If the removed item was also the active (highlighted) item, clear highlight
8524
8076
  store.state.setIndices({
8525
8077
  activeIndex: null,
@@ -8579,6 +8131,25 @@ const ComboboxInput$2 = /*#__PURE__*/React.forwardRef(function ComboboxInput(com
8579
8131
  });
8580
8132
  });
8581
8133
 
8134
+ function handleInputPress(event, store, disabled, readOnly, shouldIgnoreTarget) {
8135
+ if (event.baseUIHandlerPrevented || readOnly) {
8136
+ return;
8137
+ }
8138
+ const target = getTarget(event.nativeEvent);
8139
+ const targetElement = isElement(target) ? target : null;
8140
+ if (targetElement !== event.currentTarget && (isInteractiveElement(targetElement))) {
8141
+ return;
8142
+ }
8143
+ event.preventDefault();
8144
+ if (disabled) {
8145
+ return;
8146
+ }
8147
+ store.state.inputRef.current?.focus();
8148
+ if (store.state.openOnInputClick) {
8149
+ store.state.setOpen(true, createChangeEventDetails(inputPress, event.nativeEvent));
8150
+ }
8151
+ }
8152
+
8582
8153
  const stateAttributesMapping$1 = {
8583
8154
  ...transitionStatusMapping,
8584
8155
  ...triggerOpenStateMapping
@@ -8587,6 +8158,8 @@ const stateAttributesMapping$1 = {
8587
8158
  /**
8588
8159
  * Clears the value when clicked.
8589
8160
  * Renders a `<button>` element.
8161
+ *
8162
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
8590
8163
  */
8591
8164
  const ComboboxClear$1 = /*#__PURE__*/React.forwardRef(function ComboboxClear(componentProps, forwardedRef) {
8592
8165
  const {
@@ -8595,6 +8168,7 @@ const ComboboxClear$1 = /*#__PURE__*/React.forwardRef(function ComboboxClear(com
8595
8168
  disabled: disabledProp = false,
8596
8169
  nativeButton = true,
8597
8170
  keepMounted = false,
8171
+ style,
8598
8172
  ...elementProps
8599
8173
  } = componentProps;
8600
8174
  const {
@@ -8724,6 +8298,7 @@ const ComboboxList$2 = /*#__PURE__*/React.forwardRef(function ComboboxList(compo
8724
8298
  const {
8725
8299
  render,
8726
8300
  className,
8301
+ style,
8727
8302
  children,
8728
8303
  ...elementProps
8729
8304
  } = componentProps;
@@ -8731,16 +8306,12 @@ const ComboboxList$2 = /*#__PURE__*/React.forwardRef(function ComboboxList(compo
8731
8306
  const floatingRootContext = useComboboxFloatingContext();
8732
8307
  const hasPositionerContext = Boolean(useComboboxPositionerContext(true));
8733
8308
  const {
8734
- filteredItems
8309
+ filteredItems,
8310
+ hasItems
8735
8311
  } = useComboboxDerivedItemsContext();
8736
- const items = useStore(store, selectors.items);
8737
- const labelsRef = useStore(store, selectors.labelsRef);
8738
- const listRef = useStore(store, selectors.listRef);
8739
8312
  const selectionMode = useStore(store, selectors.selectionMode);
8740
8313
  const grid = useStore(store, selectors.grid);
8741
8314
  const popupProps = useStore(store, selectors.popupProps);
8742
- const disabled = useStore(store, selectors.disabled);
8743
- const readOnly = useStore(store, selectors.readOnly);
8744
8315
  const virtualized = useStore(store, selectors.virtualized);
8745
8316
  const multiple = selectionMode === 'multiple';
8746
8317
  const empty = filteredItems.length === 0;
@@ -8777,7 +8348,7 @@ const ComboboxList$2 = /*#__PURE__*/React.forwardRef(function ComboboxList(compo
8777
8348
  role: grid ? 'grid' : 'listbox',
8778
8349
  'aria-multiselectable': multiple ? 'true' : undefined,
8779
8350
  onKeyDown(event) {
8780
- if (disabled || readOnly) {
8351
+ if (store.state.disabled || store.state.readOnly) {
8781
8352
  return;
8782
8353
  }
8783
8354
  if (event.key === 'Enter') {
@@ -8808,12 +8379,62 @@ const ComboboxList$2 = /*#__PURE__*/React.forwardRef(function ComboboxList(compo
8808
8379
  return element;
8809
8380
  }
8810
8381
  return /*#__PURE__*/jsx(CompositeList, {
8811
- elementsRef: listRef,
8812
- labelsRef: items ? undefined : labelsRef,
8382
+ elementsRef: store.state.listRef,
8383
+ labelsRef: hasItems ? undefined : store.state.labelsRef,
8813
8384
  children: element
8814
8385
  });
8815
8386
  });
8816
8387
 
8388
+ // Word Joiner is invisible and zero-width, so it forces a text mutation without shifting layout.
8389
+ const LIVE_REGION_MARKER = '\u2060';
8390
+ // Safari VoiceOver needed roughly 200ms to reliably notice the initial polite live-region change.
8391
+ const INITIAL_LIVE_REGION_TEXT_MUTATION_RESET_DELAY = 200;
8392
+ function findLastTextNode(root) {
8393
+ const walker = root.ownerDocument.createTreeWalker(root, NodeFilter.SHOW_TEXT);
8394
+ let lastTextNode = null;
8395
+ while (walker.nextNode()) {
8396
+ const textNode = walker.currentNode;
8397
+ if (textNode.nodeValue !== '') {
8398
+ lastTextNode = textNode;
8399
+ }
8400
+ }
8401
+ return lastTextNode;
8402
+ }
8403
+ function useInitialLiveRegionTextMutation() {
8404
+ const timeout = useTimeout();
8405
+ const rootRef = React.useRef(null);
8406
+
8407
+ // Only the initial mounted announcement needs the marker; later text updates announce naturally.
8408
+ React.useEffect(() => {
8409
+ if (isIOS) {
8410
+ return undefined;
8411
+ }
8412
+ const root = rootRef.current;
8413
+ if (root == null) {
8414
+ return undefined;
8415
+ }
8416
+ const textNode = findLastTextNode(root);
8417
+ if (textNode == null) {
8418
+ return undefined;
8419
+ }
8420
+ const originalValue = textNode.nodeValue ?? '';
8421
+ const markedValue = `${originalValue}${LIVE_REGION_MARKER}`;
8422
+ textNode.nodeValue = markedValue;
8423
+ timeout.start(INITIAL_LIVE_REGION_TEXT_MUTATION_RESET_DELAY, () => {
8424
+ if (textNode.nodeValue === markedValue) {
8425
+ textNode.nodeValue = originalValue;
8426
+ }
8427
+ });
8428
+ return () => {
8429
+ timeout.clear();
8430
+ if (textNode.nodeValue === markedValue) {
8431
+ textNode.nodeValue = originalValue;
8432
+ }
8433
+ };
8434
+ }, [rootRef, timeout]);
8435
+ return rootRef;
8436
+ }
8437
+
8817
8438
  const ComboboxPortalContext = /*#__PURE__*/React.createContext(undefined);
8818
8439
  function useComboboxPortalContext() {
8819
8440
  const context = React.useContext(ComboboxPortalContext);
@@ -9032,6 +8653,7 @@ function useAnchorPositioning(params) {
9032
8653
  const anchorFnCallback = useStableCallback(anchorFn);
9033
8654
  const anchorDep = anchorFn ? anchorFnCallback : anchor;
9034
8655
  const anchorValueRef = useValueAsRef(anchor);
8656
+ const mountedRef = useValueAsRef(mounted);
9035
8657
  const direction = useDirection();
9036
8658
  const isRtl = direction === 'rtl';
9037
8659
  const side = mountSide || {
@@ -9157,12 +8779,15 @@ function useAnchorPositioning(params) {
9157
8779
  availableHeight,
9158
8780
  rects
9159
8781
  }) {
8782
+ if (!mountedRef.current) {
8783
+ return;
8784
+ }
9160
8785
  const floatingStyle = floating.style;
9161
8786
  floatingStyle.setProperty('--available-width', `${availableWidth}px`);
9162
8787
  floatingStyle.setProperty('--available-height', `${availableHeight}px`);
9163
8788
 
9164
8789
  // Snap anchor dimensions to device pixels to ensure the popup's visual width matches the anchor's one.
9165
- const dpr = window.devicePixelRatio || 1;
8790
+ const dpr = getWindow(floating).devicePixelRatio || 1;
9166
8791
  const {
9167
8792
  x,
9168
8793
  y,
@@ -9177,7 +8802,7 @@ function useAnchorPositioning(params) {
9177
8802
  }), arrow(() => ({
9178
8803
  // `transform-origin` calculations rely on an element existing. If the arrow hasn't been set,
9179
8804
  // we'll create a fake element.
9180
- element: arrowRef.current || document.createElement('div'),
8805
+ element: arrowRef.current || ownerDocument(arrowRef.current).createElement('div'),
9181
8806
  padding: arrowPadding,
9182
8807
  offsetParent: 'floating'
9183
8808
  }), [arrowPadding]), {
@@ -9221,7 +8846,8 @@ function useAnchorPositioning(params) {
9221
8846
  floatingRootContext.update({
9222
8847
  referenceElement: null,
9223
8848
  floatingElement: null,
9224
- domReferenceElement: null
8849
+ domReferenceElement: null,
8850
+ positionReference: null
9225
8851
  });
9226
8852
  }
9227
8853
  }, [mounted, floatingRootContext]);
@@ -9242,6 +8868,7 @@ function useAnchorPositioning(params) {
9242
8868
  floatingStyles: originalFloatingStyles
9243
8869
  } = useFloating({
9244
8870
  rootContext: floatingRootContext,
8871
+ open: keepMounted ? mounted : undefined,
9245
8872
  placement,
9246
8873
  middleware,
9247
8874
  strategy: positionMethod,
@@ -9351,6 +8978,61 @@ function getDisabledMountTransitionStyles(transitionStatus) {
9351
8978
  return transitionStatus === 'starting' ? DISABLED_TRANSITIONS_STYLE : EMPTY_OBJECT;
9352
8979
  }
9353
8980
 
8981
+ /**
8982
+ * Renders the shared outer Positioner element used by popup components.
8983
+ * Applies the common role, hidden state, transition styles, state attributes, and optional inert styling.
8984
+ */
8985
+ function usePositioner(componentProps, state, {
8986
+ styles,
8987
+ transitionStatus,
8988
+ props,
8989
+ refs,
8990
+ hidden,
8991
+ inert = false
8992
+ }) {
8993
+ const style = {
8994
+ ...styles
8995
+ };
8996
+ if (inert) {
8997
+ style.pointerEvents = 'none';
8998
+ }
8999
+ return useRenderElement('div', componentProps, {
9000
+ state,
9001
+ ref: refs,
9002
+ props: [{
9003
+ role: 'presentation',
9004
+ hidden,
9005
+ style
9006
+ }, getDisabledMountTransitionStyles(transitionStatus), props],
9007
+ stateAttributesMapping: popupStateMapping
9008
+ });
9009
+ }
9010
+
9011
+ // Touch-opened popups normally avoid scroll locking so users can still swipe outside to dismiss.
9012
+ // This hook re-enables scroll lock only when the popup is effectively full-width.
9013
+ // Treat popups with up to 20px of total horizontal gutter as full-width so common ~10px side
9014
+ // padding still locks scroll, since that leaves too little outside space for a reliable swipe.
9015
+ const VIEWPORT_WIDTH_TOLERANCE_PX = 20;
9016
+
9017
+ /**
9018
+ * Manages scroll lock for anchored popups. For non-touch opens, scroll lock is applied when
9019
+ * enabled. For touch opens, scroll lock is applied only when the positioner width is effectively
9020
+ * viewport-sized.
9021
+ */
9022
+ function useAnchoredPopupScrollLock(enabled, touchOpen, positionerElement, referenceElement) {
9023
+ const [touchOpenShouldLockScroll, setTouchOpenShouldLockScroll] = React.useState(false);
9024
+ useIsoLayoutEffect(() => {
9025
+ if (!enabled || !touchOpen || positionerElement == null) {
9026
+ setTouchOpenShouldLockScroll(false);
9027
+ return;
9028
+ }
9029
+ const viewportWidth = ownerDocument(positionerElement).documentElement.clientWidth;
9030
+ const popupWidth = positionerElement.offsetWidth;
9031
+ setTouchOpenShouldLockScroll(viewportWidth > 0 && popupWidth > 0 && popupWidth >= viewportWidth - VIEWPORT_WIDTH_TOLERANCE_PX);
9032
+ }, [enabled, touchOpen, positionerElement]);
9033
+ useScrollLock(enabled && (!touchOpen || touchOpenShouldLockScroll), referenceElement);
9034
+ }
9035
+
9354
9036
  const ComboboxPositioner = /*#__PURE__*/React.forwardRef(function ComboboxPositioner(componentProps, forwardedRef) {
9355
9037
  const {
9356
9038
  render,
@@ -9367,6 +9049,7 @@ const ComboboxPositioner = /*#__PURE__*/React.forwardRef(function ComboboxPositi
9367
9049
  sticky = false,
9368
9050
  disableAnchorTracking = false,
9369
9051
  collisionAvoidance = DROPDOWN_COLLISION_AVOIDANCE,
9052
+ style: styleProp,
9370
9053
  ...elementProps
9371
9054
  } = componentProps;
9372
9055
  const store = useComboboxRootContext();
@@ -9379,6 +9062,7 @@ const ComboboxPositioner = /*#__PURE__*/React.forwardRef(function ComboboxPositi
9379
9062
  const open = useStore(store, selectors.open);
9380
9063
  const mounted = useStore(store, selectors.mounted);
9381
9064
  const openMethod = useStore(store, selectors.openMethod);
9065
+ const positionerElement = useStore(store, selectors.positionerElement);
9382
9066
  const triggerElement = useStore(store, selectors.triggerElement);
9383
9067
  const inputElement = useStore(store, selectors.inputElement);
9384
9068
  const inputGroupElement = useStore(store, selectors.inputGroupElement);
@@ -9404,20 +9088,7 @@ const ComboboxPositioner = /*#__PURE__*/React.forwardRef(function ComboboxPositi
9404
9088
  collisionAvoidance,
9405
9089
  lazyFlip: true
9406
9090
  });
9407
- useScrollLock(open && modal && openMethod !== 'touch', triggerElement);
9408
- const defaultProps = React.useMemo(() => {
9409
- const style = {
9410
- ...positioning.positionerStyles
9411
- };
9412
- if (!open) {
9413
- style.pointerEvents = 'none';
9414
- }
9415
- return {
9416
- role: 'presentation',
9417
- hidden: !mounted,
9418
- style
9419
- };
9420
- }, [open, mounted, positioning.positionerStyles]);
9091
+ useAnchoredPopupScrollLock(open && modal, openMethod === 'touch', positionerElement, triggerElement);
9421
9092
  const state = {
9422
9093
  open,
9423
9094
  side: positioning.side,
@@ -9428,26 +9099,19 @@ const ComboboxPositioner = /*#__PURE__*/React.forwardRef(function ComboboxPositi
9428
9099
  useIsoLayoutEffect(() => {
9429
9100
  store.set('popupSide', positioning.side);
9430
9101
  }, [store, positioning.side]);
9431
- const contextValue = React.useMemo(() => ({
9432
- side: positioning.side,
9433
- align: positioning.align,
9434
- arrowRef: positioning.arrowRef,
9435
- arrowUncentered: positioning.arrowUncentered,
9436
- arrowStyles: positioning.arrowStyles,
9437
- anchorHidden: positioning.anchorHidden,
9438
- isPositioned: positioning.isPositioned
9439
- }), [positioning.side, positioning.align, positioning.arrowRef, positioning.arrowUncentered, positioning.arrowStyles, positioning.anchorHidden, positioning.isPositioned]);
9440
9102
  const setPositionerElement = useStableCallback(element => {
9441
9103
  store.set('positionerElement', element);
9442
9104
  });
9443
- const element = useRenderElement('div', componentProps, {
9444
- state,
9445
- ref: [forwardedRef, setPositionerElement],
9446
- props: [defaultProps, getDisabledMountTransitionStyles(transitionStatus), elementProps],
9447
- stateAttributesMapping: popupStateMapping
9105
+ const element = usePositioner(componentProps, state, {
9106
+ styles: positioning.positionerStyles,
9107
+ transitionStatus,
9108
+ props: elementProps,
9109
+ refs: [forwardedRef, setPositionerElement],
9110
+ hidden: !mounted,
9111
+ inert: !open
9448
9112
  });
9449
9113
  return /*#__PURE__*/jsxs(ComboboxPositionerContext.Provider, {
9450
- value: contextValue,
9114
+ value: positioning,
9451
9115
  children: [mounted && modal && /*#__PURE__*/jsx(InternalBackdrop, {
9452
9116
  inert: inertValue(!open),
9453
9117
  cutout: inputGroupElement ?? inputElement ?? triggerElement
@@ -9463,11 +9127,14 @@ const stateAttributesMapping = {
9463
9127
  /**
9464
9128
  * A container for the list.
9465
9129
  * Renders a `<div>` element.
9130
+ *
9131
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
9466
9132
  */
9467
9133
  const ComboboxPopup = /*#__PURE__*/React.forwardRef(function ComboboxPopup(componentProps, forwardedRef) {
9468
9134
  const {
9469
9135
  render,
9470
9136
  className,
9137
+ style,
9471
9138
  initialFocus,
9472
9139
  finalFocus,
9473
9140
  ...elementProps
@@ -9560,6 +9227,7 @@ const ComboboxGroup$2 = /*#__PURE__*/React.forwardRef(function ComboboxGroup(com
9560
9227
  const {
9561
9228
  render,
9562
9229
  className,
9230
+ style,
9563
9231
  items,
9564
9232
  ...elementProps
9565
9233
  } = componentProps;
@@ -9592,11 +9260,14 @@ const ComboboxGroup$2 = /*#__PURE__*/React.forwardRef(function ComboboxGroup(com
9592
9260
  /**
9593
9261
  * An accessible label that is automatically associated with its parent group.
9594
9262
  * Renders a `<div>` element.
9263
+ *
9264
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
9595
9265
  */
9596
9266
  const ComboboxGroupLabel = /*#__PURE__*/React.forwardRef(function ComboboxGroupLabel(componentProps, forwardedRef) {
9597
9267
  const {
9598
9268
  render,
9599
9269
  className,
9270
+ style,
9600
9271
  id: idProp,
9601
9272
  ...elementProps
9602
9273
  } = componentProps;
@@ -9641,6 +9312,7 @@ const ComboboxItem$2 = /*#__PURE__*/React.memo(/*#__PURE__*/React.forwardRef(fun
9641
9312
  index: indexProp,
9642
9313
  disabled = false,
9643
9314
  nativeButton = false,
9315
+ style,
9644
9316
  ...elementProps
9645
9317
  } = componentProps;
9646
9318
  const didPointerDownRef = React.useRef(false);
@@ -9756,6 +9428,11 @@ const ComboboxItem$2 = /*#__PURE__*/React.memo(/*#__PURE__*/React.forwardRef(fun
9756
9428
  didPointerDownRef.current = true;
9757
9429
  event.preventDefault();
9758
9430
  },
9431
+ onMouseDown(event) {
9432
+ // iOS Safari can emit a synthetic mousedown for touch taps without a preceding
9433
+ // pointerdown. Prevent default here too so tapping an item does not blur the input.
9434
+ event.preventDefault();
9435
+ },
9759
9436
  onClick(event) {
9760
9437
  if (disabled || readOnly) {
9761
9438
  return;
@@ -9790,12 +9467,19 @@ const ComboboxItem$2 = /*#__PURE__*/React.memo(/*#__PURE__*/React.forwardRef(fun
9790
9467
  * Renders its children only when the list is empty.
9791
9468
  * Requires the `items` prop on the root component.
9792
9469
  * Announces changes politely to screen readers.
9470
+ * This component's root element must remain mounted in the DOM to announce
9471
+ * changes consistently across screen readers. Avoid hiding or removing the
9472
+ * component itself with `display: none`, `hidden`, `aria-hidden`, or conditional
9473
+ * rendering. Prefer updating or conditionally rendering its children instead.
9793
9474
  * Renders a `<div>` element.
9475
+ *
9476
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
9794
9477
  */
9795
9478
  const ComboboxEmpty$2 = /*#__PURE__*/React.forwardRef(function ComboboxEmpty(componentProps, forwardedRef) {
9796
9479
  const {
9797
9480
  render,
9798
9481
  className,
9482
+ style,
9799
9483
  children: childrenProp,
9800
9484
  ...elementProps
9801
9485
  } = componentProps;
@@ -9803,9 +9487,10 @@ const ComboboxEmpty$2 = /*#__PURE__*/React.forwardRef(function ComboboxEmpty(com
9803
9487
  filteredItems
9804
9488
  } = useComboboxDerivedItemsContext();
9805
9489
  const store = useComboboxRootContext();
9490
+ const emptyRef = useInitialLiveRegionTextMutation();
9806
9491
  const children = filteredItems.length === 0 ? childrenProp : null;
9807
9492
  return useRenderElement('div', componentProps, {
9808
- ref: [forwardedRef, store.state.emptyRef],
9493
+ ref: [forwardedRef, store.state.emptyRef, emptyRef],
9809
9494
  props: [{
9810
9495
  children,
9811
9496
  role: 'status',
@@ -9826,6 +9511,7 @@ const Separator = /*#__PURE__*/React.forwardRef(function SeparatorComponent(comp
9826
9511
  className,
9827
9512
  render,
9828
9513
  orientation = 'horizontal',
9514
+ style,
9829
9515
  ...elementProps
9830
9516
  } = componentProps;
9831
9517
  const state = {
@@ -9911,6 +9597,7 @@ const Inner = /*#__PURE__*/React.memo(/*#__PURE__*/React.forwardRef((componentPr
9911
9597
  const {
9912
9598
  render,
9913
9599
  className,
9600
+ style,
9914
9601
  keepMounted,
9915
9602
  ...elementProps
9916
9603
  } = componentProps;
@@ -9951,6 +9638,7 @@ const ComboboxChips$2 = /*#__PURE__*/React.forwardRef(function ComboboxChips(com
9951
9638
  const {
9952
9639
  render,
9953
9640
  className,
9641
+ style,
9954
9642
  ...elementProps
9955
9643
  } = componentProps;
9956
9644
  const store = useComboboxRootContext();
@@ -9967,7 +9655,11 @@ const ComboboxChips$2 = /*#__PURE__*/React.forwardRef(function ComboboxChips(com
9967
9655
  // arrow keys inside a container unless it has a toolbar role.
9968
9656
  props: [hasSelectionChips ? {
9969
9657
  role: 'toolbar'
9970
- } : EMPTY_OBJECT, elementProps]
9658
+ } : EMPTY_OBJECT, {
9659
+ onMouseDown(event) {
9660
+ handleInputPress(event, store, store.state.disabled, store.state.readOnly);
9661
+ }
9662
+ }, elementProps]
9971
9663
  });
9972
9664
  const contextValue = React.useMemo(() => ({
9973
9665
  highlightedChipIndex,
@@ -9996,6 +9688,7 @@ const ComboboxChip$2 = /*#__PURE__*/React.forwardRef(function ComboboxChip(compo
9996
9688
  const {
9997
9689
  render,
9998
9690
  className,
9691
+ style,
9999
9692
  ...elementProps
10000
9693
  } = componentProps;
10001
9694
  const store = useComboboxRootContext();
@@ -10021,7 +9714,7 @@ const ComboboxChip$2 = /*#__PURE__*/React.forwardRef(function ComboboxChip(compo
10021
9714
  }
10022
9715
  } else if (event.key === 'ArrowRight') {
10023
9716
  event.preventDefault();
10024
- if (index < selectedValue.length - 1) {
9717
+ if (index < chipsRef.current.length - 1) {
10025
9718
  nextIndex = index + 1;
10026
9719
  } else {
10027
9720
  nextIndex = undefined;
@@ -10073,16 +9766,6 @@ const ComboboxChip$2 = /*#__PURE__*/React.forwardRef(function ComboboxChip(compo
10073
9766
  } else {
10074
9767
  chipsRef.current[nextIndex]?.focus();
10075
9768
  }
10076
- },
10077
- onMouseDown(event) {
10078
- if (readOnly) {
10079
- return;
10080
- }
10081
- event.preventDefault();
10082
- if (disabled) {
10083
- return;
10084
- }
10085
- store.state.inputRef.current?.focus();
10086
9769
  }
10087
9770
  }, elementProps]
10088
9771
  });
@@ -10098,6 +9781,8 @@ const ComboboxChip$2 = /*#__PURE__*/React.forwardRef(function ComboboxChip(compo
10098
9781
  /**
10099
9782
  * A button to remove a chip.
10100
9783
  * Renders a `<button>` element.
9784
+ *
9785
+ * Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
10101
9786
  */
10102
9787
  const ComboboxChipRemove = /*#__PURE__*/React.forwardRef(function ComboboxChipRemove(componentProps, forwardedRef) {
10103
9788
  const {
@@ -10105,6 +9790,7 @@ const ComboboxChipRemove = /*#__PURE__*/React.forwardRef(function ComboboxChipRe
10105
9790
  className,
10106
9791
  disabled: disabledProp = false,
10107
9792
  nativeButton = true,
9793
+ style,
10108
9794
  ...elementProps
10109
9795
  } = componentProps;
10110
9796
  const store = useComboboxRootContext();
@@ -10156,6 +9842,9 @@ const ComboboxChipRemove = /*#__PURE__*/React.forwardRef(function ComboboxChipRe
10156
9842
  state,
10157
9843
  props: [{
10158
9844
  tabIndex: -1,
9845
+ onMouseDown(event) {
9846
+ event.preventDefault();
9847
+ },
10159
9848
  onClick(event) {
10160
9849
  if (disabled || readOnly) {
10161
9850
  return;
@@ -10224,9 +9913,7 @@ function ComboboxChips$1({ className, ...props }) {
10224
9913
  function ComboboxChip$1({ className, children, showRemove = true, ...props }) {
10225
9914
  return (jsxs(ComboboxChip$2, { "data-slot": "combobox-chip", className: cn("flex h-[calc(--spacing(5.25))] w-fit items-center justify-center gap-1 rounded-sm bg-muted px-1.5 text-xs font-medium whitespace-nowrap text-foreground has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pe-0", className), ...props, children: [children, showRemove && (jsx(ComboboxChipRemove, { render: jsx(Button, { variant: "ghost", size: "icon-xs" }), className: "-ms-1 opacity-50 hover:opacity-100", "data-slot": "combobox-chip-remove", children: jsx(X, { className: "pointer-events-none" }) }))] }));
10226
9915
  }
10227
- function ComboboxChipsInput$1({ className, ...props }) {
10228
- return (jsx(ComboboxInput$2, { "data-slot": "combobox-chip-input", className: cn("min-w-16 flex-1 outline-none", className), ...props }));
10229
- }
9916
+ const ComboboxChipsInput$1 = React.forwardRef(({ className, ...props }, ref) => (jsx(ComboboxInput$2, { ref: ref, "data-slot": "combobox-chip-input", className: cn("min-w-16 flex-1 outline-none", className), ...props })));
10230
9917
  function useComboboxAnchor() {
10231
9918
  return React.useRef(null);
10232
9919
  }
@@ -10243,7 +9930,7 @@ const ComboboxEmpty = (props) => jsx(ComboboxEmpty$1, { ...props });
10243
9930
  const ComboboxSeparator = (props) => jsx(ComboboxSeparator$1, { ...props });
10244
9931
  const ComboboxChips = (props) => jsx(ComboboxChips$1, { ...props });
10245
9932
  const ComboboxChip = (props) => jsx(ComboboxChip$1, { ...props });
10246
- const ComboboxChipsInput = (props) => jsx(ComboboxChipsInput$1, { ...props });
9933
+ const ComboboxChipsInput = React__default.forwardRef((props, ref) => jsx(ComboboxChipsInput$1, { ref: ref, ...props }));
10247
9934
  const ComboboxTrigger = (props) => jsx(ComboboxTrigger$1, { ...props });
10248
9935
  const ComboboxValue = (props) => jsx(ComboboxValue$1, { ...props });
10249
9936