@proyecto-viviana/solidaria-components 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/dist/ActionBar.js +184 -0
  2. package/dist/ActionBar.js.map +1 -0
  3. package/dist/ActionBar.jsx +128 -0
  4. package/dist/ActionBar.jsx.map +1 -0
  5. package/dist/ActionGroup.js +179 -0
  6. package/dist/ActionGroup.js.map +1 -0
  7. package/dist/ActionGroup.jsx +129 -0
  8. package/dist/ActionGroup.jsx.map +1 -0
  9. package/dist/Alert.js +111 -0
  10. package/dist/Alert.js.map +1 -0
  11. package/dist/Alert.jsx +82 -0
  12. package/dist/Alert.jsx.map +1 -0
  13. package/dist/Autocomplete.js +130 -0
  14. package/dist/Autocomplete.js.map +1 -0
  15. package/dist/Autocomplete.jsx +116 -0
  16. package/dist/Autocomplete.jsx.map +1 -0
  17. package/dist/Breadcrumbs.d.ts.map +1 -1
  18. package/dist/Breadcrumbs.js +334 -0
  19. package/dist/Breadcrumbs.js.map +1 -0
  20. package/dist/Breadcrumbs.jsx +266 -0
  21. package/dist/Breadcrumbs.jsx.map +1 -0
  22. package/dist/Button.d.ts.map +1 -1
  23. package/dist/Button.js +348 -0
  24. package/dist/Button.js.map +1 -0
  25. package/dist/Button.jsx +314 -0
  26. package/dist/Button.jsx.map +1 -0
  27. package/dist/Calendar.d.ts +4 -4
  28. package/dist/Calendar.d.ts.map +1 -1
  29. package/dist/Calendar.js +538 -0
  30. package/dist/Calendar.js.map +1 -0
  31. package/dist/Calendar.jsx +333 -0
  32. package/dist/Calendar.jsx.map +1 -0
  33. package/dist/CalendarPicker.d.ts +33 -0
  34. package/dist/CalendarPicker.d.ts.map +1 -0
  35. package/dist/CalendarPicker.js +44 -0
  36. package/dist/CalendarPicker.js.map +1 -0
  37. package/dist/CalendarPicker.jsx +44 -0
  38. package/dist/CalendarPicker.jsx.map +1 -0
  39. package/dist/Checkbox.d.ts +83 -4
  40. package/dist/Checkbox.d.ts.map +1 -1
  41. package/dist/Checkbox.js +923 -0
  42. package/dist/Checkbox.js.map +1 -0
  43. package/dist/Checkbox.jsx +707 -0
  44. package/dist/Checkbox.jsx.map +1 -0
  45. package/dist/Collection.d.ts.map +1 -1
  46. package/dist/Collection.js +202 -0
  47. package/dist/Collection.js.map +1 -0
  48. package/dist/Collection.jsx +152 -0
  49. package/dist/Collection.jsx.map +1 -0
  50. package/dist/Color.d.ts.map +1 -1
  51. package/dist/Color.js +1720 -0
  52. package/dist/Color.js.map +1 -0
  53. package/dist/Color.jsx +1344 -0
  54. package/dist/Color.jsx.map +1 -0
  55. package/dist/ColorEditor.js +208 -0
  56. package/dist/ColorEditor.js.map +1 -0
  57. package/dist/ColorEditor.jsx +120 -0
  58. package/dist/ColorEditor.jsx.map +1 -0
  59. package/dist/ComboBox.d.ts +4 -4
  60. package/dist/ComboBox.d.ts.map +1 -1
  61. package/dist/ComboBox.js +992 -0
  62. package/dist/ComboBox.js.map +1 -0
  63. package/dist/ComboBox.jsx +714 -0
  64. package/dist/ComboBox.jsx.map +1 -0
  65. package/dist/ContextualHelpTrigger.js +146 -0
  66. package/dist/ContextualHelpTrigger.js.map +1 -0
  67. package/dist/ContextualHelpTrigger.jsx +109 -0
  68. package/dist/ContextualHelpTrigger.jsx.map +1 -0
  69. package/dist/DateField.d.ts +3 -3
  70. package/dist/DateField.d.ts.map +1 -1
  71. package/dist/DateField.js +4 -0
  72. package/dist/DateField.jsx +4 -0
  73. package/dist/DateField2.js +499 -0
  74. package/dist/DateField2.js.map +1 -0
  75. package/dist/DateField2.jsx +317 -0
  76. package/dist/DateField2.jsx.map +1 -0
  77. package/dist/DatePicker.d.ts +4 -4
  78. package/dist/DatePicker.d.ts.map +1 -1
  79. package/dist/DatePicker.js +991 -0
  80. package/dist/DatePicker.js.map +1 -0
  81. package/dist/DatePicker.jsx +682 -0
  82. package/dist/DatePicker.jsx.map +1 -0
  83. package/dist/Dialog.d.ts.map +1 -1
  84. package/dist/Dialog.js +337 -0
  85. package/dist/Dialog.js.map +1 -0
  86. package/dist/Dialog.jsx +192 -0
  87. package/dist/Dialog.jsx.map +1 -0
  88. package/dist/Disclosure.d.ts.map +1 -1
  89. package/dist/Disclosure.js +328 -0
  90. package/dist/Disclosure.js.map +1 -0
  91. package/dist/Disclosure.jsx +230 -0
  92. package/dist/Disclosure.jsx.map +1 -0
  93. package/dist/DragAndDrop.d.ts.map +1 -1
  94. package/dist/DragAndDrop.js +176 -0
  95. package/dist/DragAndDrop.js.map +1 -0
  96. package/dist/DragAndDrop.jsx +160 -0
  97. package/dist/DragAndDrop.jsx.map +1 -0
  98. package/dist/DropZone.d.ts.map +1 -1
  99. package/dist/DropZone.js +189 -0
  100. package/dist/DropZone.js.map +1 -0
  101. package/dist/DropZone.jsx +144 -0
  102. package/dist/DropZone.jsx.map +1 -0
  103. package/dist/FieldError.js +66 -0
  104. package/dist/FieldError.js.map +1 -0
  105. package/dist/FieldError.jsx +47 -0
  106. package/dist/FieldError.jsx.map +1 -0
  107. package/dist/FileTrigger.js +79 -0
  108. package/dist/FileTrigger.js.map +1 -0
  109. package/dist/FileTrigger.jsx +49 -0
  110. package/dist/FileTrigger.jsx.map +1 -0
  111. package/dist/Focusable.js +70 -0
  112. package/dist/Focusable.js.map +1 -0
  113. package/dist/Focusable.jsx +69 -0
  114. package/dist/Focusable.jsx.map +1 -0
  115. package/dist/Form.js +99 -0
  116. package/dist/Form.js.map +1 -0
  117. package/dist/Form.jsx +73 -0
  118. package/dist/Form.jsx.map +1 -0
  119. package/dist/GridList.d.ts +34 -2
  120. package/dist/GridList.d.ts.map +1 -1
  121. package/dist/GridList.js +723 -0
  122. package/dist/GridList.js.map +1 -0
  123. package/dist/GridList.jsx +552 -0
  124. package/dist/GridList.jsx.map +1 -0
  125. package/dist/HiddenTimeInput.js +104 -0
  126. package/dist/HiddenTimeInput.js.map +1 -0
  127. package/dist/HiddenTimeInput.jsx +69 -0
  128. package/dist/HiddenTimeInput.jsx.map +1 -0
  129. package/dist/Icon.d.ts.map +1 -1
  130. package/dist/Icon.js +127 -0
  131. package/dist/Icon.js.map +1 -0
  132. package/dist/Icon.jsx +72 -0
  133. package/dist/Icon.jsx.map +1 -0
  134. package/dist/Keyboard.js +30 -0
  135. package/dist/Keyboard.js.map +1 -0
  136. package/dist/Keyboard.jsx +24 -0
  137. package/dist/Keyboard.jsx.map +1 -0
  138. package/dist/Landmark.js +134 -0
  139. package/dist/Landmark.js.map +1 -0
  140. package/dist/Landmark.jsx +118 -0
  141. package/dist/Landmark.jsx.map +1 -0
  142. package/dist/Link.d.ts.map +1 -1
  143. package/dist/Link.js +219 -0
  144. package/dist/Link.js.map +1 -0
  145. package/dist/Link.jsx +189 -0
  146. package/dist/Link.jsx.map +1 -0
  147. package/dist/ListBox.d.ts.map +1 -1
  148. package/dist/ListBox.js +670 -0
  149. package/dist/ListBox.js.map +1 -0
  150. package/dist/ListBox.jsx +508 -0
  151. package/dist/ListBox.jsx.map +1 -0
  152. package/dist/Menu.d.ts +27 -9
  153. package/dist/Menu.d.ts.map +1 -1
  154. package/dist/Menu.js +1254 -0
  155. package/dist/Menu.js.map +1 -0
  156. package/dist/Menu.jsx +1042 -0
  157. package/dist/Menu.jsx.map +1 -0
  158. package/dist/Meter.d.ts.map +1 -1
  159. package/dist/Meter.js +123 -0
  160. package/dist/Meter.js.map +1 -0
  161. package/dist/Meter.jsx +107 -0
  162. package/dist/Meter.jsx.map +1 -0
  163. package/dist/Modal.d.ts.map +1 -1
  164. package/dist/Modal.js +380 -0
  165. package/dist/Modal.js.map +1 -0
  166. package/dist/Modal.jsx +314 -0
  167. package/dist/Modal.jsx.map +1 -0
  168. package/dist/NumberField.d.ts +3 -3
  169. package/dist/NumberField.d.ts.map +1 -1
  170. package/dist/NumberField.js +573 -0
  171. package/dist/NumberField.js.map +1 -0
  172. package/dist/NumberField.jsx +443 -0
  173. package/dist/NumberField.jsx.map +1 -0
  174. package/dist/Popover.d.ts +10 -2
  175. package/dist/Popover.d.ts.map +1 -1
  176. package/dist/Popover.js +464 -0
  177. package/dist/Popover.js.map +1 -0
  178. package/dist/Popover.jsx +333 -0
  179. package/dist/Popover.jsx.map +1 -0
  180. package/dist/Pressable.js +69 -0
  181. package/dist/Pressable.js.map +1 -0
  182. package/dist/Pressable.jsx +68 -0
  183. package/dist/Pressable.jsx.map +1 -0
  184. package/dist/ProgressBar.d.ts.map +1 -1
  185. package/dist/ProgressBar.js +130 -0
  186. package/dist/ProgressBar.js.map +1 -0
  187. package/dist/ProgressBar.jsx +114 -0
  188. package/dist/ProgressBar.jsx.map +1 -0
  189. package/dist/RadioGroup.d.ts +82 -4
  190. package/dist/RadioGroup.d.ts.map +1 -1
  191. package/dist/RadioGroup.js +931 -0
  192. package/dist/RadioGroup.js.map +1 -0
  193. package/dist/RadioGroup.jsx +681 -0
  194. package/dist/RadioGroup.jsx.map +1 -0
  195. package/dist/RangeCalendar.d.ts.map +1 -1
  196. package/dist/RangeCalendar.js +410 -0
  197. package/dist/RangeCalendar.js.map +1 -0
  198. package/dist/RangeCalendar.jsx +253 -0
  199. package/dist/RangeCalendar.jsx.map +1 -0
  200. package/dist/RouterProvider.js +118 -0
  201. package/dist/RouterProvider.js.map +1 -0
  202. package/dist/RouterProvider.jsx +112 -0
  203. package/dist/RouterProvider.jsx.map +1 -0
  204. package/dist/SearchField.d.ts +2 -2
  205. package/dist/SearchField.d.ts.map +1 -1
  206. package/dist/SearchField.js +643 -0
  207. package/dist/SearchField.js.map +1 -0
  208. package/dist/SearchField.jsx +526 -0
  209. package/dist/SearchField.jsx.map +1 -0
  210. package/dist/Select.d.ts.map +1 -1
  211. package/dist/Select.js +1031 -0
  212. package/dist/Select.js.map +1 -0
  213. package/dist/Select.jsx +744 -0
  214. package/dist/Select.jsx.map +1 -0
  215. package/dist/SelectionIndicator.d.ts.map +1 -1
  216. package/dist/SelectionIndicator.js +86 -0
  217. package/dist/SelectionIndicator.js.map +1 -0
  218. package/dist/SelectionIndicator.jsx +50 -0
  219. package/dist/SelectionIndicator.jsx.map +1 -0
  220. package/dist/Separator.js +97 -0
  221. package/dist/Separator.js.map +1 -0
  222. package/dist/Separator.jsx +85 -0
  223. package/dist/Separator.jsx.map +1 -0
  224. package/dist/SharedElementTransition.d.ts.map +1 -1
  225. package/dist/SharedElementTransition.js +165 -0
  226. package/dist/SharedElementTransition.js.map +1 -0
  227. package/dist/SharedElementTransition.jsx +138 -0
  228. package/dist/SharedElementTransition.jsx.map +1 -0
  229. package/dist/Slider.d.ts +33 -1
  230. package/dist/Slider.d.ts.map +1 -1
  231. package/dist/Slider.js +515 -0
  232. package/dist/Slider.js.map +1 -0
  233. package/dist/Slider.jsx +403 -0
  234. package/dist/Slider.jsx.map +1 -0
  235. package/dist/StepList.js +198 -0
  236. package/dist/StepList.js.map +1 -0
  237. package/dist/StepList.jsx +141 -0
  238. package/dist/StepList.jsx.map +1 -0
  239. package/dist/Switch.d.ts +65 -2
  240. package/dist/Switch.d.ts.map +1 -1
  241. package/dist/Switch.js +534 -0
  242. package/dist/Switch.js.map +1 -0
  243. package/dist/Switch.jsx +393 -0
  244. package/dist/Switch.jsx.map +1 -0
  245. package/dist/Table.d.ts +48 -0
  246. package/dist/Table.d.ts.map +1 -1
  247. package/dist/Table.js +1759 -0
  248. package/dist/Table.js.map +1 -0
  249. package/dist/Table.jsx +1348 -0
  250. package/dist/Table.jsx.map +1 -0
  251. package/dist/Tabs.d.ts +0 -4
  252. package/dist/Tabs.d.ts.map +1 -1
  253. package/dist/Tabs.js +595 -0
  254. package/dist/Tabs.js.map +1 -0
  255. package/dist/Tabs.jsx +367 -0
  256. package/dist/Tabs.jsx.map +1 -0
  257. package/dist/TagGroup.d.ts.map +1 -1
  258. package/dist/TagGroup.js +378 -0
  259. package/dist/TagGroup.js.map +1 -0
  260. package/dist/TagGroup.jsx +270 -0
  261. package/dist/TagGroup.jsx.map +1 -0
  262. package/dist/Text.d.ts +18 -6
  263. package/dist/Text.d.ts.map +1 -1
  264. package/dist/Text.js +42 -0
  265. package/dist/Text.js.map +1 -0
  266. package/dist/Text.jsx +35 -0
  267. package/dist/Text.jsx.map +1 -0
  268. package/dist/TextField.d.ts +6 -6
  269. package/dist/TextField.d.ts.map +1 -1
  270. package/dist/TextField.js +436 -0
  271. package/dist/TextField.js.map +1 -0
  272. package/dist/TextField.jsx +403 -0
  273. package/dist/TextField.jsx.map +1 -0
  274. package/dist/TimeField.d.ts +3 -3
  275. package/dist/TimeField.d.ts.map +1 -1
  276. package/dist/TimeField.js +372 -0
  277. package/dist/TimeField.js.map +1 -0
  278. package/dist/TimeField.jsx +224 -0
  279. package/dist/TimeField.jsx.map +1 -0
  280. package/dist/Toast.d.ts +14 -0
  281. package/dist/Toast.d.ts.map +1 -1
  282. package/dist/Toast.js +551 -0
  283. package/dist/Toast.js.map +1 -0
  284. package/dist/Toast.jsx +361 -0
  285. package/dist/Toast.jsx.map +1 -0
  286. package/dist/ToggleButton.d.ts.map +1 -1
  287. package/dist/ToggleButton.js +123 -0
  288. package/dist/ToggleButton.js.map +1 -0
  289. package/dist/ToggleButton.jsx +88 -0
  290. package/dist/ToggleButton.jsx.map +1 -0
  291. package/dist/ToggleButtonGroup.d.ts.map +1 -1
  292. package/dist/ToggleButtonGroup.js +114 -0
  293. package/dist/ToggleButtonGroup.js.map +1 -0
  294. package/dist/ToggleButtonGroup.jsx +85 -0
  295. package/dist/ToggleButtonGroup.jsx.map +1 -0
  296. package/dist/Toolbar.js +112 -0
  297. package/dist/Toolbar.js.map +1 -0
  298. package/dist/Toolbar.jsx +92 -0
  299. package/dist/Toolbar.jsx.map +1 -0
  300. package/dist/Tooltip.d.ts.map +1 -1
  301. package/dist/Tooltip.js +539 -0
  302. package/dist/Tooltip.js.map +1 -0
  303. package/dist/Tooltip.jsx +465 -0
  304. package/dist/Tooltip.jsx.map +1 -0
  305. package/dist/Tree.d.ts +14 -2
  306. package/dist/Tree.d.ts.map +1 -1
  307. package/dist/Tree.js +1424 -0
  308. package/dist/Tree.js.map +1 -0
  309. package/dist/Tree.jsx +1172 -0
  310. package/dist/Tree.jsx.map +1 -0
  311. package/dist/Virtualizer.d.ts +16 -2
  312. package/dist/Virtualizer.d.ts.map +1 -1
  313. package/dist/Virtualizer.js +2 -0
  314. package/dist/Virtualizer.jsx +2 -0
  315. package/dist/Virtualizer2.js +751 -0
  316. package/dist/Virtualizer2.js.map +1 -0
  317. package/dist/Virtualizer2.jsx +730 -0
  318. package/dist/Virtualizer2.jsx.map +1 -0
  319. package/dist/VirtualizerLayouts.d.ts +18 -0
  320. package/dist/VirtualizerLayouts.d.ts.map +1 -1
  321. package/dist/VisuallyHidden.js +42 -0
  322. package/dist/VisuallyHidden.js.map +1 -0
  323. package/dist/VisuallyHidden.jsx +35 -0
  324. package/dist/VisuallyHidden.jsx.map +1 -0
  325. package/dist/contexts.js +33 -0
  326. package/dist/contexts.js.map +1 -0
  327. package/dist/contexts.jsx +33 -0
  328. package/dist/contexts.jsx.map +1 -0
  329. package/dist/index.d.ts +7 -6
  330. package/dist/index.d.ts.map +1 -1
  331. package/dist/index.js +70 -23932
  332. package/dist/index.jsx +70 -18337
  333. package/dist/useDragAndDrop.js +2 -0
  334. package/dist/useDragAndDrop.jsx +2 -0
  335. package/dist/useDragAndDrop2.js +395 -0
  336. package/dist/useDragAndDrop2.js.map +1 -0
  337. package/dist/useDragAndDrop2.jsx +395 -0
  338. package/dist/useDragAndDrop2.jsx.map +1 -0
  339. package/dist/utils.d.ts +83 -11
  340. package/dist/utils.d.ts.map +1 -1
  341. package/dist/utils.js +285 -0
  342. package/dist/utils.js.map +1 -0
  343. package/dist/utils.jsx +277 -0
  344. package/dist/utils.jsx.map +1 -0
  345. package/dist/virtualizer/Layout.js +144 -0
  346. package/dist/virtualizer/Layout.js.map +1 -0
  347. package/dist/virtualizer/Layout.jsx +144 -0
  348. package/dist/virtualizer/Layout.jsx.map +1 -0
  349. package/package.json +401 -4
  350. package/src/Breadcrumbs.tsx +3 -1
  351. package/src/Button.tsx +22 -2
  352. package/src/Calendar.tsx +27 -10
  353. package/src/CalendarPicker.tsx +73 -0
  354. package/src/Checkbox.tsx +539 -3
  355. package/src/Collection.tsx +9 -3
  356. package/src/Color.tsx +42 -14
  357. package/src/ComboBox.tsx +50 -6
  358. package/src/DateField.tsx +20 -2
  359. package/src/DatePicker.tsx +57 -5
  360. package/src/Dialog.tsx +13 -5
  361. package/src/Disclosure.tsx +3 -1
  362. package/src/DragAndDrop.tsx +3 -1
  363. package/src/DropZone.tsx +3 -1
  364. package/src/GridList.tsx +125 -24
  365. package/src/Icon.tsx +3 -1
  366. package/src/Link.tsx +3 -1
  367. package/src/ListBox.tsx +31 -4
  368. package/src/Menu.tsx +252 -128
  369. package/src/Meter.tsx +3 -1
  370. package/src/Modal.tsx +100 -52
  371. package/src/NumberField.tsx +51 -8
  372. package/src/Popover.tsx +40 -10
  373. package/src/ProgressBar.tsx +3 -1
  374. package/src/RadioGroup.tsx +468 -4
  375. package/src/RangeCalendar.tsx +3 -1
  376. package/src/SearchField.tsx +27 -3
  377. package/src/Select.tsx +22 -7
  378. package/src/SelectionIndicator.tsx +3 -1
  379. package/src/SharedElementTransition.tsx +3 -1
  380. package/src/Slider.tsx +159 -13
  381. package/src/Switch.tsx +395 -2
  382. package/src/Table.tsx +409 -95
  383. package/src/Tabs.tsx +16 -45
  384. package/src/TagGroup.tsx +3 -1
  385. package/src/Text.tsx +31 -10
  386. package/src/TextField.tsx +43 -5
  387. package/src/TimeField.tsx +20 -2
  388. package/src/Toast.tsx +79 -14
  389. package/src/ToggleButton.tsx +3 -1
  390. package/src/ToggleButtonGroup.tsx +3 -1
  391. package/src/Tooltip.tsx +3 -1
  392. package/src/Tree.tsx +77 -9
  393. package/src/Virtualizer.tsx +180 -31
  394. package/src/VirtualizerLayouts.ts +45 -10
  395. package/src/index.ts +50 -0
  396. package/src/utils.tsx +243 -27
  397. package/dist/index.js.map +0 -1
  398. package/dist/index.jsx.map +0 -1
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();
@@ -246,17 +282,17 @@ export function ModalOverlay(props: ModalOverlayProps): JSX.Element {
246
282
  };
