@proyecto-viviana/solidaria-components 0.3.2 → 0.4.1

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 (417) hide show
  1. package/dist/ActionBar.d.ts.map +1 -1
  2. package/dist/ActionBar.js +175 -0
  3. package/dist/ActionBar.js.map +1 -0
  4. package/dist/ActionBar.jsx +119 -0
  5. package/dist/ActionBar.jsx.map +1 -0
  6. package/dist/ActionGroup.d.ts.map +1 -1
  7. package/dist/ActionGroup.js +179 -0
  8. package/dist/ActionGroup.js.map +1 -0
  9. package/dist/ActionGroup.jsx +129 -0
  10. package/dist/ActionGroup.jsx.map +1 -0
  11. package/dist/Alert.js +111 -0
  12. package/dist/Alert.js.map +1 -0
  13. package/dist/Alert.jsx +82 -0
  14. package/dist/Alert.jsx.map +1 -0
  15. package/dist/Autocomplete.d.ts +2 -2
  16. package/dist/Autocomplete.d.ts.map +1 -1
  17. package/dist/Autocomplete.js +130 -0
  18. package/dist/Autocomplete.js.map +1 -0
  19. package/dist/Autocomplete.jsx +116 -0
  20. package/dist/Autocomplete.jsx.map +1 -0
  21. package/dist/Breadcrumbs.d.ts.map +1 -1
  22. package/dist/Breadcrumbs.js +333 -0
  23. package/dist/Breadcrumbs.js.map +1 -0
  24. package/dist/Breadcrumbs.jsx +261 -0
  25. package/dist/Breadcrumbs.jsx.map +1 -0
  26. package/dist/Button.d.ts.map +1 -1
  27. package/dist/Button.js +348 -0
  28. package/dist/Button.js.map +1 -0
  29. package/dist/Button.jsx +314 -0
  30. package/dist/Button.jsx.map +1 -0
  31. package/dist/Calendar.d.ts +4 -4
  32. package/dist/Calendar.d.ts.map +1 -1
  33. package/dist/Calendar.js +573 -0
  34. package/dist/Calendar.js.map +1 -0
  35. package/dist/Calendar.jsx +342 -0
  36. package/dist/Calendar.jsx.map +1 -0
  37. package/dist/CalendarPicker.d.ts +33 -0
  38. package/dist/CalendarPicker.d.ts.map +1 -0
  39. package/dist/CalendarPicker.js +44 -0
  40. package/dist/CalendarPicker.js.map +1 -0
  41. package/dist/CalendarPicker.jsx +44 -0
  42. package/dist/CalendarPicker.jsx.map +1 -0
  43. package/dist/Checkbox.d.ts +83 -4
  44. package/dist/Checkbox.d.ts.map +1 -1
  45. package/dist/Checkbox.js +923 -0
  46. package/dist/Checkbox.js.map +1 -0
  47. package/dist/Checkbox.jsx +707 -0
  48. package/dist/Checkbox.jsx.map +1 -0
  49. package/dist/Collection.d.ts.map +1 -1
  50. package/dist/Collection.js +202 -0
  51. package/dist/Collection.js.map +1 -0
  52. package/dist/Collection.jsx +152 -0
  53. package/dist/Collection.jsx.map +1 -0
  54. package/dist/Color.d.ts.map +1 -1
  55. package/dist/Color.js +1717 -0
  56. package/dist/Color.js.map +1 -0
  57. package/dist/Color.jsx +1340 -0
  58. package/dist/Color.jsx.map +1 -0
  59. package/dist/ColorEditor.js +208 -0
  60. package/dist/ColorEditor.js.map +1 -0
  61. package/dist/ColorEditor.jsx +120 -0
  62. package/dist/ColorEditor.jsx.map +1 -0
  63. package/dist/ComboBox.d.ts +8 -4
  64. package/dist/ComboBox.d.ts.map +1 -1
  65. package/dist/ComboBox.js +1000 -0
  66. package/dist/ComboBox.js.map +1 -0
  67. package/dist/ComboBox.jsx +724 -0
  68. package/dist/ComboBox.jsx.map +1 -0
  69. package/dist/ContextualHelpTrigger.js +146 -0
  70. package/dist/ContextualHelpTrigger.js.map +1 -0
  71. package/dist/ContextualHelpTrigger.jsx +109 -0
  72. package/dist/ContextualHelpTrigger.jsx.map +1 -0
  73. package/dist/DateField.d.ts +14 -5
  74. package/dist/DateField.d.ts.map +1 -1
  75. package/dist/DateField.js +4 -0
  76. package/dist/DateField.jsx +4 -0
  77. package/dist/DateField2.js +502 -0
  78. package/dist/DateField2.js.map +1 -0
  79. package/dist/DateField2.jsx +354 -0
  80. package/dist/DateField2.jsx.map +1 -0
  81. package/dist/DatePicker.d.ts +46 -7
  82. package/dist/DatePicker.d.ts.map +1 -1
  83. package/dist/DatePicker.js +7 -0
  84. package/dist/DatePicker.jsx +7 -0
  85. package/dist/DatePicker2.js +1171 -0
  86. package/dist/DatePicker2.js.map +1 -0
  87. package/dist/DatePicker2.jsx +820 -0
  88. package/dist/DatePicker2.jsx.map +1 -0
  89. package/dist/DateRangePickerContext.d.ts +2 -0
  90. package/dist/DateRangePickerContext.d.ts.map +1 -1
  91. package/dist/Dialog.d.ts.map +1 -1
  92. package/dist/Dialog.js +337 -0
  93. package/dist/Dialog.js.map +1 -0
  94. package/dist/Dialog.jsx +192 -0
  95. package/dist/Dialog.jsx.map +1 -0
  96. package/dist/Disclosure.d.ts.map +1 -1
  97. package/dist/Disclosure.js +331 -0
  98. package/dist/Disclosure.js.map +1 -0
  99. package/dist/Disclosure.jsx +230 -0
  100. package/dist/Disclosure.jsx.map +1 -0
  101. package/dist/DragAndDrop.d.ts.map +1 -1
  102. package/dist/DragAndDrop.js +176 -0
  103. package/dist/DragAndDrop.js.map +1 -0
  104. package/dist/DragAndDrop.jsx +160 -0
  105. package/dist/DragAndDrop.jsx.map +1 -0
  106. package/dist/DropZone.d.ts.map +1 -1
  107. package/dist/DropZone.js +189 -0
  108. package/dist/DropZone.js.map +1 -0
  109. package/dist/DropZone.jsx +144 -0
  110. package/dist/DropZone.jsx.map +1 -0
  111. package/dist/FieldError.js +66 -0
  112. package/dist/FieldError.js.map +1 -0
  113. package/dist/FieldError.jsx +47 -0
  114. package/dist/FieldError.jsx.map +1 -0
  115. package/dist/FileTrigger.js +79 -0
  116. package/dist/FileTrigger.js.map +1 -0
  117. package/dist/FileTrigger.jsx +49 -0
  118. package/dist/FileTrigger.jsx.map +1 -0
  119. package/dist/Focusable.js +70 -0
  120. package/dist/Focusable.js.map +1 -0
  121. package/dist/Focusable.jsx +69 -0
  122. package/dist/Focusable.jsx.map +1 -0
  123. package/dist/Form.js +99 -0
  124. package/dist/Form.js.map +1 -0
  125. package/dist/Form.jsx +73 -0
  126. package/dist/Form.jsx.map +1 -0
  127. package/dist/GridList.d.ts +34 -2
  128. package/dist/GridList.d.ts.map +1 -1
  129. package/dist/GridList.js +723 -0
  130. package/dist/GridList.js.map +1 -0
  131. package/dist/GridList.jsx +552 -0
  132. package/dist/GridList.jsx.map +1 -0
  133. package/dist/Icon.d.ts.map +1 -1
  134. package/dist/Icon.js +127 -0
  135. package/dist/Icon.js.map +1 -0
  136. package/dist/Icon.jsx +72 -0
  137. package/dist/Icon.jsx.map +1 -0
  138. package/dist/Keyboard.js +30 -0
  139. package/dist/Keyboard.js.map +1 -0
  140. package/dist/Keyboard.jsx +24 -0
  141. package/dist/Keyboard.jsx.map +1 -0
  142. package/dist/Landmark.js +134 -0
  143. package/dist/Landmark.js.map +1 -0
  144. package/dist/Landmark.jsx +118 -0
  145. package/dist/Landmark.jsx.map +1 -0
  146. package/dist/Link.d.ts.map +1 -1
  147. package/dist/Link.js +219 -0
  148. package/dist/Link.js.map +1 -0
  149. package/dist/Link.jsx +189 -0
  150. package/dist/Link.jsx.map +1 -0
  151. package/dist/ListBox.d.ts +2 -2
  152. package/dist/ListBox.d.ts.map +1 -1
  153. package/dist/ListBox.js +831 -0
  154. package/dist/ListBox.js.map +1 -0
  155. package/dist/ListBox.jsx +644 -0
  156. package/dist/ListBox.jsx.map +1 -0
  157. package/dist/Menu.d.ts +27 -9
  158. package/dist/Menu.d.ts.map +1 -1
  159. package/dist/Menu.js +1254 -0
  160. package/dist/Menu.js.map +1 -0
  161. package/dist/Menu.jsx +1042 -0
  162. package/dist/Menu.jsx.map +1 -0
  163. package/dist/Meter.d.ts.map +1 -1
  164. package/dist/Meter.js +123 -0
  165. package/dist/Meter.js.map +1 -0
  166. package/dist/Meter.jsx +107 -0
  167. package/dist/Meter.jsx.map +1 -0
  168. package/dist/Modal.d.ts.map +1 -1
  169. package/dist/Modal.js +382 -0
  170. package/dist/Modal.js.map +1 -0
  171. package/dist/Modal.jsx +314 -0
  172. package/dist/Modal.jsx.map +1 -0
  173. package/dist/NumberField.d.ts +3 -3
  174. package/dist/NumberField.d.ts.map +1 -1
  175. package/dist/NumberField.js +573 -0
  176. package/dist/NumberField.js.map +1 -0
  177. package/dist/NumberField.jsx +443 -0
  178. package/dist/NumberField.jsx.map +1 -0
  179. package/dist/Popover.d.ts +10 -2
  180. package/dist/Popover.d.ts.map +1 -1
  181. package/dist/Popover.js +471 -0
  182. package/dist/Popover.js.map +1 -0
  183. package/dist/Popover.jsx +354 -0
  184. package/dist/Popover.jsx.map +1 -0
  185. package/dist/Pressable.js +69 -0
  186. package/dist/Pressable.js.map +1 -0
  187. package/dist/Pressable.jsx +68 -0
  188. package/dist/Pressable.jsx.map +1 -0
  189. package/dist/ProgressBar.d.ts.map +1 -1
  190. package/dist/ProgressBar.js +130 -0
  191. package/dist/ProgressBar.js.map +1 -0
  192. package/dist/ProgressBar.jsx +114 -0
  193. package/dist/ProgressBar.jsx.map +1 -0
  194. package/dist/RadioGroup.d.ts +82 -4
  195. package/dist/RadioGroup.d.ts.map +1 -1
  196. package/dist/RadioGroup.js +931 -0
  197. package/dist/RadioGroup.js.map +1 -0
  198. package/dist/RadioGroup.jsx +681 -0
  199. package/dist/RadioGroup.jsx.map +1 -0
  200. package/dist/RangeCalendar.d.ts.map +1 -1
  201. package/dist/RangeCalendar.js +546 -0
  202. package/dist/RangeCalendar.js.map +1 -0
  203. package/dist/RangeCalendar.jsx +323 -0
  204. package/dist/RangeCalendar.jsx.map +1 -0
  205. package/dist/RouterProvider.js +118 -0
  206. package/dist/RouterProvider.js.map +1 -0
  207. package/dist/RouterProvider.jsx +112 -0
  208. package/dist/RouterProvider.jsx.map +1 -0
  209. package/dist/SearchField.d.ts +2 -2
  210. package/dist/SearchField.d.ts.map +1 -1
  211. package/dist/SearchField.js +667 -0
  212. package/dist/SearchField.js.map +1 -0
  213. package/dist/SearchField.jsx +550 -0
  214. package/dist/SearchField.jsx.map +1 -0
  215. package/dist/Select.d.ts +7 -0
  216. package/dist/Select.d.ts.map +1 -1
  217. package/dist/Select.js +1044 -0
  218. package/dist/Select.js.map +1 -0
  219. package/dist/Select.jsx +759 -0
  220. package/dist/Select.jsx.map +1 -0
  221. package/dist/SelectionIndicator.d.ts.map +1 -1
  222. package/dist/SelectionIndicator.js +86 -0
  223. package/dist/SelectionIndicator.js.map +1 -0
  224. package/dist/SelectionIndicator.jsx +50 -0
  225. package/dist/SelectionIndicator.jsx.map +1 -0
  226. package/dist/Separator.js +97 -0
  227. package/dist/Separator.js.map +1 -0
  228. package/dist/Separator.jsx +85 -0
  229. package/dist/Separator.jsx.map +1 -0
  230. package/dist/SharedElementTransition.d.ts.map +1 -1
  231. package/dist/SharedElementTransition.js +167 -0
  232. package/dist/SharedElementTransition.js.map +1 -0
  233. package/dist/SharedElementTransition.jsx +140 -0
  234. package/dist/SharedElementTransition.jsx.map +1 -0
  235. package/dist/Slider.d.ts +33 -1
  236. package/dist/Slider.d.ts.map +1 -1
  237. package/dist/Slider.js +515 -0
  238. package/dist/Slider.js.map +1 -0
  239. package/dist/Slider.jsx +403 -0
  240. package/dist/Slider.jsx.map +1 -0
  241. package/dist/StepList.d.ts.map +1 -1
  242. package/dist/StepList.js +191 -0
  243. package/dist/StepList.js.map +1 -0
  244. package/dist/StepList.jsx +136 -0
  245. package/dist/StepList.jsx.map +1 -0
  246. package/dist/Switch.d.ts +65 -2
  247. package/dist/Switch.d.ts.map +1 -1
  248. package/dist/Switch.js +534 -0
  249. package/dist/Switch.js.map +1 -0
  250. package/dist/Switch.jsx +393 -0
  251. package/dist/Switch.jsx.map +1 -0
  252. package/dist/Table.d.ts +50 -0
  253. package/dist/Table.d.ts.map +1 -1
  254. package/dist/Table.js +1766 -0
  255. package/dist/Table.js.map +1 -0
  256. package/dist/Table.jsx +1355 -0
  257. package/dist/Table.jsx.map +1 -0
  258. package/dist/Tabs.d.ts +0 -4
  259. package/dist/Tabs.d.ts.map +1 -1
  260. package/dist/Tabs.js +598 -0
  261. package/dist/Tabs.js.map +1 -0
  262. package/dist/Tabs.jsx +367 -0
  263. package/dist/Tabs.jsx.map +1 -0
  264. package/dist/TagGroup.d.ts +3 -1
  265. package/dist/TagGroup.d.ts.map +1 -1
  266. package/dist/TagGroup.js +382 -0
  267. package/dist/TagGroup.js.map +1 -0
  268. package/dist/TagGroup.jsx +273 -0
  269. package/dist/TagGroup.jsx.map +1 -0
  270. package/dist/Text.d.ts +18 -6
  271. package/dist/Text.d.ts.map +1 -1
  272. package/dist/Text.js +42 -0
  273. package/dist/Text.js.map +1 -0
  274. package/dist/Text.jsx +35 -0
  275. package/dist/Text.jsx.map +1 -0
  276. package/dist/TextField.d.ts +6 -6
  277. package/dist/TextField.d.ts.map +1 -1
  278. package/dist/TextField.js +439 -0
  279. package/dist/TextField.js.map +1 -0
  280. package/dist/TextField.jsx +406 -0
  281. package/dist/TextField.jsx.map +1 -0
  282. package/dist/TimeField.d.ts +17 -53
  283. package/dist/TimeField.d.ts.map +1 -1
  284. package/dist/TimeField.js +278 -0
  285. package/dist/TimeField.js.map +1 -0
  286. package/dist/TimeField.jsx +218 -0
  287. package/dist/TimeField.jsx.map +1 -0
  288. package/dist/Toast.d.ts +14 -0
  289. package/dist/Toast.d.ts.map +1 -1
  290. package/dist/Toast.js +551 -0
  291. package/dist/Toast.js.map +1 -0
  292. package/dist/Toast.jsx +361 -0
  293. package/dist/Toast.jsx.map +1 -0
  294. package/dist/ToggleButton.d.ts.map +1 -1
  295. package/dist/ToggleButton.js +123 -0
  296. package/dist/ToggleButton.js.map +1 -0
  297. package/dist/ToggleButton.jsx +88 -0
  298. package/dist/ToggleButton.jsx.map +1 -0
  299. package/dist/ToggleButtonGroup.d.ts.map +1 -1
  300. package/dist/ToggleButtonGroup.js +114 -0
  301. package/dist/ToggleButtonGroup.js.map +1 -0
  302. package/dist/ToggleButtonGroup.jsx +85 -0
  303. package/dist/ToggleButtonGroup.jsx.map +1 -0
  304. package/dist/Toolbar.js +112 -0
  305. package/dist/Toolbar.js.map +1 -0
  306. package/dist/Toolbar.jsx +92 -0
  307. package/dist/Toolbar.jsx.map +1 -0
  308. package/dist/Tooltip.d.ts.map +1 -1
  309. package/dist/Tooltip.js +539 -0
  310. package/dist/Tooltip.js.map +1 -0
  311. package/dist/Tooltip.jsx +465 -0
  312. package/dist/Tooltip.jsx.map +1 -0
  313. package/dist/Tree.d.ts +14 -2
  314. package/dist/Tree.d.ts.map +1 -1
  315. package/dist/Tree.js +1424 -0
  316. package/dist/Tree.js.map +1 -0
  317. package/dist/Tree.jsx +1172 -0
  318. package/dist/Tree.jsx.map +1 -0
  319. package/dist/Virtualizer.d.ts +16 -2
  320. package/dist/Virtualizer.d.ts.map +1 -1
  321. package/dist/Virtualizer.js +2 -0
  322. package/dist/Virtualizer.jsx +2 -0
  323. package/dist/Virtualizer2.js +751 -0
  324. package/dist/Virtualizer2.js.map +1 -0
  325. package/dist/Virtualizer2.jsx +730 -0
  326. package/dist/Virtualizer2.jsx.map +1 -0
  327. package/dist/VirtualizerLayouts.d.ts +18 -0
  328. package/dist/VirtualizerLayouts.d.ts.map +1 -1
  329. package/dist/VisuallyHidden.js +42 -0
  330. package/dist/VisuallyHidden.js.map +1 -0
  331. package/dist/VisuallyHidden.jsx +35 -0
  332. package/dist/VisuallyHidden.jsx.map +1 -0
  333. package/dist/contexts.js +33 -0
  334. package/dist/contexts.js.map +1 -0
  335. package/dist/contexts.jsx +33 -0
  336. package/dist/contexts.jsx.map +1 -0
  337. package/dist/index.d.ts +9 -9
  338. package/dist/index.d.ts.map +1 -1
  339. package/dist/index.js +69 -23932
  340. package/dist/index.jsx +69 -18337
  341. package/dist/useDragAndDrop.d.ts +0 -8
  342. package/dist/useDragAndDrop.d.ts.map +1 -1
  343. package/dist/useDragAndDrop.js +2 -0
  344. package/dist/useDragAndDrop.jsx +2 -0
  345. package/dist/useDragAndDrop2.js +399 -0
  346. package/dist/useDragAndDrop2.js.map +1 -0
  347. package/dist/useDragAndDrop2.jsx +399 -0
  348. package/dist/useDragAndDrop2.jsx.map +1 -0
  349. package/dist/utils.d.ts +84 -11
  350. package/dist/utils.d.ts.map +1 -1
  351. package/dist/utils.js +285 -0
  352. package/dist/utils.js.map +1 -0
  353. package/dist/utils.jsx +277 -0
  354. package/dist/utils.jsx.map +1 -0
  355. package/dist/virtualizer/Layout.js +144 -0
  356. package/dist/virtualizer/Layout.js.map +1 -0
  357. package/dist/virtualizer/Layout.jsx +144 -0
  358. package/dist/virtualizer/Layout.jsx.map +1 -0
  359. package/package.json +395 -4
  360. package/src/ActionBar.tsx +10 -12
  361. package/src/ActionGroup.tsx +5 -3
  362. package/src/Autocomplete.tsx +14 -9
  363. package/src/Breadcrumbs.tsx +58 -39
  364. package/src/Button.tsx +22 -2
  365. package/src/Calendar.tsx +57 -11
  366. package/src/CalendarPicker.tsx +73 -0
  367. package/src/Checkbox.tsx +539 -3
  368. package/src/Collection.tsx +9 -3
  369. package/src/Color.tsx +84 -41
  370. package/src/ComboBox.tsx +97 -21
  371. package/src/DateField.tsx +304 -53
  372. package/src/DatePicker.tsx +402 -62
  373. package/src/DateRangePickerContext.tsx +2 -0
  374. package/src/Dialog.tsx +13 -5
  375. package/src/Disclosure.tsx +7 -1
  376. package/src/DragAndDrop.tsx +3 -1
  377. package/src/DropZone.tsx +3 -1
  378. package/src/GridList.tsx +133 -26
  379. package/src/Icon.tsx +3 -1
  380. package/src/Link.tsx +3 -1
  381. package/src/ListBox.tsx +354 -25
  382. package/src/Menu.tsx +252 -128
  383. package/src/Meter.tsx +3 -1
  384. package/src/Modal.tsx +120 -56
  385. package/src/NumberField.tsx +51 -8
  386. package/src/Popover.tsx +68 -17
  387. package/src/ProgressBar.tsx +3 -1
  388. package/src/RadioGroup.tsx +468 -4
  389. package/src/RangeCalendar.tsx +123 -2
  390. package/src/SearchField.tsx +80 -4
  391. package/src/Select.tsx +122 -26
  392. package/src/SelectionIndicator.tsx +3 -1
  393. package/src/SharedElementTransition.tsx +95 -37
  394. package/src/Slider.tsx +159 -13
  395. package/src/StepList.tsx +0 -7
  396. package/src/Switch.tsx +395 -2
  397. package/src/Table.tsx +428 -99
  398. package/src/Tabs.tsx +17 -45
  399. package/src/TagGroup.tsx +29 -7
  400. package/src/Text.tsx +31 -10
  401. package/src/TextField.tsx +44 -6
  402. package/src/TimeField.tsx +127 -192
  403. package/src/Toast.tsx +79 -14
  404. package/src/ToggleButton.tsx +3 -1
  405. package/src/ToggleButtonGroup.tsx +3 -1
  406. package/src/Tooltip.tsx +3 -1
  407. package/src/Tree.tsx +91 -13
  408. package/src/Virtualizer.tsx +180 -31
  409. package/src/VirtualizerLayouts.ts +45 -10
  410. package/src/index.ts +51 -8
  411. package/src/useDragAndDrop.ts +8 -10
  412. package/src/utils.tsx +246 -30
  413. package/dist/HiddenTimeInput.d.ts +0 -25
  414. package/dist/HiddenTimeInput.d.ts.map +0 -1
  415. package/dist/index.js.map +0 -1
  416. package/dist/index.jsx.map +0 -1
  417. package/src/HiddenTimeInput.tsx +0 -133
