@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
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {
9
9
  type JSX,
10
+ type Context,
10
11
  createContext,
11
12
  createEffect,
12
13
  createMemo,
@@ -19,13 +20,19 @@ import {
19
20
  import { Portal } from "solid-js/web";
20
21
  import {
21
22
  createDatePicker,
23
+ createDateField,
22
24
  createDateRangePicker,
25
+ createEnterAnimation,
26
+ createFocusRing,
27
+ createHover,
23
28
  createPopover,
29
+ mergeProps,
24
30
  FocusScope,
25
31
  useUNSAFE_PortalContext,
26
32
  type AriaDatePickerProps,
27
33
  type AriaDateRangePickerProps,
28
34
  type DatePickerState as AriaDatePickerState,
35
+ type PlacementAxis,
29
36
  } from "@proyecto-viviana/solidaria";
30
37
  import {
31
38
  createDateFieldState,
@@ -53,7 +60,9 @@ import {
53
60
  useRenderProps,
54
61
  dataAttr,
55
62
  useIsHydrated,
63
+ Provider,
56
64
  } from "./utils";
65
+ import { TextContext } from "./Text";
57
66
  import { DateFieldContext } from "./DateField";
58
67
  import { CalendarContext } from "./Calendar";
59
68
  import { RangeCalendarContext } from "./RangeCalendar";
@@ -173,6 +182,25 @@ export interface DatePickerButtonRenderProps {
173
182
  isDisabled: boolean;
174
183
  /** Whether the calendar is open. */
175
184
  isOpen: boolean;
185
+ /**
186
+ * Whether the button is currently pressed. Provided by the single
187
+ * DatePicker (fed from `createDatePicker().isButtonPressed()`); the range
188
+ * variant does not yet publish press state, so this is optional.
189
+ */
190
+ isPressed?: boolean;
191
+ /**
192
+ * Whether the button is hovered. Fed from the trigger's own `createHover`;
193
+ * mirrors RAC `Button`'s `isHovered` renderProp so the styled S2
194
+ * `baseColor("gray-100")` hover-step background compiles into the className.
195
+ */
196
+ isHovered?: boolean;
197
+ /**
198
+ * Whether the button is keyboard-focused (focus-visible). Fed from
199
+ * `createFocusRing`; mirrors RAC `Button`'s `isFocusVisible` so the styled
200
+ * S2 `focusRing()` outline (a renderProps-gated class, not a CSS
201
+ * `[data-focus-visible]` selector) compiles into the className.
202
+ */
203
+ isFocusVisible?: boolean;
176
204
  }
177
205
 
178
206
  export interface DatePickerButtonProps extends SlotProps {
@@ -184,6 +212,12 @@ export interface DatePickerButtonProps extends SlotProps {
184
212
  style?: StyleOrFunction<DatePickerButtonRenderProps>;
185
213
  /** Whether the button is disabled. */
186
214
  isDisabled?: boolean;
215
+ /**
216
+ * Ref callback for the underlying button element. Mirrors S2's CalendarButton,
217
+ * whose `buttonRef` feeds `pressScale(buttonRef)`; the styled layer forwards a
218
+ * setter here so it can size the press transform against the real element.
219
+ */
220
+ ref?: (element: HTMLButtonElement) => void;
187
221
  }
188
222
 
189
223
  export interface DateRangePickerButtonProps extends DatePickerButtonProps {}
@@ -451,6 +485,23 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
451
485
  isDateDisabled: stateProps.isDateDisabled,
452
486
  });
453
487
 
488
+ // RAC's useDatePicker re-mounts a FRESH useCalendarState every popover open
489
+ // and passes autoFocus:true, so useCalendarState seeds isFocused=true and the
490
+ // focused cell auto-focuses (useCalendarState.mjs line 80:
491
+ // `useState(props.autoFocus || false)`). The port SHARES one persistent
492
+ // calendarState across opens, so isFocused would stay whatever it last was
493
+ // (false after the first close). Mirror the fresh-mount behavior by flagging
494
+ // the shared state focused on each false->true open transition; the
495
+ // CalendarCell focus effect then pulls DOM focus to the value/today cell.
496
+ let wasOpen = false;
497
+ createEffect(() => {
498
+ const open = datePickerState.isOpen();
499
+ if (open && !wasOpen) {
500
+ calendarState.setFocused(true);
501
+ }
502
+ wasOpen = open;
503
+ });
504
+
454
505
  // Create date picker ARIA props
455
506
  const pickerAria = createDatePicker(
456
507
  () => ({
@@ -461,6 +512,18 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
461
512
  fieldState as unknown as DateFieldState<DateValue>,
462
513
  overlayState as AriaDatePickerState,
463
514
  calendarState as unknown as CalendarState<DateValue>,
515
+ () => fieldRef(),
516
+ );
517
+
518
+ // The composed picker's fieldProps (stamped role="presentation") are fed
519
+ // through createDateField — mirroring RAC's DateField consuming
520
+ // useDatePicker().fieldProps. This is what actually names the segments and
521
+ // publishes the value description through the shared hookData WeakMap; without
522
+ // it the segments would be unnamed and carry no selected-date announcement.
523
+ const fieldAria = createDateField(
524
+ () => pickerAria.fieldProps,
525
+ fieldState as unknown as DateFieldState<DateValue>,
526
+ () => fieldRef(),
464
527
  );
465
528
 
466
529
  const contextValue: DatePickerContextValue = {
@@ -515,18 +578,35 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
515
578
  <DateFieldContext.Provider
516
579
  value={{
517
580
  state: fieldState as unknown as DateFieldState<DateValue>,
581
+ // Read through getters so the DateInput/DateSegment consumers see the
582
+ // LIVE memo values (createDescription appends the value-description id
583
+ // via a deferred effect; froze snapshots would miss it). inputProps are
584
+ // the createDateField group props (role="presentation" here), which name
585
+ // the segments — NOT the raw pickerAria.fieldProps.
518
586
  aria: {
519
- labelProps: pickerAria.labelProps,
520
- inputProps: pickerAria.fieldProps,
521
- descriptionProps: pickerAria.descriptionProps,
522
- errorMessageProps: pickerAria.errorMessageProps,
587
+ get labelProps() {
588
+ return pickerAria.labelProps;
589
+ },
590
+ get inputProps() {
591
+ return fieldAria.fieldProps;
592
+ },
593
+ get descriptionProps() {
594
+ return pickerAria.descriptionProps;
595
+ },
596
+ get errorMessageProps() {
597
+ return pickerAria.errorMessageProps;
598
+ },
523
599
  },
524
600
  }}
525
601
  >
526
602
  <CalendarContext.Provider value={calendarState as unknown as CalendarState<DateValue>}>
603
+ {/* BARE ROLELESS root — mirrors RAC `DatePicker`'s outer `<div>`. The
604
+ * presentation FieldGroup shell (rendered as a child via
605
+ * `DatePickerFieldGroup`) is what carries `pickerAria.groupProps`
606
+ * (role="presentation" + label/describedby + arrow-nav/press). A
607
+ * described node here would be a spurious AX entry the S2 oracle lacks. */}
527
608
  <div
528
609
  ref={setFieldRef}
529
- {...pickerAria.groupProps}
530
610
  class={renderProps.class()}
531
611
  style={renderProps.style()}
532
612
  data-disabled={dataAttr(fieldState.isDisabled())}
@@ -535,7 +615,27 @@ function DatePickerInner<T extends DateValue = CalendarDate>(
535
615
  data-invalid={dataAttr(isInvalid())}
536
616
  data-open={dataAttr(overlayState.isOpen)}
537
617
  >
538
- {props.children}
618
+ <Provider
619
+ values={
620
+ [
621
+ [
622
+ TextContext,
623
+ {
624
+ slots: {
625
+ get description() {
626
+ return pickerAria.descriptionProps;
627
+ },
628
+ get errorMessage() {
629
+ return pickerAria.errorMessageProps;
630
+ },
631
+ },
632
+ },
633
+ ],
634
+ ] as Array<[Context<unknown>, unknown]>
635
+ }
636
+ >
637
+ {props.children}
638
+ </Provider>
539
639
  </div>
540
640
  <Show when={(rest as Record<string, unknown>).name}>
541
641
  <HiddenDateInput
@@ -626,6 +726,10 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
626
726
  };
627
727
 
628
728
  let triggerRef: HTMLElement | null = null;
729
+ // The roleless root element — scopes the shared segment focus manager and the
730
+ // outer arrow-navigation across BOTH fields, mirroring the single DatePicker's
731
+ // `fieldRef`.
732
+ const [fieldRef, setFieldRef] = createSignal<HTMLDivElement | null>(null);
629
733
  const overlayState = {
630
734
  get isOpen() {
631
735
  return isOpen();
@@ -660,6 +764,21 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
660
764
  },
661
765
  });
662
766
 
767
+ // Mirror the single DatePicker: RAC re-mounts a FRESH useRangeCalendarState
768
+ // per popover open with autoFocus:true, so isFocused seeds true and the focused
769
+ // cell auto-focuses AND publishes its range-selection prompt describedby
770
+ // ("Click to start selecting date range"). The port shares one persistent
771
+ // range state across opens, so flag it focused on each false->true open
772
+ // transition to reproduce that behavior.
773
+ let wasRangeOpen = false;
774
+ createEffect(() => {
775
+ const open = overlayState.isOpen;
776
+ if (open && !wasRangeOpen) {
777
+ calendarState.setFocused(true);
778
+ }
779
+ wasRangeOpen = open;
780
+ });
781
+
663
782
  const isInvalid = createMemo(
664
783
  () =>
665
784
  Boolean((rest as { isInvalid?: boolean }).isInvalid) ||
@@ -716,7 +835,12 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
716
835
  hideTimeZone: stateProps.hideTimeZone,
717
836
  placeholderValue: stateProps.placeholderValue,
718
837
  validationState: () => (isInvalid() ? "invalid" : access(stateProps.validationState)),
719
- isDateUnavailable: stateProps.isDateUnavailable,
838
+ // The range picker's isDateUnavailable is anchor-aware (date, anchorDate),
839
+ // but a text field has no range anchor, so adapt it to the field's 1-arg form
840
+ // by always passing a null anchor (checks raw per-date availability).
841
+ isDateUnavailable: stateProps.isDateUnavailable
842
+ ? (date: DateValue) => stateProps.isDateUnavailable!(date, null)
843
+ : undefined,
720
844
  } satisfies Partial<DateFieldStateProps<T>>;
721
845
 
722
846
  const startFieldState = createDateFieldState<T>({
@@ -739,14 +863,36 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
739
863
  }),
740
864
  calendarState as unknown as RangeCalendarState<DateValue>,
741
865
  overlayState as AriaDatePickerState,
866
+ () => fieldRef(),
867
+ );
868
+
869
+ // Each range field's presentation field props (stamped role="presentation" +
870
+ // the SHARED focus manager) are fed through createDateField — mirroring RAC's
871
+ // two `<DateInput>`s consuming useDateRangePicker().start/endFieldProps. This
872
+ // names the segments ("month, Start Date" / "month, End Date") and publishes
873
+ // them through the shared hookData WeakMap; the shared focus manager makes arrow
874
+ // keys and auto-advance walk across the start/end boundary.
875
+ const startFieldAria = createDateField(
876
+ () => pickerAria.startFieldProps,
877
+ startFieldState as unknown as DateFieldState<DateValue>,
878
+ () => fieldRef(),
879
+ );
880
+ const endFieldAria = createDateField(
881
+ () => pickerAria.endFieldProps,
882
+ endFieldState as unknown as DateFieldState<DateValue>,
883
+ () => fieldRef(),
742
884
  );
743
885
 
744
886
  const startFieldContext: DateRangePickerFieldContextValue = {
745
887
  state: startFieldState as unknown as DateFieldState<DateValue>,
746
888
  aria: {
747
889
  labelProps: {},
890
+ // The DateInput group carries createDateField's fieldProps (role="presentation"
891
+ // + arrow-nav bubbling + unicode-bidi isolate), mirroring the standalone
892
+ // DateField's `inputProps ← fieldProps` mapping. NO hiddenInputProps — the
893
+ // range owner renders its HiddenDateInput siblings below.
748
894
  get inputProps() {
749
- return pickerAria.startInputProps;
895
+ return startFieldAria.fieldProps;
750
896
  },
751
897
  get descriptionProps() {
752
898
  return pickerAria.descriptionProps;
@@ -762,7 +908,7 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
762
908
  aria: {
763
909
  labelProps: {},
764
910
  get inputProps() {
765
- return pickerAria.endInputProps;
911
+ return endFieldAria.fieldProps;
766
912
  },
767
913
  get descriptionProps() {
768
914
  return pickerAria.descriptionProps;
@@ -813,8 +959,15 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
813
959
  <RangeCalendarContext.Provider
814
960
  value={calendarState as unknown as RangeCalendarState<DateValue>}
815
961
  >
962
+ {/* BARE ROLELESS root — mirrors RAC `DateRangePicker`'s outer `<div>`.
963
+ * The presentation FieldGroup shell (rendered as a child via the styled
964
+ * DateRangeDisplay) is what carries `pickerAria.groupProps` (role=
965
+ * "presentation" + label/describedby + outer arrow-nav/press). A described
966
+ * or role="group" node here would be a spurious AX entry the S2 oracle
967
+ * lacks. The ref scopes the shared segment focus manager across both
968
+ * fields (see createDateRangePicker). */}
816
969
  <div
817
- {...pickerAria.groupProps}
970
+ ref={setFieldRef}
818
971
  class={renderProps.class()}
819
972
  style={renderProps.style()}
820
973
  data-disabled={dataAttr(calendarState.isDisabled())}
@@ -823,7 +976,27 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
823
976
  data-invalid={dataAttr(isInvalid())}
824
977
  data-open={dataAttr(overlayState.isOpen)}
825
978
  >
826
- {props.children}
979
+ <Provider
980
+ values={
981
+ [
982
+ [
983
+ TextContext,
984
+ {
985
+ slots: {
986
+ get description() {
987
+ return pickerAria.descriptionProps;
988
+ },
989
+ get errorMessage() {
990
+ return pickerAria.errorMessageProps;
991
+ },
992
+ },
993
+ },
994
+ ],
995
+ ] as Array<[Context<unknown>, unknown]>
996
+ }
997
+ >
998
+ {props.children}
999
+ </Provider>
827
1000
  </div>
828
1001
  <Show when={(rest as Record<string, unknown>).startName}>
829
1002
  <HiddenDateInput
@@ -859,14 +1032,38 @@ function DateRangePickerInner<T extends DateValue = CalendarDate>(
859
1032
  export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
860
1033
  const context = useDatePickerContext();
861
1034
 
1035
+ // Mirror RAC's `buttonProps.isDisabled = props.isDisabled || props.isReadOnly`
1036
+ // (a read-only picker can't open its calendar) — `createDatePicker` computes
1037
+ // this as `isButtonDisabled()`. Reading `fieldState.isDisabled()` alone would
1038
+ // miss the read-only case (read-only ≠ disabled on the field), so the trigger
1039
+ // would paint enabled while the S2 oracle dims it.
1040
+ const isDisabled = () => context.pickerAria.isButtonDisabled() || (props.isDisabled ?? false);
1041
+
1042
+ // Mirror RAC: the trigger is a `<Button>` whose own `useFocusRing`/`useHover`/
1043
+ // `usePress` drive its interaction paint state. The press signal is owned by
1044
+ // `createDatePicker` (`isButtonPressed`); focus-visible and hover are wired
1045
+ // here so the S2 `focusRing()`/`baseColor()` selectors (`data-focus-visible`,
1046
+ // `data-hovered`, `data-pressed`) resolve exactly as they do upstream.
1047
+ const { isFocused, isFocusVisible, focusProps } = createFocusRing();
1048
+ const { isHovered, hoverProps } = createHover({
1049
+ get isDisabled() {
1050
+ return isDisabled();
1051
+ },
1052
+ });
1053
+
862
1054
  const renderValues = createMemo<DatePickerButtonRenderProps>(() => ({
863
- isDisabled: context.fieldState.isDisabled() || (props.isDisabled ?? false),
1055
+ isDisabled: isDisabled(),
864
1056
  isOpen: context.overlayState.isOpen,
1057
+ isPressed: context.pickerAria.isButtonPressed(),
1058
+ isHovered: isHovered(),
1059
+ isFocusVisible: isFocusVisible(),
865
1060
  }));
866
1061
 
867
1062
  const renderProps = useRenderProps(
868
1063
  {
869
- children: props.children,
1064
+ get children() {
1065
+ return props.children;
1066
+ },
870
1067
  class: props.class,
871
1068
  style: props.style,
872
1069
  defaultClassName: "solidaria-DatePickerButton",
@@ -882,17 +1079,30 @@ export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
882
1079
  return props.children ?? "📅";
883
1080
  };
884
1081
 
1082
+ const buttonProps = createMemo(() =>
1083
+ mergeProps(
1084
+ context.pickerAria.buttonProps as Record<string, unknown>,
1085
+ focusProps as Record<string, unknown>,
1086
+ hoverProps as Record<string, unknown>,
1087
+ ),
1088
+ );
1089
+
885
1090
  return (
886
1091
  <button
887
1092
  ref={(el) => {
888
1093
  context.setTriggerRef(el);
1094
+ props.ref?.(el);
889
1095
  }}
890
- {...context.pickerAria.buttonProps}
1096
+ {...buttonProps()}
891
1097
  class={renderProps.class()}
892
1098
  style={renderProps.style()}
893
- disabled={context.fieldState.isDisabled() || props.isDisabled}
894
- data-disabled={dataAttr(context.fieldState.isDisabled() || props.isDisabled)}
1099
+ disabled={isDisabled()}
1100
+ data-disabled={dataAttr(isDisabled())}
895
1101
  data-open={dataAttr(context.overlayState.isOpen)}
1102
+ attr:data-hovered={isHovered() ? "true" : undefined}
1103
+ attr:data-focused={isFocused() ? "true" : undefined}
1104
+ attr:data-focus-visible={isFocusVisible() ? "true" : undefined}
1105
+ attr:data-pressed={context.pickerAria.isButtonPressed() ? "true" : undefined}
896
1106
  >
897
1107
  {getChildren()}
898
1108
  </button>
@@ -902,14 +1112,37 @@ export function DatePickerButton(props: DatePickerButtonProps): JSX.Element {
902
1112
  export function DateRangePickerButton(props: DateRangePickerButtonProps): JSX.Element {
903
1113
  const context = useDateRangePickerContext();
904
1114
 
1115
+ // Mirror RAC's `buttonProps.isDisabled = props.isDisabled || props.isReadOnly`
1116
+ // (a read-only picker can't open its calendar) — `createDateRangePicker` computes
1117
+ // this as `isButtonDisabled()`. Reading `calendarState.isDisabled()` alone would
1118
+ // miss the read-only case, so the trigger would paint enabled while S2 dims it.
1119
+ const isDisabled = () => context.pickerAria.isButtonDisabled() || (props.isDisabled ?? false);
1120
+
1121
+ // Mirror RAC: the trigger is a `<Button>` whose own `useFocusRing`/`useHover`/
1122
+ // `usePress` drive its interaction paint state. The press signal is owned by
1123
+ // `createDateRangePicker` (`isButtonPressed`); focus-visible and hover are wired
1124
+ // here so the S2 `focusRing()`/`baseColor()` selectors (`data-focus-visible`,
1125
+ // `data-hovered`, `data-pressed`) resolve exactly as they do upstream.
1126
+ const { isFocused, isFocusVisible, focusProps } = createFocusRing();
1127
+ const { isHovered, hoverProps } = createHover({
1128
+ get isDisabled() {
1129
+ return isDisabled();
1130
+ },
1131
+ });
1132
+
905
1133
  const renderValues = createMemo<DatePickerButtonRenderProps>(() => ({
906
- isDisabled: context.calendarState.isDisabled() || (props.isDisabled ?? false),
1134
+ isDisabled: isDisabled(),
907
1135
  isOpen: context.overlayState.isOpen,
1136
+ isPressed: context.pickerAria.isButtonPressed(),
1137
+ isHovered: isHovered(),
1138
+ isFocusVisible: isFocusVisible(),
908
1139
  }));
909
1140
 
910
1141
  const renderProps = useRenderProps(
911
1142
  {
912
- children: props.children,
1143
+ get children() {
1144
+ return props.children;
1145
+ },
913
1146
  class: props.class,
914
1147
  style: props.style,
915
1148
  defaultClassName: "solidaria-DateRangePickerButton",
@@ -924,26 +1157,56 @@ export function DateRangePickerButton(props: DateRangePickerButtonProps): JSX.El
924
1157
  return props.children ?? "📅";
925
1158
  };
926
1159
 
1160
+ const buttonProps = createMemo(() =>
1161
+ mergeProps(
1162
+ context.pickerAria.buttonProps as Record<string, unknown>,
1163
+ focusProps as Record<string, unknown>,
1164
+ hoverProps as Record<string, unknown>,
1165
+ ),
1166
+ );
1167
+
927
1168
  return (
928
1169
  <button
929
- ref={(el) => context.setTriggerRef(el)}
930
- {...context.pickerAria.buttonProps}
1170
+ ref={(el) => {
1171
+ context.setTriggerRef(el);
1172
+ props.ref?.(el);
1173
+ }}
1174
+ {...buttonProps()}
931
1175
  class={renderProps.class()}
932
1176
  style={renderProps.style()}
933
- disabled={context.calendarState.isDisabled() || props.isDisabled}
934
- data-disabled={dataAttr(context.calendarState.isDisabled() || props.isDisabled)}
1177
+ disabled={isDisabled()}
1178
+ data-disabled={dataAttr(isDisabled())}
935
1179
  data-open={dataAttr(context.overlayState.isOpen)}
1180
+ attr:data-hovered={isHovered() ? "true" : undefined}
1181
+ attr:data-focused={isFocused() ? "true" : undefined}
1182
+ attr:data-focus-visible={isFocusVisible() ? "true" : undefined}
1183
+ attr:data-pressed={context.pickerAria.isButtonPressed() ? "true" : undefined}
936
1184
  >
937
1185
  {getChildren()}
938
1186
  </button>
939
1187
  );
940
1188
  }
941
1189
 
1190
+ /**
1191
+ * Render props for the popover surface, mirroring RAC `Popover`'s
1192
+ * enter/exit/placement renderProps. The styled layer keys the S2
1193
+ * opacity/translate enter transition on these (a renderProps-gated class, not a
1194
+ * CSS `[data-entering]` selector).
1195
+ */
1196
+ export interface DatePickerContentRenderProps {
1197
+ /** Whether the popover is playing its enter transition (`data-entering`). */
1198
+ isEntering: boolean;
1199
+ /** Whether the popover is playing its exit transition (`data-exiting`). */
1200
+ isExiting: boolean;
1201
+ /** The resolved placement axis, for the direction-dependent translate. */
1202
+ placement: PlacementAxis | null;
1203
+ }
1204
+
942
1205
  export interface DatePickerContentProps extends SlotProps {
943
1206
  /** The children of the component. */
944
1207
  children?: JSX.Element;
945
- /** The CSS className for the element. */
946
- class?: string;
1208
+ /** The CSS className for the element, or a function of the render props. */
1209
+ class?: string | ((renderProps: DatePickerContentRenderProps) => string);
947
1210
  /** The inline style for the element. */
948
1211
  style?: JSX.CSSProperties;
949
1212
  }
@@ -971,10 +1234,12 @@ export interface DatePickerDescriptionProps {
971
1234
 
972
1235
  export function DatePickerDescription(props: DatePickerDescriptionProps): JSX.Element {
973
1236
  const context = useDatePickerContext();
1237
+ // Rendered as <span> (→ AX role "text"), mirroring S2's <Text slot="description">
1238
+ // and the standalone DateFieldDescription — NOT a <p> (paragraph).
974
1239
  return (
975
- <p {...context.pickerAria.descriptionProps} class={props.class}>
1240
+ <span {...context.pickerAria.descriptionProps} class={props.class}>
976
1241
  {props.children}
977
- </p>
1242
+ </span>
978
1243
  );
979
1244
  }
980
1245
 
@@ -985,10 +1250,12 @@ export interface DatePickerErrorMessageProps {
985
1250
 
986
1251
  export function DatePickerErrorMessage(props: DatePickerErrorMessageProps): JSX.Element {
987
1252
  const context = useDatePickerContext();
1253
+ // Rendered as <span> (→ AX role "text"), mirroring S2's <FieldError> and the
1254
+ // standalone DateFieldErrorMessage — NOT a <p> and NOT role="alert".
988
1255
  return (
989
- <p {...context.pickerAria.errorMessageProps} class={props.class}>
1256
+ <span {...context.pickerAria.errorMessageProps} class={props.class}>
990
1257
  {props.children}
991
- </p>
1258
+ </span>
992
1259
  );
993
1260
  }
994
1261
 
@@ -1013,10 +1280,12 @@ export interface DateRangePickerDescriptionProps {
1013
1280
 
1014
1281
  export function DateRangePickerDescription(props: DateRangePickerDescriptionProps): JSX.Element {
1015
1282
  const context = useDateRangePickerContext();
1283
+ // Rendered as <span> (→ AX role "text"), mirroring S2's <Text slot="description">
1284
+ // and the single DatePickerDescription — NOT a <p> (paragraph).
1016
1285
  return (
1017
- <p {...context.pickerAria.descriptionProps} class={props.class}>
1286
+ <span {...context.pickerAria.descriptionProps} class={props.class}>
1018
1287
  {props.children}
1019
- </p>
1288
+ </span>
1020
1289
  );
1021
1290
  }
1022
1291
 
@@ -1027,10 +1296,12 @@ export interface DateRangePickerErrorMessageProps {
1027
1296
 
1028
1297
  export function DateRangePickerErrorMessage(props: DateRangePickerErrorMessageProps): JSX.Element {
1029
1298
  const context = useDateRangePickerContext();
1299
+ // Rendered as <span> (→ AX role "text"), mirroring S2's <FieldError> and the
1300
+ // single DatePickerErrorMessage — NOT a <p> and NOT role="alert".
1030
1301
  return (
1031
- <p {...context.pickerAria.errorMessageProps} class={props.class}>
1302
+ <span {...context.pickerAria.errorMessageProps} class={props.class}>
1032
1303
  {props.children}
1033
- </p>
1304
+ </span>
1034
1305
  );
1035
1306
  }
1036
1307
 
@@ -1054,13 +1325,16 @@ function createEscapeDismissFallback(isOpen: () => boolean, close: () => void):
1054
1325
  export function DatePickerContent(props: DatePickerContentProps): JSX.Element {
1055
1326
  const context = useDatePickerContext();
1056
1327
  const portalContext = useUNSAFE_PortalContext();
1057
- let contentRef: HTMLDivElement | undefined;
1328
+ // A signal (not a plain `let`) so the enter-animation effect re-runs when the
1329
+ // section mounts on open — `createEnterAnimation` reads this to know the
1330
+ // element exists before removing the initial `data-entering` styles.
1331
+ const [contentRef, setContentRef] = createSignal<HTMLElement>();
1058
1332
  const portalContainer = () => portalContext.getContainer?.() ?? undefined;
1059
1333
 
1060
1334
  const popoverAria = createPopover(
1061
1335
  {
1062
1336
  triggerRef: () => context.triggerRef()?.parentElement ?? context.triggerRef(),
1063
- popoverRef: () => contentRef ?? null,
1337
+ popoverRef: () => contentRef() ?? null,
1064
1338
  placement: "bottom start",
1065
1339
  offset: 8,
1066
1340
  isNonModal: false,
@@ -1076,6 +1350,35 @@ export function DatePickerContent(props: DatePickerContentProps): JSX.Element {
1076
1350
 
1077
1351
  createEscapeDismissFallback(() => context.overlayState.isOpen, context.overlayState.close);
1078
1352
 
1353
+ // Mirror S2's `<Popover>` enter transition (RAC `useEnterAnimation`): the
1354
+ // surface mounts carrying `data-entering` (opacity 0 + a small placement-ward
1355
+ // translate), which an effect removes on the next frame so the CSS transition
1356
+ // plays. The exit half is out of scope for this unit — the popover unmounts on
1357
+ // close (no `isOpen || isExiting` gate), so `isExiting` stays false; only the
1358
+ // enter motion is certified (D2).
1359
+ const isEntering = createEnterAnimation(contentRef, () => context.overlayState.isOpen);
1360
+
1361
+ const renderProps = (): DatePickerContentRenderProps => ({
1362
+ isEntering: isEntering(),
1363
+ isExiting: false,
1364
+ // Seed the base placement so the ENTER frame already carries the
1365
+ // placement-ward `translate` (S2's popover motion is placement-gated:
1366
+ // `translateY: { placement: { bottom: { isEntering: -4 } } }`). RAC resolves
1367
+ // placement in a `useLayoutEffect` BEFORE the first paint, so no painted
1368
+ // frame is ever null-placement; the port's positioning `createEffect` lands
1369
+ // one frame later, so without this seed the entering frame drops `translateY`
1370
+ // and only `opacity` transitions (D2 caught the missing translate). The
1371
+ // desired placement is `bottom start` (see `createPopover` above), so the
1372
+ // base axis is always `bottom` until the measure refines it.
1373
+ placement: popoverAria.placement() ?? "bottom",
1374
+ });
1375
+
1376
+ const resolvedClass = (): string => {
1377
+ const c = props.class;
1378
+ if (typeof c === "function") return c(renderProps());
1379
+ return c ?? "solidaria-DatePickerContent";
1380
+ };
1381
+
1079
1382
  const cleanPopoverProps = () => {
1080
1383
  const {
1081
1384
  style: _style,
@@ -1095,28 +1398,39 @@ export function DatePickerContent(props: DatePickerContentProps): JSX.Element {
1095
1398
  };
1096
1399
  };
1097
1400
 
1098
- // Return focus to trigger when overlay closes
1099
- createEffect(() => {
1100
- const open = context.overlayState.isOpen;
1101
- if (!open) {
1102
- requestAnimationFrame(() => context.triggerRef()?.focus());
1103
- }
1104
- });
1401
+ // Close-focus restoration is delegated to the overlay's `FocusScope`
1402
+ // (`restoreFocus`) — exactly as RAC's DatePicker does, and as certified Select
1403
+ // and Menu do. The prior ad-hoc effect (`if (!open) triggerRef().focus()`)
1404
+ // fired once on mount with `open === false`, stealing focus to the trigger and
1405
+ // painting a phantom focus ring at rest.
1105
1406
 
1106
1407
  return (
1107
1408
  <Show when={context.overlayState.isOpen}>
1108
1409
  <Portal mount={portalContainer()}>
1109
1410
  <FocusScope contain restoreFocus>
1411
+ {/* Un-folded to mirror S2's `<Popover>` DOM. The OUTER role-null `<div>`
1412
+ * is the positioned surface that carries the enter motion + chrome —
1413
+ * this is the element RAC/S2 animate (`AriaPopover`'s div: role null, no
1414
+ * tabindex, accessible name computed from the calendar's textContent).
1415
+ * A nested `role="dialog"` element (RAC's `Dialog`, which S2's
1416
+ * CalendarPopover wraps the Calendar in) carries the dialog semantics.
1417
+ * Folding both onto one `<section role="dialog">` made D2 animate the
1418
+ * dialog node instead of the role-null div; the role-null wrapper is
1419
+ * pruned from the AX tree so D5/D6 are unaffected. */}
1110
1420
  <div
1111
- ref={contentRef}
1421
+ ref={setContentRef}
1112
1422
  {...cleanPopoverProps()}
1113
- {...context.pickerAria.dialogProps}
1114
- tabIndex={-1}
1115
- class={props.class ?? "solidaria-DatePickerContent"}
1423
+ class={resolvedClass()}
1116
1424
  style={mergedStyle()}
1117
- data-placement={popoverAria.placement() ?? undefined}
1425
+ data-placement={popoverAria.placement() ?? "bottom"}
1426
+ data-entering={dataAttr(isEntering())}
1118
1427
  >
1119
- {props.children}
1428
+ {/* RAC's `Dialog` renders a `<section role="dialog">` by default — the
1429
+ * D5 roving trail records this element's tag, so it must be `section`
1430
+ * (a `<div>` here regressed the focus-trail tag match). */}
1431
+ <section {...context.pickerAria.dialogProps} tabIndex={-1}>
1432
+ {props.children}
1433
+ </section>
1120
1434
  </div>
1121
1435
  </FocusScope>
1122
1436
  </Portal>
@@ -1127,13 +1441,16 @@ export function DatePickerContent(props: DatePickerContentProps): JSX.Element {
1127
1441
  export function DateRangePickerContent(props: DateRangePickerContentProps): JSX.Element {
1128
1442
  const context = useDateRangePickerContext();
1129
1443
  const portalContext = useUNSAFE_PortalContext();
1130
- let contentRef: HTMLDivElement | undefined;
1444
+ // A signal (not a plain `let`) so the enter-animation effect re-runs when the
1445
+ // surface mounts on open — `createEnterAnimation` reads this to know the
1446
+ // element exists before removing the initial `data-entering` styles.
1447
+ const [contentRef, setContentRef] = createSignal<HTMLElement>();
1131
1448
  const portalContainer = () => portalContext.getContainer?.() ?? undefined;
1132
1449
 
1133
1450
  const popoverAria = createPopover(
1134
1451
  {
1135
1452
  triggerRef: () => context.triggerRef()?.parentElement ?? context.triggerRef(),
1136
- popoverRef: () => contentRef ?? null,
1453
+ popoverRef: () => contentRef() ?? null,
1137
1454
  placement: "bottom start",
1138
1455
  offset: 8,
1139
1456
  isNonModal: false,
@@ -1149,6 +1466,26 @@ export function DateRangePickerContent(props: DateRangePickerContentProps): JSX.
1149
1466
 
1150
1467
  createEscapeDismissFallback(() => context.overlayState.isOpen, context.overlayState.close);
1151
1468
 
1469
+ // Mirror S2's `<Popover>` enter transition (RAC `useEnterAnimation`): the
1470
+ // surface mounts carrying `data-entering` (opacity 0 + a small placement-ward
1471
+ // translate), which an effect removes on the next frame so the CSS transition
1472
+ // plays. Only the enter half is certified (D2) — the popover unmounts on close.
1473
+ const isEntering = createEnterAnimation(contentRef, () => context.overlayState.isOpen);
1474
+
1475
+ const renderProps = (): DatePickerContentRenderProps => ({
1476
+ isEntering: isEntering(),
1477
+ isExiting: false,
1478
+ // Seed the base placement so the ENTER frame already carries the
1479
+ // placement-ward `translate` (see the single DatePickerContent note).
1480
+ placement: popoverAria.placement() ?? "bottom",
1481
+ });
1482
+
1483
+ const resolvedClass = (): string => {
1484
+ const c = props.class;
1485
+ if (typeof c === "function") return c(renderProps());
1486
+ return c ?? "solidaria-DateRangePickerContent";
1487
+ };
1488
+
1152
1489
  const cleanPopoverProps = () => {
1153
1490
  const {
1154
1491
  style: _style,
@@ -1168,28 +1505,31 @@ export function DateRangePickerContent(props: DateRangePickerContentProps): JSX.
1168
1505
  };
1169
1506
  };
1170
1507
 
1171
- // Return focus to trigger when overlay closes
1172
- createEffect(() => {
1173
- const open = context.overlayState.isOpen;
1174
- if (!open) {
1175
- requestAnimationFrame(() => context.triggerRef()?.focus());
1176
- }
1177
- });
1508
+ // Close-focus restoration is delegated to the overlay's `FocusScope`
1509
+ // (`restoreFocus`) — see the single-value `DatePickerContent` note. The prior
1510
+ // ad-hoc effect fired on mount and painted a phantom focus ring at rest.
1178
1511
 
1179
1512
  return (
1180
1513
  <Show when={context.overlayState.isOpen}>
1181
1514
  <Portal mount={portalContainer()}>
1182
1515
  <FocusScope contain restoreFocus>
1516
+ {/* Un-folded to mirror S2's `<Popover>` DOM (see DatePickerContent).
1517
+ * OUTER role-null `<div>` = positioned surface carrying the enter
1518
+ * motion + chrome (the element RAC/S2 animate; pruned from the AX
1519
+ * tree). Nested `<section role="dialog">` carries the dialog
1520
+ * semantics — the D5 roving trail records this tag, so it must be
1521
+ * `section`, not a folded `div`. */}
1183
1522
  <div
1184
- ref={contentRef}
1523
+ ref={setContentRef}
1185
1524
  {...cleanPopoverProps()}
1186
- {...context.pickerAria.dialogProps}
1187
- tabIndex={-1}
1188
- class={props.class ?? "solidaria-DateRangePickerContent"}
1525
+ class={resolvedClass()}
1189
1526
  style={mergedStyle()}
1190
- data-placement={popoverAria.placement() ?? undefined}
1527
+ data-placement={popoverAria.placement() ?? "bottom"}
1528
+ data-entering={dataAttr(isEntering())}
1191
1529
  >
1192
- {props.children}
1530
+ <section {...context.pickerAria.dialogProps} tabIndex={-1}>
1531
+ {props.children}
1532
+ </section>
1193
1533
  </div>
1194
1534
  </FocusScope>
1195
1535
  </Portal>