247
283
 
248
284
  return (
249
- <Show when={isHydrated() && (isOpen() || local.isExiting)}>
285
+ <Show when={isHydrated() && (isOpen() || combinedExiting())}>
250
286
  <Portal mount={portalContainer()}>
251
287
  <OverlayTriggerStateContext.Provider value={state}>
252
288
  <InternalModalContext.Provider value={internalModalContext}>
253
289
  <div
254
290
  {...domProps()}
255
- ref={overlayRef}
291
+ ref={registerOverlayRef}
256
292
  class={renderProps.class()}
257
293
  style={renderProps.style()}
258
- data-entering={dataAttr(local.isEntering)}
259
- data-exiting={dataAttr(local.isExiting)}
294
+ data-entering={dataAttr(overlayEntering())}
295
+ data-exiting={dataAttr(combinedExiting())}
260
296
  onPointerDown={handleOverlayPointerDown}
261
297
  >
262
298
  {resolveChildren()}
@@ -305,26 +341,17 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
305
341
  // Check for InternalModalContext - if present, we're inside a ModalOverlay
306
342
  const internalContext = useContext(InternalModalContext);
307
343
 
308
- // If wrapped in ModalOverlay, just render the content
344
+ // If wrapped in ModalOverlay, just render the content. ModalContent reads the
345
+ // overlay's InternalModalContext itself (via useContext), so nothing needs
346
+ // threading — in both branches ModalContent renders inside a provider.
309
347
  if (internalContext) {
310
- return (
311
- <ModalContent {...modalProps} internalContext={internalContext}>
312
- {props.children}
313
- </ModalContent>
314
- );
348
+ return <ModalContent {...modalProps}>{props.children}</ModalContent>;
315
349
  }
316
350
 
317
- // For standalone usage, wrap in ModalOverlay
318
- const standaloneContext: InternalModalContextValue = {
319
- isDismissable: overlayProps.isDismissable,
320
- isKeyboardDismissDisabled: overlayProps.isKeyboardDismissDisabled,
321
- };
322
-
351
+ // For standalone usage, wrap in ModalOverlay.
323
352
  return (
324
353
  <ModalOverlay {...overlayProps}>
325
- <ModalContent {...modalProps} internalContext={standaloneContext}>
326
- {props.children}
327
- </ModalContent>
354
+ <ModalContent {...modalProps}>{props.children}</ModalContent>
328
355
  </ModalOverlay>
329
356
  );
330
357
  }
