@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
@@ -0,0 +1,333 @@
1
+ import { dataAttr, filterDOMProps, useIsHydrated, useRenderProps } from "./utils.jsx";
2
+ import { o as usePopoverTrigger, r as PopoverTriggerContext, t as DialogTriggerContext } from "./contexts.jsx";
3
+ import { Show, createContext, createEffect, createMemo, createSignal, createUniqueId, onCleanup, splitProps, useContext } from "solid-js";
4
+ import { Portal } from "solid-js/web";
5
+ import { FocusScope, createOverlayTrigger, createPopover, useUNSAFE_PortalContext, visuallyHiddenStyles } from "@proyecto-viviana/solidaria";
6
+ import { createOverlayTriggerState } from "@proyecto-viviana/solid-stately";
7
+ //#region src/Popover.tsx
8
+ /**
9
+ * Popover component for solidaria-components
10
+ *
11
+ * A headless popover component that positions relative to a trigger element.
12
+ * Port of react-aria-components Popover.
13
+ */
14
+ const PopoverContext = createContext(null);
15
+ const PopoverGroupContext = createContext(null);
16
+ function PopoverDismissButton(props) {
17
+ return <button type="button" aria-label="Dismiss" tabIndex={-1} onClick={props.onDismiss} style={visuallyHiddenStyles} />;
18
+ }
19
+ /**
20
+ * A PopoverTrigger opens a popover when a trigger element is pressed.
21
+ * Children should include a trigger element (e.g. Button) and the Popover.
22
+ */
23
+ function PopoverTrigger(props) {
24
+ const [local] = splitProps(props, [
25
+ "isOpen",
26
+ "defaultOpen",
27
+ "onOpenChange"
28
+ ]);
29
+ const state = createOverlayTriggerState({
30
+ get isOpen() {
31
+ return local.isOpen;
32
+ },
33
+ get defaultOpen() {
34
+ return local.defaultOpen;
35
+ },
36
+ onOpenChange: local.onOpenChange
37
+ });
38
+ let triggerRef = null;
39
+ const triggerId = createUniqueId();
40
+ const triggerAria = createOverlayTrigger({ type: "dialog" }, state, () => triggerRef);
41
+ const contextValue = createMemo(() => ({
42
+ state: {
43
+ isOpen: () => state.isOpen(),
44
+ open: () => state.open(),
45
+ close: () => state.close(),
46
+ toggle: () => state.toggle()
47
+ },
48
+ triggerRef: () => triggerRef,
49
+ setTriggerRef: (el) => {
50
+ if (!el) return;
51
+ if (!triggerRef || !triggerRef.isConnected) triggerRef = el;
52
+ },
53
+ triggerId,
54
+ triggerProps: triggerAria.triggerProps,
55
+ overlayProps: triggerAria.overlayProps,
56
+ trigger: "PopoverTrigger"
57
+ }));
58
+ return <PopoverTriggerContext.Provider value={contextValue()}>
59
+ {props.children}
60
+ </PopoverTriggerContext.Provider>;
61
+ }
62
+ /**
63
+ * A popover is an overlay element positioned relative to a trigger.
64
+ */
65
+ function Popover(props) {
66
+ const [local, rest] = splitProps(props, [
67
+ "class",
68
+ "style",
69
+ "trigger",
70
+ "triggerRef",
71
+ "placement",
72
+ "containerPadding",
73
+ "offset",
74
+ "crossOffset",
75
+ "shouldFlip",
76
+ "maxHeight",
77
+ "boundaryElement",
78
+ "getTargetRect",
79
+ "arrowRef",
80
+ "scrollRef",
81
+ "isNonModal",
82
+ "isKeyboardDismissDisabled",
83
+ "shouldCloseOnInteractOutside",
84
+ "isOpen",
85
+ "defaultOpen",
86
+ "onOpenChange",
87
+ "autoFocus",
88
+ "isEntering",
89
+ "isExiting"
90
+ ]);
91
+ let popoverRef;
92
+ const [groupRef, setGroupRef] = createSignal(null);
93
+ const isHydrated = useIsHydrated();
94
+ const triggerContext = useContext(PopoverTriggerContext);
95
+ const dialogTriggerContext = useContext(DialogTriggerContext);
96
+ const popoverGroupContext = useContext(PopoverGroupContext);
97
+ const resolvedTrigger = () => local.trigger ?? triggerContext?.trigger ?? (dialogTriggerContext ? "DialogTrigger" : void 0);
98
+ const isSubPopover = () => resolvedTrigger() === "SubmenuTrigger" && popoverGroupContext != null;
99
+ const [internalOpen, setInternalOpen] = createSignal(local.defaultOpen ?? false);
100
+ const isOpen = () => {
101
+ if (local.isOpen !== void 0) return local.isOpen;
102
+ if (triggerContext) return triggerContext.state.isOpen();
103
+ if (dialogTriggerContext) return dialogTriggerContext.state.isOpen();
104
+ return internalOpen();
105
+ };
106
+ const close = () => {
107
+ if (local.isOpen !== void 0) local.onOpenChange?.(false);
108
+ else if (triggerContext) {
109
+ triggerContext.state.close();
110
+ local.onOpenChange?.(false);
111
+ } else if (dialogTriggerContext) {
112
+ dialogTriggerContext.state.close();
113
+ local.onOpenChange?.(false);
114
+ } else {
115
+ setInternalOpen(false);
116
+ local.onOpenChange?.(false);
117
+ }
118
+ };
119
+ const getTriggerRef = () => {
120
+ if (local.triggerRef) return local.triggerRef();
121
+ if (triggerContext) return triggerContext.triggerRef();
122
+ if (dialogTriggerContext) return dialogTriggerContext.triggerRef();
123
+ return null;
124
+ };
125
+ const popoverAria = createPopover({
126
+ triggerRef: getTriggerRef,
127
+ popoverRef: () => null,
128
+ groupRef: () => isSubPopover() ? popoverGroupContext?.() ?? null : groupRef(),
129
+ get placement() {
130
+ return local.placement;
131
+ },
132
+ get containerPadding() {
133
+ return local.containerPadding;
134
+ },
135
+ get offset() {
136
+ return local.offset ?? 8;
137
+ },
138
+ get crossOffset() {
139
+ return local.crossOffset;
140
+ },
141
+ get shouldFlip() {
142
+ return local.shouldFlip;
143
+ },
144
+ get maxHeight() {
145
+ return local.maxHeight;
146
+ },
147
+ get boundaryElement() {
148
+ return local.boundaryElement;
149
+ },
150
+ get getTargetRect() {
151
+ return local.getTargetRect;
152
+ },
153
+ get arrowRef() {
154
+ return local.arrowRef;
155
+ },
156
+ get scrollRef() {
157
+ return local.scrollRef;
158
+ },
159
+ get isNonModal() {
160
+ return local.isNonModal;
161
+ },
162
+ get isKeyboardDismissDisabled() {
163
+ return local.isKeyboardDismissDisabled;
164
+ },
165
+ get shouldCloseOnInteractOutside() {
166
+ return local.shouldCloseOnInteractOutside;
167
+ },
168
+ get trigger() {
169
+ return resolvedTrigger();
170
+ }
171
+ }, {
172
+ isOpen,
173
+ open: () => {
174
+ if (local.isOpen !== void 0) local.onOpenChange?.(true);
175
+ else if (triggerContext) {
176
+ triggerContext.state.open();
177
+ local.onOpenChange?.(true);
178
+ } else if (dialogTriggerContext) {
179
+ dialogTriggerContext.state.open();
180
+ local.onOpenChange?.(true);
181
+ } else {
182
+ setInternalOpen(true);
183
+ local.onOpenChange?.(true);
184
+ }
185
+ },
186
+ close,
187
+ toggle: () => {
188
+ if (isOpen()) close();
189
+ else if (local.isOpen !== void 0) local.onOpenChange?.(true);
190
+ else if (triggerContext) triggerContext.state.toggle();
191
+ else if (dialogTriggerContext) dialogTriggerContext.state.toggle();
192
+ else {
193
+ setInternalOpen(true);
194
+ local.onOpenChange?.(true);
195
+ }
196
+ }
197
+ });
198
+ const renderValues = createMemo(() => ({
199
+ trigger: resolvedTrigger() ?? null,
200
+ placement: popoverAria.placement(),
201
+ isEntering: local.isEntering ?? false,
202
+ isExiting: local.isExiting ?? false
203
+ }));
204
+ const renderProps = useRenderProps({
205
+ get children() {
206
+ return props.children;
207
+ },
208
+ class: local.class,
209
+ style: local.style,
210
+ defaultClassName: "solidaria-Popover"
211
+ }, renderValues);
212
+ const [triggerWidth, setTriggerWidth] = createSignal();
213
+ const hasExplicitTriggerWidth = () => {
214
+ return renderProps.style()?.["--trigger-width"] != null;
215
+ };
216
+ const updateTriggerWidth = () => {
217
+ const trigger = getTriggerRef();
218
+ if (!trigger || hasExplicitTriggerWidth()) return;
219
+ setTriggerWidth(`${trigger.getBoundingClientRect().width}px`);
220
+ };
221
+ createEffect(() => {
222
+ if (!isOpen()) return;
223
+ updateTriggerWidth();
224
+ const trigger = getTriggerRef();
225
+ if (!trigger || hasExplicitTriggerWidth() || typeof ResizeObserver === "undefined") return;
226
+ const observer = new ResizeObserver(updateTriggerWidth);
227
+ observer.observe(trigger);
228
+ onCleanup(() => observer.disconnect());
229
+ });
230
+ const domProps = createMemo(() => filterDOMProps(rest, { global: true }));
231
+ const overlayId = () => {
232
+ return rest.id ?? triggerContext?.overlayProps?.id ?? dialogTriggerContext?.overlayProps?.id;
233
+ };
234
+ const cleanPopoverProps = () => {
235
+ const { style: _style, ref: _ref, ...remaining } = popoverAria.popoverProps;
236
+ return remaining;
237
+ };
238
+ const mergedStyle = () => {
239
+ const ariaStyle = popoverAria.popoverProps.style;
240
+ const renderStyle = renderProps.style() || {};
241
+ return {
242
+ ...ariaStyle,
243
+ ...renderStyle,
244
+ "--trigger-width": renderStyle["--trigger-width"] ?? triggerWidth()
245
+ };
246
+ };
247
+ const shouldBeDialog = () => !local.isNonModal || resolvedTrigger() === "SubmenuTrigger";
248
+ const shouldContainFocus = () => {
249
+ if (!shouldBeDialog()) return false;
250
+ const trigger = resolvedTrigger();
251
+ return trigger !== "MenuTrigger" && trigger !== "SubmenuTrigger";
252
+ };
253
+ const portalContext = useUNSAFE_PortalContext();
254
+ const portalContainer = () => {
255
+ if (isSubPopover()) return popoverGroupContext?.() ?? portalContext.getContainer?.() ?? void 0;
256
+ return portalContext.getContainer?.() ?? void 0;
257
+ };
258
+ createEffect(() => {
259
+ if (!isOpen() || !shouldBeDialog()) return;
260
+ if ((local.autoFocus ?? true) === false) return;
261
+ });
262
+ createEffect(() => {
263
+ if (!isOpen()) return;
264
+ if (local.isKeyboardDismissDisabled) return;
265
+ const onKeyDown = (event) => {
266
+ if (event.key !== "Escape") return;
267
+ if (event.defaultPrevented) return;
268
+ close();
269
+ };
270
+ document.addEventListener("keydown", onKeyDown);
271
+ onCleanup(() => document.removeEventListener("keydown", onKeyDown));
272
+ });
273
+ const overlay = () => <PopoverContext.Provider value={{
274
+ placement: popoverAria.placement,
275
+ arrowProps: () => popoverAria.arrowProps
276
+ }}>
277
+ <FocusScope contain={shouldContainFocus()} restoreFocus>
278
+ <div {...domProps()} {...cleanPopoverProps()} ref={popoverRef} id={overlayId()} role={shouldBeDialog() ? "dialog" : void 0} tabIndex={shouldBeDialog() ? -1 : void 0} class={renderProps.class()} style={mergedStyle()} data-trigger={resolvedTrigger()} data-placement={popoverAria.placement()} data-entering={dataAttr(local.isEntering)} data-exiting={dataAttr(local.isExiting)}>
279
+ <Show when={!local.isNonModal}>
280
+ <PopoverDismissButton onDismiss={close} />
281
+ </Show>
282
+ {renderProps.renderChildren()}
283
+ <PopoverDismissButton onDismiss={close} />
284
+ </div>
285
+ </FocusScope>
286
+ </PopoverContext.Provider>;
287
+ const underlay = () => <div data-testid="underlay" {...popoverAria.underlayProps} style={{
288
+ position: "fixed",
289
+ inset: 0
290
+ }} />;
291
+ return <Show when={isHydrated() && (isOpen() || local.isExiting)}>
292
+ <Portal mount={portalContainer()}>
293
+ <Show when={!local.isNonModal && !isSubPopover() && isOpen()}>{underlay()}</Show>
294
+ <Show when={isSubPopover()} fallback={<div ref={setGroupRef} style={{ display: "contents" }}>
295
+ <PopoverGroupContext.Provider value={() => groupRef()}>
296
+ {overlay()}
297
+ </PopoverGroupContext.Provider>
298
+ </div>}>
299
+ {overlay()}
300
+ </Show>
301
+ </Portal>
302
+ </Show>;
303
+ }
304
+ /**
305
+ * An arrow element that points towards the trigger.
306
+ */
307
+ function OverlayArrow(props) {
308
+ const popoverContext = useContext(PopoverContext);
309
+ const placement = () => popoverContext?.placement() ?? null;
310
+ const mergedStyle = () => {
311
+ const currentPlacement = placement();
312
+ const style = {
313
+ position: "absolute",
314
+ transform: currentPlacement === "top" || currentPlacement === "bottom" ? "translateX(-50%)" : "translateY(-50%)"
315
+ };
316
+ if (currentPlacement != null) style[currentPlacement] = "100%";
317
+ const contextStyle = (popoverContext?.arrowProps())?.style;
318
+ if (typeof contextStyle?.left === "string") style.left = contextStyle.left;
319
+ if (typeof contextStyle?.top === "string") style.top = contextStyle.top;
320
+ const localStyle = props.style && !(typeof CSSStyleDeclaration !== "undefined" && props.style instanceof CSSStyleDeclaration) ? props.style : void 0;
321
+ return {
322
+ ...style,
323
+ ...localStyle
324
+ };
325
+ };
326
+ return <div class={props.class} style={mergedStyle()} data-placement={placement()}>
327
+ {props.render ? props.render() : props.children}
328
+ </div>;
329
+ }
330
+ //#endregion
331
+ export { OverlayArrow, Popover, Popover as default, PopoverContext, PopoverTrigger, PopoverTriggerContext, usePopoverTrigger };
332
+
333
+ //# sourceMappingURL=Popover.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Popover.jsx","names":[],"sources":["../src/Popover.tsx"],"sourcesContent":["/**\n * Popover component for solidaria-components\n *\n * A headless popover component that positions relative to a trigger element.\n * Port of react-aria-components Popover.\n */\n\nimport {\n type JSX,\n createContext,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n onCleanup,\n splitProps,\n useContext,\n Show,\n} from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport {\n createOverlayTrigger,\n createPopover,\n FocusScope,\n useUNSAFE_PortalContext,\n visuallyHiddenStyles,\n type AriaLabelingProps,\n type Placement,\n type PlacementAxis,\n} from \"@proyecto-viviana/solidaria\";\nimport { createOverlayTriggerState } from \"@proyecto-viviana/solid-stately\";\nimport {\n type RenderChildren,\n type ClassNameOrFunction,\n type StyleOrFunction,\n type SlotProps,\n useRenderProps,\n filterDOMProps,\n dataAttr,\n useIsHydrated,\n} from \"./utils\";\nimport { DialogTriggerContext, PopoverTriggerContext } from \"./contexts\";\n\nexport interface PopoverRenderProps {\n /**\n * The name of the component that triggered the popover.\n */\n trigger: string | null;\n /**\n * The placement of the popover relative to the trigger.\n */\n placement: PlacementAxis | null;\n /**\n * Whether the popover is currently entering (for animations).\n */\n isEntering: boolean;\n /**\n * Whether the popover is currently exiting (for animations).\n */\n isExiting: boolean;\n}\n\nexport interface PopoverProps extends SlotProps, AriaLabelingProps {\n /** The children of the component - can be JSX or render function. */\n children?: RenderChildren<PopoverRenderProps>;\n /** The CSS className for the element. */\n class?: ClassNameOrFunction<PopoverRenderProps>;\n /** The inline style for the element. */\n style?: StyleOrFunction<PopoverRenderProps>;\n /**\n * The name of the component that triggered the popover.\n */\n trigger?: string;\n /**\n * The ref for the element which the popover positions itself with respect to.\n * Required when used standalone (not within a trigger component).\n */\n triggerRef?: () => Element | null;\n /**\n * The placement of the element with respect to its anchor element.\n * @default 'bottom'\n */\n placement?: Placement;\n /**\n * The placement padding that should be applied between the element and its\n * surrounding container.\n * @default 12\n */\n containerPadding?: number;\n /**\n * The additional offset applied along the main axis between the element and its\n * anchor element.\n * @default 8\n */\n offset?: number;\n /**\n * The additional offset applied along the cross axis between the element and its\n * anchor element.\n * @default 0\n */\n crossOffset?: number;\n /**\n * Whether the element should flip its orientation when there is insufficient room.\n * @default true\n */\n shouldFlip?: boolean;\n /**\n * The max height of the popover.\n */\n maxHeight?: number;\n /**\n * A boundary element for placement calculations.\n */\n boundaryElement?: Element;\n /**\n * Overrides the target element's bounding rectangle. Useful for positioning relative to\n * a specific point such as the mouse cursor (e.g. context menus) or text selection.\n *\n * @default target.getBoundingClientRect()\n * @param target - The target element.\n */\n getTargetRect?: (target: Element) => DOMRect | null | undefined;\n /**\n * A ref for the popover arrow element.\n */\n arrowRef?: () => Element | null;\n /**\n * A ref for the scrollable popover element.\n */\n scrollRef?: () => Element | null;\n /**\n * Whether the popover is non-modal (allows interaction outside).\n */\n isNonModal?: boolean;\n /**\n * Whether pressing Escape to close should be disabled.\n */\n isKeyboardDismissDisabled?: boolean;\n /**\n * Filter for which outside interactions should close the popover.\n */\n shouldCloseOnInteractOutside?: (element: Element) => boolean;\n /** Whether the popover is open (controlled). */\n isOpen?: boolean;\n /** Whether the popover opens by default (uncontrolled). */\n defaultOpen?: boolean;\n /** Handler called when the popover's open state changes. */\n onOpenChange?: (isOpen: boolean) => void;\n /**\n * Whether focus should move to the popover container on open.\n * @default true\n */\n autoFocus?: boolean;\n /** Whether the popover is entering (for animations). */\n isEntering?: boolean;\n /** Whether the popover is exiting (for animations). */\n isExiting?: boolean;\n}\n\nexport interface PopoverTriggerProps {\n /** The children - should include a trigger and popover content. */\n children: JSX.Element;\n /** Whether the popover is open (controlled). */\n isOpen?: boolean;\n /** Whether the popover is open by default (uncontrolled). */\n defaultOpen?: boolean;\n /** Callback when open state changes. */\n onOpenChange?: (isOpen: boolean) => void;\n}\n\nexport {\n PopoverTriggerContext,\n usePopoverTrigger,\n type PopoverTriggerContextValue,\n} from \"./contexts\";\n\ninterface PopoverContextValue {\n placement: () => PlacementAxis | null;\n arrowProps: () => JSX.HTMLAttributes<HTMLElement>;\n}\n\nexport const PopoverContext = createContext<PopoverContextValue | null>(null);\nconst PopoverGroupContext = createContext<(() => HTMLElement | null) | null>(null);\n\nfunction PopoverDismissButton(props: { onDismiss: () => void }): JSX.Element {\n return (\n <button\n type=\"button\"\n aria-label=\"Dismiss\"\n tabIndex={-1}\n onClick={props.onDismiss}\n style={visuallyHiddenStyles}\n />\n );\n}\n\n/**\n * A PopoverTrigger opens a popover when a trigger element is pressed.\n * Children should include a trigger element (e.g. Button) and the Popover.\n */\nexport function PopoverTrigger(props: PopoverTriggerProps): JSX.Element {\n const [local] = splitProps(props, [\"isOpen\", \"defaultOpen\", \"onOpenChange\"]);\n\n const state = createOverlayTriggerState({\n get isOpen() {\n return local.isOpen;\n },\n get defaultOpen() {\n return local.defaultOpen;\n },\n onOpenChange: local.onOpenChange,\n });\n\n let triggerRef: HTMLElement | null = null;\n const triggerId = createUniqueId();\n\n const triggerAria = createOverlayTrigger({ type: \"dialog\" }, state, () => triggerRef);\n\n const contextValue = createMemo(() => ({\n state: {\n isOpen: () => state.isOpen(),\n open: () => state.open(),\n close: () => state.close(),\n toggle: () => state.toggle(),\n },\n triggerRef: () => triggerRef,\n setTriggerRef: (el: HTMLElement | null) => {\n if (!el) return;\n if (!triggerRef || !triggerRef.isConnected) {\n triggerRef = el;\n }\n },\n triggerId,\n triggerProps: triggerAria.triggerProps,\n overlayProps: triggerAria.overlayProps,\n trigger: \"PopoverTrigger\",\n }));\n\n return (\n <PopoverTriggerContext.Provider value={contextValue()}>\n {props.children}\n </PopoverTriggerContext.Provider>\n );\n}\n\n/**\n * A popover is an overlay element positioned relative to a trigger.\n */\nexport function Popover(props: PopoverProps): JSX.Element {\n // Note: do NOT early-return on the server. Returning `null` on the server and a\n // full <Show>/<Portal> tree on the client desyncs Solid's hydration walk (the\n // server emits no marker for the <Show>), which surfaces as \"Hydration Mismatch /\n // getNextElement\" in the parent (e.g. Picker). Instead, run the same structure on\n // both and gate the Portal on `useIsHydrated()` so the overlay only mounts on the\n // client after hydration — the server + first client render both produce an empty\n // <Show> marker, so hydration aligns.\n const [local, rest] = splitProps(props, [\n \"class\",\n \"style\",\n \"trigger\",\n \"triggerRef\",\n \"placement\",\n \"containerPadding\",\n \"offset\",\n \"crossOffset\",\n \"shouldFlip\",\n \"maxHeight\",\n \"boundaryElement\",\n \"getTargetRect\",\n \"arrowRef\",\n \"scrollRef\",\n \"isNonModal\",\n \"isKeyboardDismissDisabled\",\n \"shouldCloseOnInteractOutside\",\n \"isOpen\",\n \"defaultOpen\",\n \"onOpenChange\",\n \"autoFocus\",\n \"isEntering\",\n \"isExiting\",\n ]);\n\n let popoverRef!: HTMLDivElement;\n const [groupRef, setGroupRef] = createSignal<HTMLDivElement | null>(null);\n // False on the server and during hydration; true after onMount. Gates the Portal\n // so overlay content only ever renders client-side, post-hydration.\n const isHydrated = useIsHydrated();\n\n const triggerContext = useContext(PopoverTriggerContext);\n const dialogTriggerContext = useContext(DialogTriggerContext);\n const popoverGroupContext = useContext(PopoverGroupContext);\n const resolvedTrigger = () =>\n local.trigger ??\n triggerContext?.trigger ??\n (dialogTriggerContext ? \"DialogTrigger\" : undefined);\n const isSubPopover = () => resolvedTrigger() === \"SubmenuTrigger\" && popoverGroupContext != null;\n\n const [internalOpen, setInternalOpen] = createSignal(local.defaultOpen ?? false);\n\n const isOpen = (): boolean => {\n if (local.isOpen !== undefined) return local.isOpen;\n if (triggerContext) {\n return triggerContext.state.isOpen();\n }\n if (dialogTriggerContext) {\n return dialogTriggerContext.state.isOpen();\n }\n return internalOpen();\n };\n\n const close = () => {\n if (local.isOpen !== undefined) {\n local.onOpenChange?.(false);\n } else if (triggerContext) {\n triggerContext.state.close();\n local.onOpenChange?.(false);\n } else if (dialogTriggerContext) {\n dialogTriggerContext.state.close();\n local.onOpenChange?.(false);\n } else {\n setInternalOpen(false);\n local.onOpenChange?.(false);\n }\n };\n\n const getTriggerRef = () => {\n if (local.triggerRef) return local.triggerRef();\n if (triggerContext) return triggerContext.triggerRef();\n if (dialogTriggerContext) return dialogTriggerContext.triggerRef();\n return null;\n };\n\n const popoverAria = createPopover(\n {\n triggerRef: getTriggerRef,\n popoverRef: () => popoverRef ?? null,\n groupRef: () => (isSubPopover() ? (popoverGroupContext?.() ?? null) : groupRef()),\n get placement() {\n return local.placement;\n },\n get containerPadding() {\n return local.containerPadding;\n },\n get offset() {\n return local.offset ?? 8;\n },\n get crossOffset() {\n return local.crossOffset;\n },\n get shouldFlip() {\n return local.shouldFlip;\n },\n get maxHeight() {\n return local.maxHeight;\n },\n get boundaryElement() {\n return local.boundaryElement;\n },\n get getTargetRect() {\n return local.getTargetRect;\n },\n get arrowRef() {\n return local.arrowRef;\n },\n get scrollRef() {\n return local.scrollRef;\n },\n get isNonModal() {\n return local.isNonModal;\n },\n get isKeyboardDismissDisabled() {\n return local.isKeyboardDismissDisabled;\n },\n get shouldCloseOnInteractOutside() {\n return local.shouldCloseOnInteractOutside;\n },\n get trigger() {\n return resolvedTrigger();\n },\n },\n {\n isOpen,\n open: () => {\n if (local.isOpen !== undefined) {\n local.onOpenChange?.(true);\n } else if (triggerContext) {\n triggerContext.state.open();\n local.onOpenChange?.(true);\n } else if (dialogTriggerContext) {\n dialogTriggerContext.state.open();\n local.onOpenChange?.(true);\n } else {\n setInternalOpen(true);\n local.onOpenChange?.(true);\n }\n },\n close,\n toggle: () => {\n if (isOpen()) close();\n else if (local.isOpen !== undefined) {\n local.onOpenChange?.(true);\n } else if (triggerContext) {\n triggerContext.state.toggle();\n } else if (dialogTriggerContext) {\n dialogTriggerContext.state.toggle();\n } else {\n setInternalOpen(true);\n local.onOpenChange?.(true);\n }\n },\n },\n );\n\n const renderValues = createMemo<PopoverRenderProps>(() => ({\n trigger: resolvedTrigger() ?? null,\n placement: popoverAria.placement(),\n isEntering: local.isEntering ?? false,\n isExiting: local.isExiting ?? false,\n }));\n\n const renderProps = useRenderProps(\n {\n // Read children lazily. The popover content is gated behind\n // `<Show when={isHydrated() && …}>` below, so it must NOT be instantiated\n // during the component body. An eager `children: props.children` reads the\n // child getter at object-construction time, building the content template\n // (and walking `getNextElement`) before the gate — which the server, with\n // the gate closed, never emitted → hydration mismatch. The getter defers\n // the read until `renderChildren()` runs inside the gated overlay.\n get children() {\n return props.children;\n },\n class: local.class,\n style: local.style,\n defaultClassName: \"solidaria-Popover\",\n },\n renderValues,\n );\n\n const [triggerWidth, setTriggerWidth] = createSignal<string | undefined>();\n const hasExplicitTriggerWidth = () => {\n const style = renderProps.style() as (JSX.CSSProperties & Record<string, unknown>) | undefined;\n return style?.[\"--trigger-width\"] != null;\n };\n const updateTriggerWidth = () => {\n const trigger = getTriggerRef();\n if (!trigger || hasExplicitTriggerWidth()) return;\n setTriggerWidth(`${trigger.getBoundingClientRect().width}px`);\n };\n createEffect(() => {\n if (!isOpen()) return;\n updateTriggerWidth();\n\n const trigger = getTriggerRef();\n if (!trigger || hasExplicitTriggerWidth() || typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(updateTriggerWidth);\n observer.observe(trigger);\n onCleanup(() => observer.disconnect());\n });\n\n const domProps = createMemo(() =>\n filterDOMProps(rest as Record<string, unknown>, { global: true }),\n );\n const overlayId = () => {\n const restId = (rest as Record<string, unknown>).id as string | undefined;\n return (\n restId ??\n (triggerContext?.overlayProps?.id as string | undefined) ??\n (dialogTriggerContext?.overlayProps?.id as string | undefined)\n );\n };\n\n const cleanPopoverProps = () => {\n const {\n style: _style,\n ref: _ref,\n ...remaining\n } = popoverAria.popoverProps as Record<string, unknown>;\n return remaining;\n };\n\n const mergedStyle = (): JSX.CSSProperties => {\n const ariaStyle = (popoverAria.popoverProps as Record<string, unknown>).style as\n | JSX.CSSProperties\n | undefined;\n const renderStyle = (renderProps.style() || {}) as JSX.CSSProperties & Record<string, unknown>;\n return {\n ...ariaStyle,\n ...renderStyle,\n \"--trigger-width\": renderStyle[\"--trigger-width\"] ?? triggerWidth(),\n };\n };\n\n const shouldBeDialog = () => !local.isNonModal || resolvedTrigger() === \"SubmenuTrigger\";\n const shouldContainFocus = () => {\n if (!shouldBeDialog()) {\n return false;\n }\n\n const trigger = resolvedTrigger();\n return trigger !== \"MenuTrigger\" && trigger !== \"SubmenuTrigger\";\n };\n const portalContext = useUNSAFE_PortalContext();\n const portalContainer = () => {\n if (isSubPopover()) {\n return popoverGroupContext?.() ?? portalContext.getContainer?.() ?? undefined;\n }\n return portalContext.getContainer?.() ?? undefined;\n };\n\n // Match React Aria Components: focus the popover container only when no\n // descendant has already moved focus during mount.\n createEffect(() => {\n if (!isOpen() || !shouldBeDialog()) return;\n if ((local.autoFocus ?? true) === false) return;\n if (!popoverRef) return;\n if (resolvedTrigger() === \"SubmenuTrigger\") return;\n\n let timeout: number | undefined;\n let frame: number | undefined;\n\n const focusIfNeeded = () => {\n if (!isOpen() || !shouldBeDialog()) return;\n if (!popoverRef || resolvedTrigger() === \"SubmenuTrigger\") return;\n if (document.activeElement === popoverRef || popoverRef.contains(document.activeElement)) {\n return;\n }\n popoverRef.focus();\n };\n\n const scheduleFocus = () => {\n timeout = window.setTimeout(focusIfNeeded, 0);\n };\n\n if (typeof window.requestAnimationFrame === \"function\") {\n frame = window.requestAnimationFrame(scheduleFocus);\n } else {\n scheduleFocus();\n }\n\n onCleanup(() => {\n if (frame !== undefined) {\n window.cancelAnimationFrame(frame);\n }\n if (timeout !== undefined) {\n window.clearTimeout(timeout);\n }\n });\n });\n\n // Fallback Escape handling for environments where focus is not moved into the popover.\n createEffect(() => {\n if (!isOpen()) return;\n if (local.isKeyboardDismissDisabled) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n if (event.defaultPrevented) return;\n close();\n };\n\n document.addEventListener(\"keydown\", onKeyDown);\n onCleanup(() => document.removeEventListener(\"keydown\", onKeyDown));\n });\n\n const overlay = () => (\n <PopoverContext.Provider\n value={{ placement: popoverAria.placement, arrowProps: () => popoverAria.arrowProps }}\n >\n <FocusScope contain={shouldContainFocus()} restoreFocus>\n <div\n {...domProps()}\n {...cleanPopoverProps()}\n ref={popoverRef}\n id={overlayId()}\n role={shouldBeDialog() ? \"dialog\" : undefined}\n tabIndex={shouldBeDialog() ? -1 : undefined}\n class={renderProps.class()}\n style={mergedStyle()}\n data-trigger={resolvedTrigger()}\n data-placement={popoverAria.placement()}\n data-entering={dataAttr(local.isEntering)}\n data-exiting={dataAttr(local.isExiting)}\n >\n <Show when={!local.isNonModal}>\n <PopoverDismissButton onDismiss={close} />\n </Show>\n {renderProps.renderChildren()}\n <PopoverDismissButton onDismiss={close} />\n </div>\n </FocusScope>\n </PopoverContext.Provider>\n );\n\n const underlay = () => (\n <div\n data-testid=\"underlay\"\n {...(popoverAria.underlayProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}\n style={{ position: \"fixed\", inset: 0 }}\n />\n );\n\n return (\n <Show when={isHydrated() && (isOpen() || local.isExiting)}>\n <Portal mount={portalContainer()}>\n <Show when={!local.isNonModal && !isSubPopover() && isOpen()}>{underlay()}</Show>\n <Show\n when={isSubPopover()}\n fallback={\n <div ref={setGroupRef} style={{ display: \"contents\" }}>\n <PopoverGroupContext.Provider value={() => groupRef()}>\n {overlay()}\n </PopoverGroupContext.Provider>\n </div>\n }\n >\n {overlay()}\n </Show>\n </Portal>\n </Show>\n );\n}\n\nexport interface OverlayArrowProps {\n /** The children - should be an SVG or element for the arrow. */\n children?: JSX.Element;\n /** Render function used when Solid children accessors would be ambiguous. */\n render?: () => JSX.Element;\n /** The CSS className. */\n class?: string;\n /** The inline style. */\n style?: JSX.CSSProperties;\n}\n\n/**\n * An arrow element that points towards the trigger.\n */\nexport function OverlayArrow(props: OverlayArrowProps): JSX.Element {\n const popoverContext = useContext(PopoverContext);\n const placement = () => popoverContext?.placement() ?? null;\n\n // Mirror react-aria-components' OverlayArrow: the wrapper positions itself\n // absolutely against the popover edge (`[placement]: '100%'`) and takes the\n // cross-axis offset (`left`/`top`) from the overlay's computed `arrowProps`.\n // No `aria-hidden`/`role=\"presentation\"` — upstream leaves the arrow in the\n // accessibility tree (the arrow SVG surfaces as an unlabeled `img`), matching\n // S2's `<OverlayArrow className=\"\">`. The styled layer therefore passes no\n // positioning class of its own.\n const mergedStyle = (): JSX.CSSProperties => {\n const currentPlacement = placement();\n // Mirror react-aria-components' OverlayArrow: the reported `arrowProps`\n // offset (`left`/`top`) points at the arrow's CENTER, so the wrapper must be\n // pulled back by half its size to center on that point — horizontally for\n // top/bottom placements, vertically for left/right. Omitting this shifts the\n // arrow off by half its width/height (a self-inflicted divergence).\n const style: JSX.CSSProperties = {\n position: \"absolute\",\n transform:\n currentPlacement === \"top\" || currentPlacement === \"bottom\"\n ? \"translateX(-50%)\"\n : \"translateY(-50%)\",\n };\n if (currentPlacement != null) {\n (style as Record<string, string>)[currentPlacement] = \"100%\";\n }\n\n const contextStyle = (popoverContext?.arrowProps() as Record<string, unknown> | undefined)\n ?.style as (JSX.CSSProperties & Record<string, unknown>) | undefined;\n if (typeof contextStyle?.left === \"string\") {\n style.left = contextStyle.left;\n }\n if (typeof contextStyle?.top === \"string\") {\n style.top = contextStyle.top;\n }\n\n const localStyle =\n props.style &&\n !(typeof CSSStyleDeclaration !== \"undefined\" && props.style instanceof CSSStyleDeclaration)\n ? props.style\n : undefined;\n\n return {\n ...style,\n ...localStyle,\n };\n };\n\n return (\n <div class={props.class} style={mergedStyle()} data-placement={placement()}>\n {props.render ? props.render() : props.children}\n </div>\n );\n}\n\nexport default Popover;\n"],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { memo } from "solid-js/web";
2
+ import { children, createEffect, onCleanup, splitProps } from "solid-js";
3
+ import { createFocusable, createPress } from "@proyecto-viviana/solidaria";
4
+ //#region src/Pressable.tsx
5
+ /**
6
+ * Pressable component for solidaria-components
7
+ *
8
+ * A render-prop component that wraps createPress + createFocusable
9
+ * to make an element pressable. Port of React Aria's Pressable.
10
+ */
11
+ /**
12
+ * Makes its child element pressable and focusable.
13
+ * Combines createPress and createFocusable for full interaction support.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <Pressable onPress={() => console.log('pressed')}>
18
+ * <div role="button" tabIndex={0}>Click me</div>
19
+ * </Pressable>
20
+ * ```
21
+ */
22
+ function Pressable(props) {
23
+ const [local, pressProps] = splitProps(props, ["children", "ref"]);
24
+ let ref;
25
+ const { pressProps: domPressProps } = createPress(pressProps);
26
+ const { focusableProps: domFocusableProps } = createFocusable(pressProps, () => ref);
27
+ const resolved = children(() => local.children);
28
+ createEffect(() => {
29
+ const child = resolved();
30
+ if (child instanceof HTMLElement) {
31
+ ref = child;
32
+ if (typeof local.ref === "function") local.ref(child);
33
+ const allProps = {
34
+ ...domFocusableProps,
35
+ ...domPressProps
36
+ };
37
+ const listeners = [];
38
+ for (const [key, handler] of Object.entries(allProps)) if (key.startsWith("on") && typeof handler === "function") {
39
+ const eventName = key.slice(2).toLowerCase();
40
+ const listener = handler;
41
+ child.addEventListener(eventName, listener);
42
+ listeners.push([eventName, listener]);
43
+ }
44
+ for (const [key, value] of Object.entries(allProps)) {
45
+ if (key === "ref" || key.startsWith("on") && typeof value === "function") continue;
46
+ if (key === "tabIndex") {
47
+ if (child.hasAttribute("tabindex")) continue;
48
+ if (value == null || value === false) child.removeAttribute("tabindex");
49
+ else child.tabIndex = Number(value);
50
+ continue;
51
+ }
52
+ if (key.startsWith("aria-") || key.startsWith("data-") || key === "id" || key === "role") {
53
+ if (child.hasAttribute(key)) continue;
54
+ if (value == null || value === false) child.removeAttribute(key);
55
+ else if (value === true) child.setAttribute(key, "");
56
+ else child.setAttribute(key, String(value));
57
+ }
58
+ }
59
+ onCleanup(() => {
60
+ for (const [eventName, listener] of listeners) child.removeEventListener(eventName, listener);
61
+ });
62
+ }
63
+ });
64
+ return memo(resolved);
65
+ }
66
+ //#endregion
67
+ export { Pressable };
68
+
69
+ //# sourceMappingURL=Pressable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pressable.js","names":["JSX","children","resolveChildren","createEffect","onCleanup","splitProps","createPress","createFocusable","CreatePressProps","CreateFocusableProps","PressableProps","Element","ref","HTMLElement","el","Pressable","props","local","pressProps","domPressProps","focusableProps","domFocusableProps","resolved","child","allProps","listeners","Array","EventListener","key","handler","Object","entries","startsWith","eventName","slice","toLowerCase","listener","addEventListener","push","value","hasAttribute","removeAttribute","tabIndex","Number","setAttribute","String","removeEventListener","_$memo"],"sources":["../src/Pressable.tsx"],"sourcesContent":["/**\n * Pressable component for solidaria-components\n *\n * A render-prop component that wraps createPress + createFocusable\n * to make an element pressable. Port of React Aria's Pressable.\n */\n\nimport {\n type JSX,\n children as resolveChildren,\n createEffect,\n onCleanup,\n splitProps,\n} from \"solid-js\";\nimport {\n createPress,\n createFocusable,\n type CreatePressProps,\n type CreateFocusableProps,\n} from \"@proyecto-viviana/solidaria\";\n\nexport interface PressableProps extends CreatePressProps {\n /** A single child element to make pressable. */\n children: JSX.Element;\n /** Ref callback. */\n ref?: HTMLElement | ((el: HTMLElement) => void);\n}\n\n/**\n * Makes its child element pressable and focusable.\n * Combines createPress and createFocusable for full interaction support.\n *\n * @example\n * ```tsx\n * <Pressable onPress={() => console.log('pressed')}>\n * <div role=\"button\" tabIndex={0}>Click me</div>\n * </Pressable>\n * ```\n */\nexport function Pressable(props: PressableProps): JSX.Element {\n const [local, pressProps] = splitProps(props, [\"children\", \"ref\"]);\n\n let ref!: HTMLElement;\n const { pressProps: domPressProps } = createPress(pressProps);\n const { focusableProps: domFocusableProps } = createFocusable(\n pressProps as CreateFocusableProps,\n () => ref,\n );\n\n const resolved = resolveChildren(() => local.children);\n\n createEffect(() => {\n const child = resolved() as HTMLElement;\n if (child instanceof HTMLElement) {\n ref = child;\n if (typeof local.ref === \"function\") {\n local.ref(child);\n }\n\n // Apply press props\n const allProps = { ...domFocusableProps, ...domPressProps };\n const listeners: Array<[string, EventListener]> = [];\n for (const [key, handler] of Object.entries(allProps)) {\n if (key.startsWith(\"on\") && typeof handler === \"function\") {\n const eventName = key.slice(2).toLowerCase();\n const listener = handler as EventListener;\n child.addEventListener(eventName, listener);\n listeners.push([eventName, listener]);\n }\n }\n\n // Apply non-event press/focusable props (e.g. tabIndex/data attrs).\n // Keep explicit child tabIndex to mirror mergeProps(child.props precedence).\n for (const [key, value] of Object.entries(allProps)) {\n if (key === \"ref\" || (key.startsWith(\"on\") && typeof value === \"function\")) continue;\n\n if (key === \"tabIndex\") {\n if (child.hasAttribute(\"tabindex\")) continue;\n if (value == null || value === false) {\n child.removeAttribute(\"tabindex\");\n } else {\n child.tabIndex = Number(value);\n }\n continue;\n }\n\n if (key.startsWith(\"aria-\") || key.startsWith(\"data-\") || key === \"id\" || key === \"role\") {\n if (child.hasAttribute(key)) continue;\n if (value == null || value === false) {\n child.removeAttribute(key);\n } else if (value === true) {\n child.setAttribute(key, \"\");\n } else {\n child.setAttribute(key, String(value));\n }\n }\n }\n\n onCleanup(() => {\n for (const [eventName, listener] of listeners) {\n child.removeEventListener(eventName, listener);\n }\n });\n }\n });\n\n return <>{resolved()}</>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAuCA,SAAgBe,UAAUC,OAAoC;CAC5D,MAAM,CAACC,OAAOC,cAAcb,WAAWW,OAAO,CAAC,YAAY,KAAK,CAAC;CAEjE,IAAIJ;CACJ,MAAM,EAAEM,YAAYC,kBAAkBb,YAAYY,UAAU;CAC5D,MAAM,EAAEE,gBAAgBC,sBAAsBd,gBAC5CW,kBACMN,GACR;CAEA,MAAMU,WAAWpB,eAAsBe,MAAMhB,QAAQ;CAErDE,mBAAmB;EACjB,MAAMoB,QAAQD,SAAS;EACvB,IAAIC,iBAAiBV,aAAa;GAChCD,MAAMW;GACN,IAAI,OAAON,MAAML,QAAQ,YACvBK,MAAML,IAAIW,KAAK;GAIjB,MAAMC,WAAW;IAAE,GAAGH;IAAmB,GAAGF;GAAc;GAC1D,MAAMM,YAA4C,CAAA;GAClD,KAAK,MAAM,CAACG,KAAKC,YAAYC,OAAOC,QAAQP,QAAQ,GAClD,IAAII,IAAII,WAAW,IAAI,KAAK,OAAOH,YAAY,YAAY;IACzD,MAAMI,YAAYL,IAAIM,MAAM,CAAC,CAAC,CAACC,YAAY;IAC3C,MAAMC,WAAWP;IACjBN,MAAMc,iBAAiBJ,WAAWG,QAAQ;IAC1CX,UAAUa,KAAK,CAACL,WAAWG,QAAQ,CAAC;GACtC;GAKF,KAAK,MAAM,CAACR,KAAKW,UAAUT,OAAOC,QAAQP,QAAQ,GAAG;IACnD,IAAII,QAAQ,SAAUA,IAAII,WAAW,IAAI,KAAK,OAAOO,UAAU,YAAa;IAE5E,IAAIX,QAAQ,YAAY;KACtB,IAAIL,MAAMiB,aAAa,UAAU,GAAG;KACpC,IAAID,SAAS,QAAQA,UAAU,OAC7BhB,MAAMkB,gBAAgB,UAAU;UAEhClB,MAAMmB,WAAWC,OAAOJ,KAAK;KAE/B;IACF;IAEA,IAAIX,IAAII,WAAW,OAAO,KAAKJ,IAAII,WAAW,OAAO,KAAKJ,QAAQ,QAAQA,QAAQ,QAAQ;KACxF,IAAIL,MAAMiB,aAAaZ,GAAG,GAAG;KAC7B,IAAIW,SAAS,QAAQA,UAAU,OAC7BhB,MAAMkB,gBAAgBb,GAAG;UACpB,IAAIW,UAAU,MACnBhB,MAAMqB,aAAahB,KAAK,EAAE;UAE1BL,MAAMqB,aAAahB,KAAKiB,OAAON,KAAK,CAAC;IAEzC;GACF;GAEAnC,gBAAgB;IACd,KAAK,MAAM,CAAC6B,WAAWG,aAAaX,WAClCF,MAAMuB,oBAAoBb,WAAWG,QAAQ;GAEjD,CAAC;EACH;CACF,CAAC;CAED,OAAAW,KAAUzB,QAAQ;AACpB"}
@@ -0,0 +1,68 @@
1
+ import { children, createEffect, onCleanup, splitProps } from "solid-js";
2
+ import { createFocusable, createPress } from "@proyecto-viviana/solidaria";
3
+ //#region src/Pressable.tsx
4
+ /**
5
+ * Pressable component for solidaria-components
6
+ *
7
+ * A render-prop component that wraps createPress + createFocusable
8
+ * to make an element pressable. Port of React Aria's Pressable.
9
+ */
10
+ /**
11
+ * Makes its child element pressable and focusable.
12
+ * Combines createPress and createFocusable for full interaction support.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <Pressable onPress={() => console.log('pressed')}>
17
+ * <div role="button" tabIndex={0}>Click me</div>
18
+ * </Pressable>
19
+ * ```
20
+ */
21
+ function Pressable(props) {
22
+ const [local, pressProps] = splitProps(props, ["children", "ref"]);
23
+ let ref;
24
+ const { pressProps: domPressProps } = createPress(pressProps);
25
+ const { focusableProps: domFocusableProps } = createFocusable(pressProps, () => ref);
26
+ const resolved = children(() => local.children);
27
+ createEffect(() => {
28
+ const child = resolved();
29
+ if (child instanceof HTMLElement) {
30
+ ref = child;
31
+ if (typeof local.ref === "function") local.ref(child);
32
+ const allProps = {
33
+ ...domFocusableProps,
34
+ ...domPressProps
35
+ };
36
+ const listeners = [];
37
+ for (const [key, handler] of Object.entries(allProps)) if (key.startsWith("on") && typeof handler === "function") {
38
+ const eventName = key.slice(2).toLowerCase();
39
+ const listener = handler;
40
+ child.addEventListener(eventName, listener);
41
+ listeners.push([eventName, listener]);
42
+ }
43
+ for (const [key, value] of Object.entries(allProps)) {
44
+ if (key === "ref" || key.startsWith("on") && typeof value === "function") continue;
45
+ if (key === "tabIndex") {
46
+ if (child.hasAttribute("tabindex")) continue;
47
+ if (value == null || value === false) child.removeAttribute("tabindex");
48
+ else child.tabIndex = Number(value);
49
+ continue;
50
+ }
51
+ if (key.startsWith("aria-") || key.startsWith("data-") || key === "id" || key === "role") {
52
+ if (child.hasAttribute(key)) continue;
53
+ if (value == null || value === false) child.removeAttribute(key);
54
+ else if (value === true) child.setAttribute(key, "");
55
+ else child.setAttribute(key, String(value));
56
+ }
57
+ }
58
+ onCleanup(() => {
59
+ for (const [eventName, listener] of listeners) child.removeEventListener(eventName, listener);
60
+ });
61
+ }
62
+ });
63
+ return <>{resolved()}</>;
64
+ }
65
+ //#endregion
66
+ export { Pressable };
67
+
68
+ //# sourceMappingURL=Pressable.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pressable.jsx","names":["resolveChildren"],"sources":["../src/Pressable.tsx"],"sourcesContent":["/**\n * Pressable component for solidaria-components\n *\n * A render-prop component that wraps createPress + createFocusable\n * to make an element pressable. Port of React Aria's Pressable.\n */\n\nimport {\n type JSX,\n children as resolveChildren,\n createEffect,\n onCleanup,\n splitProps,\n} from \"solid-js\";\nimport {\n createPress,\n createFocusable,\n type CreatePressProps,\n type CreateFocusableProps,\n} from \"@proyecto-viviana/solidaria\";\n\nexport interface PressableProps extends CreatePressProps {\n /** A single child element to make pressable. */\n children: JSX.Element;\n /** Ref callback. */\n ref?: HTMLElement | ((el: HTMLElement) => void);\n}\n\n/**\n * Makes its child element pressable and focusable.\n * Combines createPress and createFocusable for full interaction support.\n *\n * @example\n * ```tsx\n * <Pressable onPress={() => console.log('pressed')}>\n * <div role=\"button\" tabIndex={0}>Click me</div>\n * </Pressable>\n * ```\n */\nexport function Pressable(props: PressableProps): JSX.Element {\n const [local, pressProps] = splitProps(props, [\"children\", \"ref\"]);\n\n let ref!: HTMLElement;\n const { pressProps: domPressProps } = createPress(pressProps);\n const { focusableProps: domFocusableProps } = createFocusable(\n pressProps as CreateFocusableProps,\n () => ref,\n );\n\n const resolved = resolveChildren(() => local.children);\n\n createEffect(() => {\n const child = resolved() as HTMLElement;\n if (child instanceof HTMLElement) {\n ref = child;\n if (typeof local.ref === \"function\") {\n local.ref(child);\n }\n\n // Apply press props\n const allProps = { ...domFocusableProps, ...domPressProps };\n const listeners: Array<[string, EventListener]> = [];\n for (const [key, handler] of Object.entries(allProps)) {\n if (key.startsWith(\"on\") && typeof handler === \"function\") {\n const eventName = key.slice(2).toLowerCase();\n const listener = handler as EventListener;\n child.addEventListener(eventName, listener);\n listeners.push([eventName, listener]);\n }\n }\n\n // Apply non-event press/focusable props (e.g. tabIndex/data attrs).\n // Keep explicit child tabIndex to mirror mergeProps(child.props precedence).\n for (const [key, value] of Object.entries(allProps)) {\n if (key === \"ref\" || (key.startsWith(\"on\") && typeof value === \"function\")) continue;\n\n if (key === \"tabIndex\") {\n if (child.hasAttribute(\"tabindex\")) continue;\n if (value == null || value === false) {\n child.removeAttribute(\"tabindex\");\n } else {\n child.tabIndex = Number(value);\n }\n continue;\n }\n\n if (key.startsWith(\"aria-\") || key.startsWith(\"data-\") || key === \"id\" || key === \"role\") {\n if (child.hasAttribute(key)) continue;\n if (value == null || value === false) {\n child.removeAttribute(key);\n } else if (value === true) {\n child.setAttribute(key, \"\");\n } else {\n child.setAttribute(key, String(value));\n }\n }\n }\n\n onCleanup(() => {\n for (const [eventName, listener] of listeners) {\n child.removeEventListener(eventName, listener);\n }\n });\n }\n });\n\n return <>{resolved()}</>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuCA,SAAgB,UAAU,OAAoC;CAC5D,MAAM,CAAC,OAAO,cAAc,WAAW,OAAO,CAAC,YAAY,KAAK,CAAC;CAEjE,IAAI;CACJ,MAAM,EAAE,YAAY,kBAAkB,YAAY,UAAU;CAC5D,MAAM,EAAE,gBAAgB,sBAAsB,gBAC5C,kBACM,GACR;CAEA,MAAM,WAAWA,eAAsB,MAAM,QAAQ;CAErD,mBAAmB;EACjB,MAAM,QAAQ,SAAS;EACvB,IAAI,iBAAiB,aAAa;GAChC,MAAM;GACN,IAAI,OAAO,MAAM,QAAQ,YACvB,MAAM,IAAI,KAAK;GAIjB,MAAM,WAAW;IAAE,GAAG;IAAmB,GAAG;GAAc;GAC1D,MAAM,YAA4C,CAAC;GACnD,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAAQ,QAAQ,GAClD,IAAI,IAAI,WAAW,IAAI,KAAK,OAAO,YAAY,YAAY;IACzD,MAAM,YAAY,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY;IAC3C,MAAM,WAAW;IACjB,MAAM,iBAAiB,WAAW,QAAQ;IAC1C,UAAU,KAAK,CAAC,WAAW,QAAQ,CAAC;GACtC;GAKF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,GAAG;IACnD,IAAI,QAAQ,SAAU,IAAI,WAAW,IAAI,KAAK,OAAO,UAAU,YAAa;IAE5E,IAAI,QAAQ,YAAY;KACtB,IAAI,MAAM,aAAa,UAAU,GAAG;KACpC,IAAI,SAAS,QAAQ,UAAU,OAC7B,MAAM,gBAAgB,UAAU;UAEhC,MAAM,WAAW,OAAO,KAAK;KAE/B;IACF;IAEA,IAAI,IAAI,WAAW,OAAO,KAAK,IAAI,WAAW,OAAO,KAAK,QAAQ,QAAQ,QAAQ,QAAQ;KACxF,IAAI,MAAM,aAAa,GAAG,GAAG;KAC7B,IAAI,SAAS,QAAQ,UAAU,OAC7B,MAAM,gBAAgB,GAAG;UACpB,IAAI,UAAU,MACnB,MAAM,aAAa,KAAK,EAAE;UAE1B,MAAM,aAAa,KAAK,OAAO,KAAK,CAAC;IAEzC;GACF;GAEA,gBAAgB;IACd,KAAK,MAAM,CAAC,WAAW,aAAa,WAClC,MAAM,oBAAoB,WAAW,QAAQ;GAEjD,CAAC;EACH;CACF,CAAC;CAED,OAAO,GAAG,SAAS,EAAE;AACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../src/ProgressBar.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAiE,MAAM,UAAU,CAAC;AACnG,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,SAAS,EAGf,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,wCAAwC;IACxC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB,EAAE,SAAS;IACvE,sBAAsB;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yFAAyF;IACzF,QAAQ,CAAC,EAAE,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAClD,yCAAyC;IACzC,KAAK,CAAC,EAAE,mBAAmB,CAAC,sBAAsB,CAAC,CAAC;IACpD,wCAAwC;IACxC,KAAK,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,kBAAkB,qDAA+C,CAAC;AAW/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CA0FhE"}
1
+ {"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../src/ProgressBar.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAiE,MAAM,UAAU,CAAC;AACnG,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAC3F,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,SAAS,EAGf,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,wCAAwC;IACxC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB,EAAE,SAAS;IACvE,sBAAsB;IACtB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yFAAyF;IACzF,QAAQ,CAAC,EAAE,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAClD,yCAAyC;IACzC,KAAK,CAAC,EAAE,mBAAmB,CAAC,sBAAsB,CAAC,CAAC;IACpD,wCAAwC;IACxC,KAAK,CAAC,EAAE,eAAe,CAAC,sBAAsB,CAAC,CAAC;CACjD;AAED,eAAO,MAAM,kBAAkB,qDAA+C,CAAC;AAW/E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CA4FhE"}