package/src/Meter.tsx CHANGED
@@ -119,7 +119,9 @@ export function Meter(props: MeterProps): JSX.Element {
119
119
 
120
120
  const renderProps = useRenderProps(
121
121
  {
122
- children: props.children,
122
+ get children() {
123
+ return props.children;
124
+ },
123
125
  class: local.class,
124
126
  style: local.style,
125
127
  defaultClassName: "solidaria-Meter",
package/src/Modal.tsx CHANGED
@@ -22,6 +22,8 @@ import {
22
22
  ariaHideOutside,
23
23
  FocusScope,
24
24
  useUNSAFE_PortalContext,
25
+ createEnterAnimation,
26
+ createExitAnimation,
25
27
  } from "@proyecto-viviana/solidaria";
26
28
  import {
27
29
  type RenderChildren,
@@ -37,6 +39,7 @@ import {
37
39
  OverlayTriggerStateContext,
38
40
  type OverlayTriggerState,
39
41
  } from "./contexts";
42
+ import { VisuallyHidden } from "./VisuallyHidden";
40
43
 
41
44
  /**
42
45
  * Internal context to signal that Modal is wrapped in ModalOverlay.
@@ -45,6 +48,13 @@ import {
45
48
  interface InternalModalContextValue {
46
49
  isDismissable?: boolean;
47
50
  isKeyboardDismissDisabled?: boolean;
51
+ // Upstream's ModalOverlay owns the modal element's ref so it can watch the
52
+ // modal surface's exit animation alongside the overlay's (both must finish
53
+ // before the overlay unmounts). ModalContent registers its element here.
54
+ setModalRef?: (element: HTMLElement | null) => void;
55
+ // Combined exit flag (overlay OR modal still exiting). Both the overlay and
56
+ // the modal surface carry `data-exiting` off this so they fade out together.
57
+ isExiting?: () => boolean;
48
58
  }
49
59
 
50
60
  const InternalModalContext = createContext<InternalModalContextValue | null>(null);
@@ -177,9 +187,34 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
177
187
  toggle,
178
188
  };
179
189
 
190
+ // Enter/exit animation state (mirrors upstream's ModalOverlayWithForwardRef +
191
+ // ModalOverlayInner). The overlay stays mounted here even while closed, so the
192
+ // enter animation is gated on `isOpen` (isReady) — otherwise it would resolve
193
+ // to "done entering" before the element ever mounts. Exit is watched for BOTH
194
+ // the overlay and the modal surface; the modal registers its element via
195
+ // InternalModalContext (setModalRef) so we can await its exit too.
196
+ let overlayRef!: HTMLDivElement;
197
+ // Signal-backed so the enter/exit effects re-run once the element mounts — a
198
+ // plain closure over `overlayRef` would read `null` if the effect fired first
199
+ // and, with no reactive dep on the ref, never recover (stuck `data-entering`).
200
+ const [overlayEl, setOverlayEl] = createSignal<HTMLElement | null>(null);
201
+ const overlayRefAccessor = () => overlayEl();
202
+ const registerOverlayRef = (element: HTMLDivElement) => {
203
+ overlayRef = element;
204
+ setOverlayEl(element);
205
+ };
206
+ const [modalEl, setModalEl] = createSignal<HTMLElement | null>(null);
207
+
208
+ const isOverlayEntering = createEnterAnimation(overlayRefAccessor, isOpen);
209
+ const isOverlayExiting = createExitAnimation(overlayRefAccessor, isOpen);
210
+ const isModalExiting = createExitAnimation(() => modalEl(), isOpen);
211
+ const overlayEntering = () => isOverlayEntering() || (local.isEntering ?? false);
212
+ const combinedExiting = () =>
213
+ isOverlayExiting() || isModalExiting() || (local.isExiting ?? false);
214
+
180
215
  const renderValues = createMemo<ModalRenderProps>(() => ({
181
- isEntering: local.isEntering ?? false,
182
- isExiting: local.isExiting ?? false,
216
+ isEntering: overlayEntering(),
217
+ isExiting: combinedExiting(),
183
218
  }));
184
219
 
185
220
  // Resolve render props - don't pass children, we'll render props.children directly
@@ -200,10 +235,11 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
200
235
  const internalModalContext: InternalModalContextValue = {
201
236
  isDismissable: local.isDismissable,
202
237
  isKeyboardDismissDisabled: local.isKeyboardDismissDisabled,
238
+ setModalRef: setModalEl,
239
+ isExiting: combinedExiting,
203
240
  };
204
241
  const portalContext = useUNSAFE_PortalContext();
205
242
  const portalContainer = () => portalContext.getContainer?.() ?? undefined;
206
- let overlayRef!: HTMLDivElement;
207
243
 
208
244
  const isTopMostModalInOverlay = () => {
209
245
  pruneDisconnectedModals();
@@ -228,9 +264,14 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
228
264
  }
229
265
  };
230
266
 
231
- document.addEventListener("keydown", handleKeyDown, true);
267
+ // Bubble phase, mirroring react-aria's `useOverlay` (its `onKeyDown` is an
268
+ // overlay-element prop, handled on bubble). Capture would preempt inner
269
+ // widgets that dismiss on Escape (a combobox/menu inside the dialog must
270
+ // consume Escape first) and would also fire before the event is recorded by
271
+ // capture-phase listeners, inverting the keydown/onOpenChange order.
272
+ document.addEventListener("keydown", handleKeyDown, false);
232
273
  onCleanup(() => {
233
- document.removeEventListener("keydown", handleKeyDown, true);
274
+ document.removeEventListener("keydown", handleKeyDown, false);
234
275
  });
235
276
  });
236
277
 
@@ -246,17 +287,17 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
246
287
  };
247
288
 
248
289
  return (
249
- <Show when={isHydrated() && (isOpen() || local.isExiting)}>
290
+ <Show when={isHydrated() && (isOpen() || combinedExiting())}>
250
291
  <Portal mount={portalContainer()}>
251
292
  <OverlayTriggerStateContext.Provider value={state}>
252
293
  <InternalModalContext.Provider value={internalModalContext}>
253
294
  <div
254
295
  {...domProps()}
255
- ref={overlayRef}
296
+ ref={registerOverlayRef}
256
297
  class={renderProps.class()}
257
298
  style={renderProps.style()}
258
- data-entering={dataAttr(local.isEntering)}
259
- data-exiting={dataAttr(local.isExiting)}
299
+ data-entering={dataAttr(overlayEntering())}
300
+ data-exiting={dataAttr(combinedExiting())}
260
301
  onPointerDown={handleOverlayPointerDown}
261
302
  >
262
303
  {resolveChildren()}
@@ -305,26 +346,17 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
305
346
  // Check for InternalModalContext - if present, we're inside a ModalOverlay
306
347
  const internalContext = useContext(InternalModalContext);
307
348
 
308
- // If wrapped in ModalOverlay, just render the content
349
+ // If wrapped in ModalOverlay, just render the content. ModalContent reads the
350
+ // overlay's InternalModalContext itself (via useContext), so nothing needs
351
+ // threading — in both branches ModalContent renders inside a provider.
309
352
  if (internalContext) {
310
- return (
311
- <ModalContent {...modalProps} internalContext={internalContext}>
312
- {props.children}
313
- </ModalContent>
314
- );
353
+ return <ModalContent {...modalProps}>{props.children}</ModalContent>;
315
354
  }
316
355
 
317
- // For standalone usage, wrap in ModalOverlay
318
- const standaloneContext: InternalModalContextValue = {
319
- isDismissable: overlayProps.isDismissable,
320
- isKeyboardDismissDisabled: overlayProps.isKeyboardDismissDisabled,
321
- };
322
-
356
+ // For standalone usage, wrap in ModalOverlay.
323
357
  return (
324
358
  <ModalOverlay {...overlayProps}>
325
- <ModalContent {...modalProps} internalContext={standaloneContext}>
326
- {props.children}
327
- </ModalContent>
359
+ <ModalContent {...modalProps}>{props.children}</ModalContent>
328
360
  </ModalOverlay>
329
361
  );
330
362
  }
@@ -333,9 +365,7 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
333
365
  * Internal component that renders the actual modal content.
334
366
  * Used by both standalone Modal and Modal wrapped in ModalOverlay.
335
367
  */
336
- function ModalContent(
337
- props: ModalProps & { internalContext: InternalModalContextValue },
338
- ): JSX.Element {
368
+ function ModalContent(props: ModalProps): JSX.Element {
339
369
  if (isServer) {
340
370
  return <>{props.children}</>;
341
371
  }
@@ -351,19 +381,27 @@ function ModalContent(
351
381
  "isKeyboardDismissDisabled",
352
382
  "isEntering",
353
383
  "isExiting",
354
- "internalContext",
355
384
  ]);
356
385
 
357
386
  let modalRef!: HTMLDivElement;
358
387
  const modalRefAccessor = () => modalRef ?? null;
388
+ // Signal-backed element for the enter animation, so the effect re-runs when
389
+ // the surface mounts (see the overlay's note); the plain `modalRef` var still
390
+ // backs the synchronous consumers (focus stack, interact-outside, aria-hide).
391
+ const [modalEl, setModalEl] = createSignal<HTMLElement | null>(null);
359
392
 
360
393
  // Get state from parent OverlayTriggerStateContext (provided by ModalOverlay)
361
394
  const parentState = useContext(OverlayTriggerStateContext);
362
395
 
396
+ // The overlay (auto or user-provided) always wraps this content, so it owns
397
+ // the InternalModalContext: dismissal settings, the modal-ref registration
398
+ // sink, and the combined exit flag.
399
+ const internalContext = useContext(InternalModalContext);
400
+
363
401
  // Get dismissable settings from internal context (set by ModalOverlay)
364
- const isDismissable = () => local.internalContext?.isDismissable ?? local.isDismissable;
402
+ const isDismissable = () => internalContext?.isDismissable ?? local.isDismissable;
365
403
  const isKeyboardDismissDisabled = () =>
366
- local.internalContext?.isKeyboardDismissDisabled ?? local.isKeyboardDismissDisabled;
404
+ internalContext?.isKeyboardDismissDisabled ?? local.isKeyboardDismissDisabled;
367
405
 
368
406
  // Determine if open from parent state
369
407
  const isOpen = (): boolean => {
@@ -371,6 +409,19 @@ function ModalContent(
371
409
  return parentState?.isOpen ?? false;
372
410
  };
373
411
 
412
+ // Register this element with the overlay so it can await the modal surface's
413
+ // exit animation (upstream threads modalRef down the same way). The overlay's
414
+ // combined exit flag drives this surface's `data-exiting`. The enter animation
415
+ // is local — the modal fades/slides in on its own timeline (delay 160 vs the
416
+ // overlay's 0).
417
+ const registerModalRef = (element: HTMLDivElement) => {
418
+ modalRef = element;
419
+ setModalEl(element);
420
+ internalContext?.setModalRef?.(element);
421
+ };
422
+ const isModalEntering = createEnterAnimation(() => modalEl(), isOpen);
423
+ const isModalExiting = () => internalContext?.isExiting?.() ?? local.isExiting ?? false;
424
+
374
425
  // Keep this modal in a global stack so nested modals dismiss in top-down order.
375
426
  createEffect(() => {
376
427
  if (!isOpen()) return;
@@ -441,9 +492,11 @@ function ModalContent(
441
492
  }
442
493
  };
443
494
 
444
- document.addEventListener("keydown", handleKeyDown, true);
495
+ // Bubble phase — see the ModalOverlay handler above for why (react-aria
496
+ // `useOverlay` parity; inner-widget Escape precedence; event-order fidelity).
497
+ document.addEventListener("keydown", handleKeyDown, false);
445
498
  onCleanup(() => {
446
- document.removeEventListener("keydown", handleKeyDown, true);
499
+ document.removeEventListener("keydown", handleKeyDown, false);
447
500
  });
448
501
  });
449
502
 
@@ -457,7 +510,7 @@ function ModalContent(
457
510
 
458
511
  const hideOutside = () => {
459
512
  if (cancelled || !modalRef?.isConnected) return;
460
- cleanup = ariaHideOutside([modalRef]);
513
+ cleanup = ariaHideOutside([modalRef], { shouldUseInert: true });
461
514
  };
462
515
 
463
516
  if (modalRef.isConnected) {
@@ -473,8 +526,8 @@ function ModalContent(
473
526
  });
474
527
 
475
528
  const renderValues = createMemo<ModalRenderProps>(() => ({
476
- isEntering: local.isEntering ?? false,
477
- isExiting: local.isExiting ?? false,
529
+ isEntering: isModalEntering(),
530
+ isExiting: isModalExiting(),
478
531
  }));
479
532
 
480
533
  const renderProps = useRenderProps(
@@ -499,33 +552,44 @@ function ModalContent(
499
552
  );
500
553
 
501
554
  return (
502
- <FocusScope contain restoreFocus autoFocus>
555
+ // No autoFocus: react-aria's Overlay renders FocusScope with restoreFocus +
556
+ // contain only — initial focus is useDialog's job (it focuses the dialog
557
+ // element itself when nothing inside holds focus).
558
+ //
559
+ // `contain` is gated on `!isExiting`, mirroring react-aria's Overlay
560
+ // (react-aria/src/overlays/Overlay.tsx: `contain={... && !isExiting}`). The
561
+ // overlay stays mounted through its exit transition (isOpen || isExiting), so
562
+ // without this gate containment would remain active during the exit and yank
563
+ // focus back into the dialog as restoreFocus moves it to the trigger —
564
+ // producing a focus bounce (focusout→focusin→focusout) that React never
565
+ // shows. Releasing containment the instant the exit begins lets focus settle
566
+ // on the trigger in a single move, matching upstream's event sequence.
567
+ <FocusScope contain={!isModalExiting()} restoreFocus>
503
568
  <div
504
569
  {...domProps()}
505
- ref={modalRef}
570
+ ref={registerModalRef}
506
571
  class={renderProps.class()}
507
572
  style={renderProps.style()}
508
- data-entering={dataAttr(local.isEntering)}
509
- data-exiting={dataAttr(local.isExiting)}
573
+ data-entering={dataAttr(isModalEntering())}
574
+ data-exiting={dataAttr(isModalExiting())}
510
575
  >
511
576
  <Show when={isDismissable()}>
512
- <button
513
- type="button"
514
- aria-label="Dismiss"
515
- tabIndex={-1}
516
- onClick={close}
517
- style={{
518
- position: "absolute",
519
- width: "1px",
520
- height: "1px",
521
- padding: 0,
522
- margin: "-1px",
523
- overflow: "hidden",
524
- clip: "rect(0, 0, 0, 0)",
525
- "white-space": "nowrap",
526
- border: 0,
527
- }}
528
- />
577
+ {/* Faithful to react-aria's DismissButton: a bare button carrying
578
+ only `width/height: 1px` inside a VisuallyHidden `div` wrapper —
579
+ NOT the hidden styles inlined onto the button. The wrapper clips
580
+ it out of sight while the button keeps its intrinsic UA border-box,
581
+ which is exactly what upstream renders (and what D8 target-size
582
+ measures against the pair oracle). Inlining the reset onto the
583
+ button instead collapsed it to a 1x1 box, diverging from
584
+ upstream's ~16x6 sentinel. */}
585
+ <VisuallyHidden elementType="div">
586
+ <button
587
+ aria-label="Dismiss"
588
+ tabIndex={-1}
589
+ onClick={close}
590
+ style={{ width: "1px", height: "1px" }}
591
+ />
592
+ </VisuallyHidden>
529
593
  </Show>
530
594
  {renderProps.renderChildren()}
531
595
  </div>
@@ -5,7 +5,14 @@
5
5
  * Port of react-aria-components/src/NumberField.tsx
6
6
  */
7
7
 
8
- import { type JSX, createContext, createMemo, splitProps, useContext } from "solid-js";
8
+ import {
9
+ type JSX,
10
+ type Context,
11
+ createContext,
12
+ createMemo,
13
+ splitProps,
14
+ useContext,
15
+ } from "solid-js";
9
16
  import {
10
17
  createNumberField,
11
18
  createButton,
@@ -22,7 +29,9 @@ import {
22
29
  type SlotProps,
23
30
  useRenderProps,
24
31
  filterDOMProps,
32
+ Provider,
25
33
  } from "./utils";
34
+ import { TextContext } from "./Text";
26
35
 
27
36
  export interface NumberFieldRenderProps {
28
37
  /** Whether the number field is disabled. */
@@ -294,7 +303,9 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
294
303
 
295
304
  const renderProps = useRenderProps(
296
305
  {
297
- children: props.children,
306
+ get children() {
307
+ return props.children;
308
+ },
298
309
  class: local.class,
299
310
  style: local.style,
300
311
  defaultClassName: "solidaria-NumberField",
@@ -366,6 +377,21 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
366
377
  },
367
378
  setInputRef,
368
379
  };
380
+ // Provide the description / errorMessage props as `TextContext` slots (mirrors
381
+ // react-aria-components' NumberField), so a `<Text slot="description">` /
382
+ // `<Text slot="errorMessage">` child picks up the `id` its `aria-describedby`
383
+ // references. Additive: existing consumers reading these off
384
+ // `NumberFieldContext` are unaffected.
385
+ const textSlots = {
386
+ slots: {
387
+ get description() {
388
+ return numberFieldAria.descriptionProps;
389
+ },
390
+ get errorMessage() {
391
+ return numberFieldAria.errorMessageProps;
392
+ },
393
+ },
394
+ };
369
395
 
370
396
  return (
371
397
  <NumberFieldStateContext.Provider value={state}>
@@ -379,7 +405,9 @@ export function NumberField(props: NumberFieldProps): JSX.Element {
379
405
  data-required={ariaProps.isRequired || undefined}
380
406
  data-readonly={ariaProps.isReadOnly || undefined}
381
407
  >
382
- {fieldChildren()}
408
+ <Provider values={[[TextContext, textSlots]] as Array<[Context<unknown>, unknown]>}>
409
+ {fieldChildren()}
410
+ </Provider>
383
411
  </div>
384
412
  </NumberFieldContext.Provider>
385
413
  </NumberFieldStateContext.Provider>
@@ -399,14 +427,25 @@ export function NumberFieldLabel(props: {
399
427
  throw new Error("NumberFieldLabel must be used within a NumberField");
400
428
  }
401
429
 
430
+ // Upstream RAC/S2 renders the NumberField label as a native `<label>` (the field's
431
+ // `labelElementType` is the default `'label'`), so `labelProps` carries `for=inputId`.
432
+ // This was a `<span>` — a self-inflicted divergence dropping the native for/label
433
+ // semantics; reverted to `<label>` to match the shipped React DOM byte-for-byte.
434
+ // (Mirror SearchFieldLabel: `labelProps` is typed for a generic element, so strip the
435
+ // `ref` and spread the rest onto the `<label>` intrinsic.)
436
+ const cleanLabelProps = () => {
437
+ const { ref: _ref, ...rest } = context.labelProps as Record<string, unknown>;
438
+ return rest;
439
+ };
440
+
402
441
  return (
403
- <span
404
- {...context.labelProps}
442
+ <label
443
+ {...cleanLabelProps()}
405
444
  class={props.class ?? "solidaria-NumberField-label"}
406
445
  style={props.style}
407
446
  >
408
447
  {props.children}
409
- </span>
448
+ </label>
410
449
  );
411
450
  }
412
451
 
@@ -558,7 +597,9 @@ export function NumberFieldIncrementButton(props: NumberFieldIncrementButtonProp
558
597
 
559
598
  const renderProps = useRenderProps(
560
599
  {
561
- children: props.children,
600
+ get children() {
601
+ return props.children;
602
+ },
562
603
  class: local.class,
563
604
  style: local.style,
564
605
  defaultClassName: "solidaria-NumberField-increment",
@@ -637,7 +678,9 @@ export function NumberFieldDecrementButton(props: NumberFieldDecrementButtonProp
637
678
 
638
679
  const renderProps = useRenderProps(
639
680
  {
640
- children: props.children,
681
+ get children() {
682
+ return props.children;
683
+ },
641
684
  class: local.class,
642
685
  style: local.style,
643
686
  defaultClassName: "solidaria-NumberField-decrement",
package/src/Popover.tsx CHANGED
@@ -22,8 +22,10 @@ import {
22
22
  createOverlayTrigger,
23
23
  createPopover,
24
24
  FocusScope,
25
+ useLocale,
25
26
  useUNSAFE_PortalContext,
26
27
  visuallyHiddenStyles,
28
+ type AriaLabelingProps,
27
29
  type Placement,
28
30
  type PlacementAxis,
29
31
  } from "@proyecto-viviana/solidaria";
@@ -59,7 +61,7 @@ export interface PopoverRenderProps {
59
61
  isExiting: boolean;
60
62
  }
61
63
 
62
- export interface PopoverProps extends SlotProps {
64
+ export interface PopoverProps extends SlotProps, AriaLabelingProps {
63
65
  /** The children of the component - can be JSX or render function. */
64
66
  children?: RenderChildren<PopoverRenderProps>;
65
67
  /** The CSS className for the element. */
@@ -111,6 +113,14 @@ export interface PopoverProps extends SlotProps {
111
113
  * A boundary element for placement calculations.
112
114
  */
113
115
  boundaryElement?: Element;
116
+ /**
117
+ * Overrides the target element's bounding rectangle. Useful for positioning relative to
118
+ * a specific point such as the mouse cursor (e.g. context menus) or text selection.
119
+ *
120
+ * @default target.getBoundingClientRect()
121
+ * @param target - The target element.
122
+ */
123
+ getTargetRect?: (target: Element) => DOMRect | null | undefined;
114
124
  /**
115
125
  * A ref for the popover arrow element.
116
126
  */
@@ -257,6 +267,7 @@ export function Popover(props: PopoverProps): JSX.Element {
257
267
  "shouldFlip",
258
268
  "maxHeight",
259
269
  "boundaryElement",
270
+ "getTargetRect",
260
271
  "arrowRef",
261
272
  "scrollRef",
262
273
  "isNonModal",
@@ -270,12 +281,29 @@ export function Popover(props: PopoverProps): JSX.Element {
270
281
  "isExiting",
271
282
  ]);
272
283
 
273
- let popoverRef!: HTMLDivElement;
284
+ // A reactive ref (not a plain `let`) so the overlay-position effect in
285
+ // createOverlayPosition — which tracks `overlayRef()` as a dependency —
286
+ // re-runs once the portal node actually mounts. React gets this timing for
287
+ // free from useLayoutEffect (the ref is populated before the position effect
288
+ // fires); in Solid the portal node is created lazily on open, AFTER the
289
+ // position effect first ran with a null ref, so a non-reactive ref left the
290
+ // popover stranded at the createOverlayPosition fallback (position:fixed;
291
+ // top:0; left:0) whenever no other dependency happened to re-fire the effect
292
+ // after mount. Mirrors the sibling groupRef signal below.
293
+ const [popoverRef, setPopoverRef] = createSignal<HTMLDivElement | null>(null);
274
294
  const [groupRef, setGroupRef] = createSignal<HTMLDivElement | null>(null);
275
295
  // False on the server and during hydration; true after onMount. Gates the Portal
276
296
  // so overlay content only ever renders client-side, post-hydration.
277
297
  const isHydrated = useIsHydrated();
278
298
 
299
+ // Mirrors upstream S2 Popover (Popover.mjs: `el.lang = locale; el.dir =
300
+ // direction`): the overlay portals out of the app root, so it must carry both
301
+ // the locale `lang` AND writing `direction` — otherwise the portaled
302
+ // listbox/dialog stays LTR and keeps the Latin font under an RTL Provider (the
303
+ // `:lang(ar)` font swap needs a `lang` ancestor the portal would otherwise
304
+ // escape). RAC's own Popover only threads `dir`; S2 adds `lang` on top.
305
+ const locale = useLocale();
306
+
279
307
  const triggerContext = useContext(PopoverTriggerContext);
280
308
  const dialogTriggerContext = useContext(DialogTriggerContext);
281
309
  const popoverGroupContext = useContext(PopoverGroupContext);
@@ -323,7 +351,7 @@ export function Popover(props: PopoverProps): JSX.Element {
323
351
  const popoverAria = createPopover(
324
352
  {
325
353
  triggerRef: getTriggerRef,
326
- popoverRef: () => popoverRef ?? null,
354
+ popoverRef: () => popoverRef(),
327
355
  groupRef: () => (isSubPopover() ? (popoverGroupContext?.() ?? null) : groupRef()),
328
356
  get placement() {
329
357
  return local.placement;
@@ -346,6 +374,9 @@ export function Popover(props: PopoverProps): JSX.Element {
346
374
  get boundaryElement() {
347
375
  return local.boundaryElement;
348
376
  },
377
+ get getTargetRect() {
378
+ return local.getTargetRect;
379
+ },
349
380
  get arrowRef() {
350
381
  return local.arrowRef;
351
382
  },
@@ -501,7 +532,7 @@ export function Popover(props: PopoverProps): JSX.Element {
501
532
  createEffect(() => {
502
533
  if (!isOpen() || !shouldBeDialog()) return;
503
534
  if ((local.autoFocus ?? true) === false) return;
504
- if (!popoverRef) return;
535
+ if (!popoverRef()) return;
505
536
  if (resolvedTrigger() === "SubmenuTrigger") return;
506
537
 
507
538
  let timeout: number | undefined;
@@ -509,11 +540,12 @@ export function Popover(props: PopoverProps): JSX.Element {
509
540
 
510
541
  const focusIfNeeded = () => {
511
542
  if (!isOpen() || !shouldBeDialog()) return;
512
- if (!popoverRef || resolvedTrigger() === "SubmenuTrigger") return;
513
- if (document.activeElement === popoverRef || popoverRef.contains(document.activeElement)) {
543
+ const node = popoverRef();
544
+ if (!node || resolvedTrigger() === "SubmenuTrigger") return;
545
+ if (document.activeElement === node || node.contains(document.activeElement)) {
514
546
  return;
515
547
  }
516
- popoverRef.focus();
548
+ node.focus();
517
549
  };
518
550
 
519
551
  const scheduleFocus = () => {
@@ -559,12 +591,14 @@ export function Popover(props: PopoverProps): JSX.Element {
559
591
  <div
560
592
  {...domProps()}
561
593
  {...cleanPopoverProps()}
562
- ref={popoverRef}
594
+ ref={setPopoverRef}
563
595
  id={overlayId()}
564
596
  role={shouldBeDialog() ? "dialog" : undefined}
565
597
  tabIndex={shouldBeDialog() ? -1 : undefined}
566
598
  class={renderProps.class()}
567
599
  style={mergedStyle()}
600
+ lang={locale().locale}
601
+ dir={locale().direction}
568
602
  data-trigger={resolvedTrigger()}
569
603
  data-placement={popoverAria.placement()}
570
604
  data-entering={dataAttr(local.isEntering)}
@@ -627,10 +661,33 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
627
661
  const popoverContext = useContext(PopoverContext);
628
662
  const placement = () => popoverContext?.placement() ?? null;
629
663
 
630
- const mergedStyle = () => {
664
+ // Mirror react-aria-components' OverlayArrow: the wrapper positions itself
665
+ // absolutely against the popover edge (`[placement]: '100%'`) and takes the
666
+ // cross-axis offset (`left`/`top`) from the overlay's computed `arrowProps`.
667
+ // No `aria-hidden`/`role="presentation"` — upstream leaves the arrow in the
668
+ // accessibility tree (the arrow SVG surfaces as an unlabeled `img`), matching
669
+ // S2's `<OverlayArrow className="">`. The styled layer therefore passes no
670
+ // positioning class of its own.
671
+ const mergedStyle = (): JSX.CSSProperties => {
672
+ const currentPlacement = placement();
673
+ // Mirror react-aria-components' OverlayArrow: the reported `arrowProps`
674
+ // offset (`left`/`top`) points at the arrow's CENTER, so the wrapper must be
675
+ // pulled back by half its size to center on that point — horizontally for
676
+ // top/bottom placements, vertically for left/right. Omitting this shifts the
677
+ // arrow off by half its width/height (a self-inflicted divergence).
678
+ const style: JSX.CSSProperties = {
679
+ position: "absolute",
680
+ transform:
681
+ currentPlacement === "top" || currentPlacement === "bottom"
682
+ ? "translateX(-50%)"
683
+ : "translateY(-50%)",
684
+ };
685
+ if (currentPlacement != null) {
686
+ (style as Record<string, string>)[currentPlacement] = "100%";
687
+ }
688
+
631
689
  const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)
632
690
  ?.style as (JSX.CSSProperties & Record<string, unknown>) | undefined;
633
- const style: JSX.CSSProperties = {};
634
691
  if (typeof contextStyle?.left === "string") {
635
692
  style.left = contextStyle.left;
636
693
  }
@@ -651,13 +708,7 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
651
708
  };
652
709
 
653
710
  return (
654
- <div
655
- class={props.class}
656
- style={mergedStyle()}
657
- data-placement={placement()}
658
- aria-hidden="true"
659
- role="presentation"
660
- >
711
+ <div class={props.class} style={mergedStyle()} data-placement={placement()}>
661
712
  {props.render ? props.render() : props.children}
662
713
  </div>
663
714
  );
@@ -133,7 +133,9 @@ export function ProgressBar(props: ProgressBarProps): JSX.Element {
133
133
 
134
134
  const renderProps = useRenderProps(
135
135
  {
136
- children: props.children,
136
+ get children() {
137
+ return props.children;
138
+ },
137
139
  class: local.class,
138
140
  style: local.style,
139
141
  defaultClassName: "solidaria-ProgressBar",