@@ -333,9 +360,7 @@ function ModalContentWithAutoOverlay(props: ModalProps): JSX.Element {
333
360
  * Internal component that renders the actual modal content.
334
361
  * Used by both standalone Modal and Modal wrapped in ModalOverlay.
335
362
  */
336
- function ModalContent(
337
- props: ModalProps & { internalContext: InternalModalContextValue },
338
- ): JSX.Element {
363
+ function ModalContent(props: ModalProps): JSX.Element {
339
364
  if (isServer) {
340
365
  return <>{props.children}</>;
341
366
  }
@@ -351,19 +376,27 @@ function ModalContent(
351
376
  "isKeyboardDismissDisabled",
352
377
  "isEntering",
353
378
  "isExiting",
354
- "internalContext",
355
379
  ]);
356
380
 
357
381
  let modalRef!: HTMLDivElement;
358
382
  const modalRefAccessor = () => modalRef ?? null;
383
+ // Signal-backed element for the enter animation, so the effect re-runs when
384
+ // the surface mounts (see the overlay's note); the plain `modalRef` var still
385
+ // backs the synchronous consumers (focus stack, interact-outside, aria-hide).
386
+ const [modalEl, setModalEl] = createSignal<HTMLElement | null>(null);
359
387
 
360
388
  // Get state from parent OverlayTriggerStateContext (provided by ModalOverlay)
361
389
  const parentState = useContext(OverlayTriggerStateContext);
362
390
 
391
+ // The overlay (auto or user-provided) always wraps this content, so it owns
392
+ // the InternalModalContext: dismissal settings, the modal-ref registration
393
+ // sink, and the combined exit flag.
394
+ const internalContext = useContext(InternalModalContext);
395
+
363
396
  // Get dismissable settings from internal context (set by ModalOverlay)
364
- const isDismissable = () => local.internalContext?.isDismissable ?? local.isDismissable;
397
+ const isDismissable = () => internalContext?.isDismissable ?? local.isDismissable;
365
398
  const isKeyboardDismissDisabled = () =>
366
- local.internalContext?.isKeyboardDismissDisabled ?? local.isKeyboardDismissDisabled;
399
+ internalContext?.isKeyboardDismissDisabled ?? local.isKeyboardDismissDisabled;
367
400
 
368
401
  // Determine if open from parent state
369
402
  const isOpen = (): boolean => {
@@ -371,6 +404,19 @@ function ModalContent(
371
404
  return parentState?.isOpen ?? false;
372
405
  };
373
406
 
407
+ // Register this element with the overlay so it can await the modal surface's
408
+ // exit animation (upstream threads modalRef down the same way). The overlay's
409
+ // combined exit flag drives this surface's `data-exiting`. The enter animation
410
+ // is local — the modal fades/slides in on its own timeline (delay 160 vs the
411
+ // overlay's 0).
412
+ const registerModalRef = (element: HTMLDivElement) => {
413
+ modalRef = element;
414
+ setModalEl(element);
415
+ internalContext?.setModalRef?.(element);
416
+ };
417
+ const isModalEntering = createEnterAnimation(() => modalEl(), isOpen);
418
+ const isModalExiting = () => internalContext?.isExiting?.() ?? local.isExiting ?? false;
419
+
374
420
  // Keep this modal in a global stack so nested modals dismiss in top-down order.
375
421
  createEffect(() => {
376
422
  if (!isOpen()) return;
@@ -457,7 +503,7 @@ function ModalContent(
457
503
 
458
504
  const hideOutside = () => {
459
505
  if (cancelled || !modalRef?.isConnected) return;
460
- cleanup = ariaHideOutside([modalRef]);
506
+ cleanup = ariaHideOutside([modalRef], { shouldUseInert: true });
461
507
  };
462
508
 
463
509
  if (modalRef.isConnected) {
@@ -473,8 +519,8 @@ function ModalContent(
473
519
  });
474
520
 
475
521
  const renderValues = createMemo<ModalRenderProps>(() => ({
476
- isEntering: local.isEntering ?? false,
477
- isExiting: local.isExiting ?? false,
522
+ isEntering: isModalEntering(),
523
+ isExiting: isModalExiting(),
478
524
  }));
479
525
 
480
526
  const renderProps = useRenderProps(
@@ -499,33 +545,35 @@ function ModalContent(
499
545
  );
500
546
 
501
547
  return (
502
- <FocusScope contain restoreFocus autoFocus>
548
+ // No autoFocus: react-aria's Overlay renders FocusScope with restoreFocus +
549
+ // contain only — initial focus is useDialog's job (it focuses the dialog
550
+ // element itself when nothing inside holds focus).
551
+ <FocusScope contain restoreFocus>
503
552
  <div
504
553
  {...domProps()}
505
- ref={modalRef}
554
+ ref={registerModalRef}
506
555
  class={renderProps.class()}
507
556
  style={renderProps.style()}
508
- data-entering={dataAttr(local.isEntering)}
509
- data-exiting={dataAttr(local.isExiting)}
557
+ data-entering={dataAttr(isModalEntering())}
558
+ data-exiting={dataAttr(isModalExiting())}
510
559
  >
511
560
  <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
- />
561
+ {/* Faithful to react-aria's DismissButton: a bare button carrying
562
+ only `width/height: 1px` inside a VisuallyHidden `div` wrapper —
563
+ NOT the hidden styles inlined onto the button. The wrapper clips
564
+ it out of sight while the button keeps its intrinsic UA border-box,
565
+ which is exactly what upstream renders (and what D8 target-size
566
+ measures against the pair oracle). Inlining the reset onto the
567
+ button instead collapsed it to a 1x1 box, diverging from
568
+ upstream's ~16x6 sentinel. */}
569
+ <VisuallyHidden elementType="div">
570
+ <button
571
+ aria-label="Dismiss"
572
+ tabIndex={-1}
573
+ onClick={close}
574
+ style={{ width: "1px", height: "1px" }}
575
+ />
576
+ </VisuallyHidden>
529
577
  </Show>
530
578
  {renderProps.renderChildren()}
531
579
  </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
@@ -24,6 +24,7 @@ import {
24
24
  FocusScope,
25
25
  useUNSAFE_PortalContext,
26
26
  visuallyHiddenStyles,
27
+ type AriaLabelingProps,
27
28
  type Placement,
28
29
  type PlacementAxis,
29
30
  } from "@proyecto-viviana/solidaria";
@@ -59,7 +60,7 @@ export interface PopoverRenderProps {
59
60
  isExiting: boolean;
60
61
  }
61
62
 
62
- export interface PopoverProps extends SlotProps {
63
+ export interface PopoverProps extends SlotProps, AriaLabelingProps {
63
64
  /** The children of the component - can be JSX or render function. */
64
65
  children?: RenderChildren<PopoverRenderProps>;
65
66
  /** The CSS className for the element. */
@@ -111,6 +112,14 @@ export interface PopoverProps extends SlotProps {
111
112
  * A boundary element for placement calculations.
112
113
  */
113
114
  boundaryElement?: Element;
115
+ /**
116
+ * Overrides the target element's bounding rectangle. Useful for positioning relative to
117
+ * a specific point such as the mouse cursor (e.g. context menus) or text selection.
118
+ *
119
+ * @default target.getBoundingClientRect()
120
+ * @param target - The target element.
121
+ */
122
+ getTargetRect?: (target: Element) => DOMRect | null | undefined;
114
123
  /**
115
124
  * A ref for the popover arrow element.
116
125
  */
@@ -257,6 +266,7 @@ export function Popover(props: PopoverProps): JSX.Element {
257
266
  "shouldFlip",
258
267
  "maxHeight",
259
268
  "boundaryElement",
269
+ "getTargetRect",
260
270
  "arrowRef",
261
271
  "scrollRef",
262
272
  "isNonModal",
@@ -346,6 +356,9 @@ export function Popover(props: PopoverProps): JSX.Element {
346
356
  get boundaryElement() {
347
357
  return local.boundaryElement;
348
358
  },
359
+ get getTargetRect() {
360
+ return local.getTargetRect;
361
+ },
349
362
  get arrowRef() {
350
363
  return local.arrowRef;
351
364
  },
@@ -627,10 +640,33 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
627
640
  const popoverContext = useContext(PopoverContext);
628
641
  const placement = () => popoverContext?.placement() ?? null;
629
642
 
630
- const mergedStyle = () => {
643
+ // Mirror react-aria-components' OverlayArrow: the wrapper positions itself
644
+ // absolutely against the popover edge (`[placement]: '100%'`) and takes the
645
+ // cross-axis offset (`left`/`top`) from the overlay's computed `arrowProps`.
646
+ // No `aria-hidden`/`role="presentation"` — upstream leaves the arrow in the
647
+ // accessibility tree (the arrow SVG surfaces as an unlabeled `img`), matching
648
+ // S2's `<OverlayArrow className="">`. The styled layer therefore passes no
649
+ // positioning class of its own.
650
+ const mergedStyle = (): JSX.CSSProperties => {
651
+ const currentPlacement = placement();
652
+ // Mirror react-aria-components' OverlayArrow: the reported `arrowProps`
653
+ // offset (`left`/`top`) points at the arrow's CENTER, so the wrapper must be
654
+ // pulled back by half its size to center on that point — horizontally for
655
+ // top/bottom placements, vertically for left/right. Omitting this shifts the
656
+ // arrow off by half its width/height (a self-inflicted divergence).
657
+ const style: JSX.CSSProperties = {
658
+ position: "absolute",
659
+ transform:
660
+ currentPlacement === "top" || currentPlacement === "bottom"
661
+ ? "translateX(-50%)"
662
+ : "translateY(-50%)",
663
+ };
664
+ if (currentPlacement != null) {
665
+ (style as Record<string, string>)[currentPlacement] = "100%";
666
+ }
667
+
631
668
  const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)
632
669
  ?.style as (JSX.CSSProperties & Record<string, unknown>) | undefined;
633
- const style: JSX.CSSProperties = {};
634
670
  if (typeof contextStyle?.left === "string") {
635
671
  style.left = contextStyle.left;
636
672
  }
@@ -651,13 +687,7 @@ export function OverlayArrow(props: OverlayArrowProps): JSX.Element {
651
687
  };
652
688
 
653
689
  return (
654
- <div
655
- class={props.class}
656
- style={mergedStyle()}
657
- data-placement={placement()}
658
- aria-hidden="true"
659
- role="presentation"
660
- >
690
+ <div class={props.class} style={mergedStyle()} data-placement={placement()}>
661
691
  {props.render ? props.render() : props.children}
662
692
  </div>
663
693
  );
@@ -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",