@proyecto-viviana/solidaria 0.4.0 → 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 (480) hide show
  1. package/dist/_chunk/DragManager.js +627 -0
  2. package/dist/_chunk/DragManager.js.map +1 -0
  3. package/dist/_chunk/DragManager.jsx +627 -0
  4. package/dist/_chunk/DragManager.jsx.map +1 -0
  5. package/dist/_chunk/FocusScope.js +400 -0
  6. package/dist/_chunk/FocusScope.js.map +1 -0
  7. package/dist/_chunk/FocusScope.jsx +375 -0
  8. package/dist/_chunk/FocusScope.jsx.map +1 -0
  9. package/dist/_chunk/actiongroup.js +13 -79
  10. package/dist/_chunk/actiongroup.js.map +1 -1
  11. package/dist/_chunk/actiongroup.jsx +13 -79
  12. package/dist/_chunk/actiongroup.jsx.map +1 -1
  13. package/dist/_chunk/{live-announcer.js → announce.js} +1 -1
  14. package/dist/_chunk/announce.js.map +1 -0
  15. package/dist/_chunk/{live-announcer.jsx → announce.jsx} +1 -1
  16. package/dist/_chunk/announce.jsx.map +1 -0
  17. package/dist/_chunk/autocomplete.js +56 -8
  18. package/dist/_chunk/autocomplete.js.map +1 -1
  19. package/dist/_chunk/autocomplete.jsx +56 -8
  20. package/dist/_chunk/autocomplete.jsx.map +1 -1
  21. package/dist/_chunk/breadcrumbs.js +6 -4
  22. package/dist/_chunk/breadcrumbs.js.map +1 -1
  23. package/dist/_chunk/breadcrumbs.jsx +6 -4
  24. package/dist/_chunk/breadcrumbs.jsx.map +1 -1
  25. package/dist/_chunk/button.js +8 -9
  26. package/dist/_chunk/button.js.map +1 -1
  27. package/dist/_chunk/button.jsx +8 -9
  28. package/dist/_chunk/button.jsx.map +1 -1
  29. package/dist/_chunk/calendar.js +27 -26
  30. package/dist/_chunk/calendar.js.map +1 -1
  31. package/dist/_chunk/calendar.jsx +27 -26
  32. package/dist/_chunk/calendar.jsx.map +1 -1
  33. package/dist/_chunk/checkbox.js +5 -4
  34. package/dist/_chunk/checkbox.js.map +1 -1
  35. package/dist/_chunk/checkbox.jsx +5 -4
  36. package/dist/_chunk/checkbox.jsx.map +1 -1
  37. package/dist/_chunk/color.js +302 -18
  38. package/dist/_chunk/color.js.map +1 -1
  39. package/dist/_chunk/color.jsx +302 -18
  40. package/dist/_chunk/color.jsx.map +1 -1
  41. package/dist/_chunk/combobox.js +638 -12
  42. package/dist/_chunk/combobox.js.map +1 -1
  43. package/dist/_chunk/combobox.jsx +638 -12
  44. package/dist/_chunk/combobox.jsx.map +1 -1
  45. package/dist/_chunk/constants.js +19 -0
  46. package/dist/_chunk/constants.js.map +1 -0
  47. package/dist/_chunk/constants.jsx +19 -0
  48. package/dist/_chunk/constants.jsx.map +1 -0
  49. package/dist/_chunk/createCollator.js +3 -171
  50. package/dist/_chunk/createCollator.js.map +1 -1
  51. package/dist/_chunk/createCollator.jsx +3 -165
  52. package/dist/_chunk/createCollator.jsx.map +1 -1
  53. package/dist/_chunk/createField.js +2 -1
  54. package/dist/_chunk/createField.js.map +1 -1
  55. package/dist/_chunk/createField.jsx +2 -1
  56. package/dist/_chunk/createField.jsx.map +1 -1
  57. package/dist/_chunk/createFocus.js +12 -8
  58. package/dist/_chunk/createFocus.js.map +1 -1
  59. package/dist/_chunk/createFocus.jsx +12 -8
  60. package/dist/_chunk/createFocus.jsx.map +1 -1
  61. package/dist/_chunk/createFocusWithin.js +12 -13
  62. package/dist/_chunk/createFocusWithin.js.map +1 -1
  63. package/dist/_chunk/createFocusWithin.jsx +12 -13
  64. package/dist/_chunk/createFocusWithin.jsx.map +1 -1
  65. package/dist/_chunk/createFocusable.js +3 -3
  66. package/dist/_chunk/createFocusable.js.map +1 -1
  67. package/dist/_chunk/createFocusable.jsx +3 -3
  68. package/dist/_chunk/createFocusable.jsx.map +1 -1
  69. package/dist/_chunk/{form.js → createFormReset.js} +1 -1
  70. package/dist/_chunk/createFormReset.js.map +1 -0
  71. package/dist/_chunk/{form.jsx → createFormReset.jsx} +1 -1
  72. package/dist/_chunk/createFormReset.jsx.map +1 -0
  73. package/dist/_chunk/createHover.js +2 -1
  74. package/dist/_chunk/createHover.js.map +1 -1
  75. package/dist/_chunk/createHover.jsx +2 -1
  76. package/dist/_chunk/createHover.jsx.map +1 -1
  77. package/dist/_chunk/createInteractionModality.js +2 -3
  78. package/dist/_chunk/createInteractionModality.js.map +1 -1
  79. package/dist/_chunk/createInteractionModality.jsx +2 -3
  80. package/dist/_chunk/createInteractionModality.jsx.map +1 -1
  81. package/dist/_chunk/createLabel.js +2 -1
  82. package/dist/_chunk/createLabel.js.map +1 -1
  83. package/dist/_chunk/createLabel.jsx +2 -1
  84. package/dist/_chunk/createLabel.jsx.map +1 -1
  85. package/dist/_chunk/createLabels.js +3 -2
  86. package/dist/_chunk/createLabels.js.map +1 -1
  87. package/dist/_chunk/createLabels.jsx +3 -2
  88. package/dist/_chunk/createLabels.jsx.map +1 -1
  89. package/dist/_chunk/createLandmark.js +1 -1
  90. package/dist/_chunk/createLandmark.jsx +1 -1
  91. package/dist/_chunk/createProgressBar.js +2 -1
  92. package/dist/_chunk/createProgressBar.js.map +1 -1
  93. package/dist/_chunk/createProgressBar.jsx +2 -1
  94. package/dist/_chunk/createProgressBar.jsx.map +1 -1
  95. package/dist/_chunk/createSelectableItem.js +7 -3
  96. package/dist/_chunk/createSelectableItem.js.map +1 -1
  97. package/dist/_chunk/createSelectableItem.jsx +7 -3
  98. package/dist/_chunk/createSelectableItem.jsx.map +1 -1
  99. package/dist/_chunk/createStringFormatter.js +61 -0
  100. package/dist/_chunk/createStringFormatter.js.map +1 -0
  101. package/dist/_chunk/createStringFormatter.jsx +61 -0
  102. package/dist/_chunk/createStringFormatter.jsx.map +1 -0
  103. package/dist/_chunk/createToggle.js +5 -4
  104. package/dist/_chunk/createToggle.js.map +1 -1
  105. package/dist/_chunk/createToggle.jsx +5 -4
  106. package/dist/_chunk/createToggle.jsx.map +1 -1
  107. package/dist/_chunk/datepicker.js +1413 -1100
  108. package/dist/_chunk/datepicker.js.map +1 -1
  109. package/dist/_chunk/datepicker.jsx +1413 -1100
  110. package/dist/_chunk/datepicker.jsx.map +1 -1
  111. package/dist/_chunk/disclosure.js +2 -2
  112. package/dist/_chunk/disclosure.js.map +1 -1
  113. package/dist/_chunk/disclosure.jsx +2 -2
  114. package/dist/_chunk/disclosure.jsx.map +1 -1
  115. package/dist/_chunk/dnd.js +1586 -495
  116. package/dist/_chunk/dnd.js.map +1 -1
  117. package/dist/_chunk/dnd.jsx +1586 -495
  118. package/dist/_chunk/dnd.jsx.map +1 -1
  119. package/dist/_chunk/env.js +1 -19
  120. package/dist/_chunk/env.js.map +1 -1
  121. package/dist/_chunk/env.jsx +1 -19
  122. package/dist/_chunk/env.jsx.map +1 -1
  123. package/dist/_chunk/focus.js +1 -1
  124. package/dist/_chunk/focus.js.map +1 -1
  125. package/dist/_chunk/focus.jsx +1 -1
  126. package/dist/_chunk/focus.jsx.map +1 -1
  127. package/dist/_chunk/focus2.js +54 -318
  128. package/dist/_chunk/focus2.js.map +1 -1
  129. package/dist/_chunk/focus2.jsx +53 -292
  130. package/dist/_chunk/focus2.jsx.map +1 -1
  131. package/dist/_chunk/grid.js +1 -1
  132. package/dist/_chunk/grid.jsx +1 -1
  133. package/dist/_chunk/gridlist.js +14 -9
  134. package/dist/_chunk/gridlist.js.map +1 -1
  135. package/dist/_chunk/gridlist.jsx +14 -9
  136. package/dist/_chunk/gridlist.jsx.map +1 -1
  137. package/dist/_chunk/i18n.js +3 -58
  138. package/dist/_chunk/i18n.js.map +1 -1
  139. package/dist/_chunk/i18n.jsx +3 -58
  140. package/dist/_chunk/i18n.jsx.map +1 -1
  141. package/dist/_chunk/interactions.js +99 -9
  142. package/dist/_chunk/interactions.js.map +1 -1
  143. package/dist/_chunk/interactions.jsx +97 -9
  144. package/dist/_chunk/interactions.jsx.map +1 -1
  145. package/dist/_chunk/link.js +2 -1
  146. package/dist/_chunk/link.js.map +1 -1
  147. package/dist/_chunk/link.jsx +2 -1
  148. package/dist/_chunk/link.jsx.map +1 -1
  149. package/dist/_chunk/listbox.js +42 -10
  150. package/dist/_chunk/listbox.js.map +1 -1
  151. package/dist/_chunk/listbox.jsx +42 -10
  152. package/dist/_chunk/listbox.jsx.map +1 -1
  153. package/dist/_chunk/locale.js +173 -0
  154. package/dist/_chunk/locale.js.map +1 -0
  155. package/dist/_chunk/locale.jsx +167 -0
  156. package/dist/_chunk/locale.jsx.map +1 -0
  157. package/dist/_chunk/menu.js +5 -4
  158. package/dist/_chunk/menu.js.map +1 -1
  159. package/dist/_chunk/menu.jsx +5 -4
  160. package/dist/_chunk/menu.jsx.map +1 -1
  161. package/dist/_chunk/numberfield.js +3 -2
  162. package/dist/_chunk/numberfield.js.map +1 -1
  163. package/dist/_chunk/numberfield.jsx +3 -2
  164. package/dist/_chunk/numberfield.jsx.map +1 -1
  165. package/dist/_chunk/overlays.js +1 -1
  166. package/dist/_chunk/overlays.jsx +1 -1
  167. package/dist/_chunk/popover.js +3 -3
  168. package/dist/_chunk/popover.js.map +1 -1
  169. package/dist/_chunk/popover.jsx +3 -3
  170. package/dist/_chunk/popover.jsx.map +1 -1
  171. package/dist/_chunk/radio.js +7 -6
  172. package/dist/_chunk/radio.js.map +1 -1
  173. package/dist/_chunk/radio.jsx +7 -6
  174. package/dist/_chunk/radio.jsx.map +1 -1
  175. package/dist/_chunk/reactivity.js +21 -0
  176. package/dist/_chunk/reactivity.js.map +1 -0
  177. package/dist/_chunk/reactivity.jsx +21 -0
  178. package/dist/_chunk/reactivity.jsx.map +1 -0
  179. package/dist/_chunk/searchfield.js +2 -1
  180. package/dist/_chunk/searchfield.js.map +1 -1
  181. package/dist/_chunk/searchfield.jsx +2 -1
  182. package/dist/_chunk/searchfield.jsx.map +1 -1
  183. package/dist/_chunk/select.js +8 -5
  184. package/dist/_chunk/select.js.map +1 -1
  185. package/dist/_chunk/select.jsx +8 -5
  186. package/dist/_chunk/select.jsx.map +1 -1
  187. package/dist/_chunk/selection.js +8 -21
  188. package/dist/_chunk/selection.js.map +1 -1
  189. package/dist/_chunk/selection.jsx +8 -21
  190. package/dist/_chunk/selection.jsx.map +1 -1
  191. package/dist/_chunk/separator.js +1 -1
  192. package/dist/_chunk/separator.jsx +1 -1
  193. package/dist/_chunk/slider.js +5 -4
  194. package/dist/_chunk/slider.js.map +1 -1
  195. package/dist/_chunk/slider.jsx +5 -4
  196. package/dist/_chunk/slider.jsx.map +1 -1
  197. package/dist/_chunk/spinbutton.js +153 -0
  198. package/dist/_chunk/spinbutton.js.map +1 -0
  199. package/dist/_chunk/spinbutton.jsx +153 -0
  200. package/dist/_chunk/spinbutton.jsx.map +1 -0
  201. package/dist/_chunk/table.js +45 -8
  202. package/dist/_chunk/table.js.map +1 -1
  203. package/dist/_chunk/table.jsx +45 -8
  204. package/dist/_chunk/table.jsx.map +1 -1
  205. package/dist/_chunk/tabs.js +11 -8
  206. package/dist/_chunk/tabs.js.map +1 -1
  207. package/dist/_chunk/tabs.jsx +11 -8
  208. package/dist/_chunk/tabs.jsx.map +1 -1
  209. package/dist/_chunk/tag.js +54 -18
  210. package/dist/_chunk/tag.js.map +1 -1
  211. package/dist/_chunk/tag.jsx +54 -18
  212. package/dist/_chunk/tag.jsx.map +1 -1
  213. package/dist/_chunk/textfield.js +2 -1
  214. package/dist/_chunk/textfield.js.map +1 -1
  215. package/dist/_chunk/textfield.jsx +2 -1
  216. package/dist/_chunk/textfield.jsx.map +1 -1
  217. package/dist/_chunk/toolbar.js +4 -36
  218. package/dist/_chunk/toolbar.js.map +1 -1
  219. package/dist/_chunk/toolbar.jsx +4 -36
  220. package/dist/_chunk/toolbar.jsx.map +1 -1
  221. package/dist/_chunk/tooltip.js +2 -2
  222. package/dist/_chunk/tooltip.js.map +1 -1
  223. package/dist/_chunk/tooltip.jsx +2 -2
  224. package/dist/_chunk/tooltip.jsx.map +1 -1
  225. package/dist/_chunk/tree.js +42 -14
  226. package/dist/_chunk/tree.js.map +1 -1
  227. package/dist/_chunk/tree.jsx +42 -14
  228. package/dist/_chunk/tree.jsx.map +1 -1
  229. package/dist/_chunk/utils.js +59 -19
  230. package/dist/_chunk/utils.js.map +1 -1
  231. package/dist/_chunk/utils.jsx +59 -19
  232. package/dist/_chunk/utils.jsx.map +1 -1
  233. package/dist/_chunk/visually-hidden.js +3 -2
  234. package/dist/_chunk/visually-hidden.js.map +1 -1
  235. package/dist/_chunk/visually-hidden.jsx +3 -2
  236. package/dist/_chunk/visually-hidden.jsx.map +1 -1
  237. package/dist/actiongroup/createActionGroup.d.ts.map +1 -1
  238. package/dist/autocomplete/createAutocomplete.d.ts +10 -7
  239. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  240. package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
  241. package/dist/button/createToggleButtonGroup.d.ts.map +1 -1
  242. package/dist/calendar/createCalendar.d.ts.map +1 -1
  243. package/dist/calendar/createCalendarCell.d.ts.map +1 -1
  244. package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
  245. package/dist/calendar/createRangeCalendar.d.ts.map +1 -1
  246. package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
  247. package/dist/calendar/intl/index.d.ts +1 -1
  248. package/dist/calendar/intl/index.d.ts.map +1 -1
  249. package/dist/collections/index.js +1 -1
  250. package/dist/collections/index.jsx +1 -1
  251. package/dist/color/createColorArea.d.ts.map +1 -1
  252. package/dist/color/createColorField.d.ts.map +1 -1
  253. package/dist/color/createColorSlider.d.ts.map +1 -1
  254. package/dist/color/createColorSwatch.d.ts.map +1 -1
  255. package/dist/color/createColorWheel.d.ts.map +1 -1
  256. package/dist/color/intl/index.d.ts +30 -0
  257. package/dist/color/intl/index.d.ts.map +1 -0
  258. package/dist/combobox/createComboBox.d.ts.map +1 -1
  259. package/dist/combobox/intl/generated-locales.d.ts +16 -0
  260. package/dist/combobox/intl/generated-locales.d.ts.map +1 -0
  261. package/dist/combobox/intl/index.d.ts +2 -2
  262. package/dist/combobox/intl/index.d.ts.map +1 -1
  263. package/dist/datepicker/createDateField.d.ts +45 -23
  264. package/dist/datepicker/createDateField.d.ts.map +1 -1
  265. package/dist/datepicker/createDatePicker.d.ts +34 -6
  266. package/dist/datepicker/createDatePicker.d.ts.map +1 -1
  267. package/dist/datepicker/createDatePickerGroup.d.ts +13 -13
  268. package/dist/datepicker/createDatePickerGroup.d.ts.map +1 -1
  269. package/dist/datepicker/createDateRangePicker.d.ts +55 -7
  270. package/dist/datepicker/createDateRangePicker.d.ts.map +1 -1
  271. package/dist/datepicker/createDateSegment.d.ts +6 -15
  272. package/dist/datepicker/createDateSegment.d.ts.map +1 -1
  273. package/dist/datepicker/createDisplayNames.d.ts +17 -0
  274. package/dist/datepicker/createDisplayNames.d.ts.map +1 -0
  275. package/dist/datepicker/createTimeField.d.ts +12 -49
  276. package/dist/datepicker/createTimeField.d.ts.map +1 -1
  277. package/dist/datepicker/index.d.ts +3 -3
  278. package/dist/datepicker/index.d.ts.map +1 -1
  279. package/dist/datepicker/index.js +2 -2
  280. package/dist/datepicker/index.jsx +2 -2
  281. package/dist/datepicker/intl.d.ts +12 -0
  282. package/dist/datepicker/intl.d.ts.map +1 -0
  283. package/dist/dnd/DragManager.d.ts +86 -0
  284. package/dist/dnd/DragManager.d.ts.map +1 -0
  285. package/dist/dnd/DropTargetKeyboardNavigation.d.ts +42 -0
  286. package/dist/dnd/DropTargetKeyboardNavigation.d.ts.map +1 -0
  287. package/dist/dnd/createDrag.d.ts.map +1 -1
  288. package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
  289. package/dist/dnd/createDraggableItem.d.ts +12 -7
  290. package/dist/dnd/createDraggableItem.d.ts.map +1 -1
  291. package/dist/dnd/createDroppableCollection.d.ts +7 -15
  292. package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
  293. package/dist/dnd/index.d.ts +5 -1
  294. package/dist/dnd/index.d.ts.map +1 -1
  295. package/dist/dnd/index.js +3 -2
  296. package/dist/dnd/index.jsx +3 -2
  297. package/dist/dnd/intl/index.d.ts +39 -0
  298. package/dist/dnd/intl/index.d.ts.map +1 -0
  299. package/dist/dnd/utils.d.ts +5 -0
  300. package/dist/dnd/utils.d.ts.map +1 -1
  301. package/dist/focus/FocusScope.d.ts +7 -0
  302. package/dist/focus/FocusScope.d.ts.map +1 -1
  303. package/dist/focus/index.d.ts +2 -1
  304. package/dist/focus/index.d.ts.map +1 -1
  305. package/dist/focus/index.js +3 -2
  306. package/dist/focus/index.jsx +3 -2
  307. package/dist/focus/virtualFocus.d.ts +26 -0
  308. package/dist/focus/virtualFocus.d.ts.map +1 -0
  309. package/dist/form/index.js +1 -1
  310. package/dist/form/index.jsx +1 -1
  311. package/dist/gridlist/createGridList.d.ts.map +1 -1
  312. package/dist/i18n/index.js +4 -2
  313. package/dist/i18n/index.jsx +4 -2
  314. package/dist/index.d.ts +3 -3
  315. package/dist/index.d.ts.map +1 -1
  316. package/dist/index.js +18 -12
  317. package/dist/index.jsx +18 -12
  318. package/dist/interactions/FocusableProvider.d.ts.map +1 -1
  319. package/dist/interactions/createFocus.d.ts.map +1 -1
  320. package/dist/interactions/createFocusWithin.d.ts.map +1 -1
  321. package/dist/interactions/createInteractionModality.d.ts.map +1 -1
  322. package/dist/interactions/index.js +1 -2
  323. package/dist/interactions/index.jsx +1 -2
  324. package/dist/label/createLabels.d.ts.map +1 -1
  325. package/dist/listbox/createListBox.d.ts.map +1 -1
  326. package/dist/listbox/createOption.d.ts +1 -1
  327. package/dist/listbox/createOption.d.ts.map +1 -1
  328. package/dist/live-announcer/index.js +1 -1
  329. package/dist/live-announcer/index.jsx +1 -1
  330. package/dist/select/createSelect.d.ts +2 -0
  331. package/dist/select/createSelect.d.ts.map +1 -1
  332. package/dist/selection/createSelectableItem.d.ts.map +1 -1
  333. package/dist/selection/index.js +2 -1
  334. package/dist/selection/index.jsx +2 -1
  335. package/dist/spinbutton/createSpinButton.d.ts +41 -0
  336. package/dist/spinbutton/createSpinButton.d.ts.map +1 -0
  337. package/dist/spinbutton/index.d.ts +3 -0
  338. package/dist/spinbutton/index.d.ts.map +1 -0
  339. package/dist/spinbutton/index.js +2 -0
  340. package/dist/spinbutton/index.jsx +2 -0
  341. package/dist/spinbutton/intl.d.ts +5 -0
  342. package/dist/spinbutton/intl.d.ts.map +1 -0
  343. package/dist/table/createTable.d.ts.map +1 -1
  344. package/dist/table/createTableColumnHeader.d.ts.map +1 -1
  345. package/dist/table/createTableRow.d.ts.map +1 -1
  346. package/dist/table/createTableSelectionCheckbox.d.ts.map +1 -1
  347. package/dist/table/types.d.ts +8 -0
  348. package/dist/table/types.d.ts.map +1 -1
  349. package/dist/table/utils.d.ts +15 -0
  350. package/dist/table/utils.d.ts.map +1 -0
  351. package/dist/tabs/createTabs.d.ts +1 -0
  352. package/dist/tabs/createTabs.d.ts.map +1 -1
  353. package/dist/tag/createTag.d.ts.map +1 -1
  354. package/dist/tag/createTagGroup.d.ts +7 -0
  355. package/dist/tag/createTagGroup.d.ts.map +1 -1
  356. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  357. package/dist/tree/createTree.d.ts.map +1 -1
  358. package/dist/tree/createTreeSelectionCheckbox.d.ts.map +1 -1
  359. package/dist/utils/animation.d.ts.map +1 -1
  360. package/dist/utils/dom.d.ts +1 -0
  361. package/dist/utils/dom.d.ts.map +1 -1
  362. package/dist/utils/index.d.ts +1 -1
  363. package/dist/utils/index.d.ts.map +1 -1
  364. package/dist/utils/index.js +4 -3
  365. package/dist/utils/index.jsx +4 -3
  366. package/package.json +2 -2
  367. package/src/actiongroup/createActionGroup.ts +26 -109
  368. package/src/autocomplete/createAutocomplete.ts +136 -15
  369. package/src/breadcrumbs/createBreadcrumbs.ts +12 -4
  370. package/src/button/createToggleButtonGroup.ts +19 -14
  371. package/src/calendar/createCalendar.ts +3 -4
  372. package/src/calendar/createCalendarCell.ts +17 -3
  373. package/src/calendar/createCalendarGrid.ts +5 -4
  374. package/src/calendar/createRangeCalendar.ts +27 -17
  375. package/src/calendar/createRangeCalendarCell.ts +17 -3
  376. package/src/calendar/intl/index.ts +8 -0
  377. package/src/color/createColorArea.ts +17 -10
  378. package/src/color/createColorField.ts +8 -1
  379. package/src/color/createColorSlider.ts +1 -2
  380. package/src/color/createColorSwatch.ts +4 -2
  381. package/src/color/createColorWheel.ts +0 -6
  382. package/src/color/intl/index.ts +316 -0
  383. package/src/combobox/createComboBox.ts +35 -4
  384. package/src/combobox/intl/generated-locales.ts +635 -0
  385. package/src/combobox/intl/index.ts +8 -2
  386. package/src/datepicker/createDateField.ts +228 -213
  387. package/src/datepicker/createDatePicker.ts +157 -146
  388. package/src/datepicker/createDatePickerGroup.ts +88 -82
  389. package/src/datepicker/createDateRangePicker.ts +230 -179
  390. package/src/datepicker/createDateSegment.ts +386 -389
  391. package/src/datepicker/createDisplayNames.ts +45 -0
  392. package/src/datepicker/createTimeField.ts +36 -129
  393. package/src/datepicker/index.ts +13 -14
  394. package/src/datepicker/intl.ts +633 -0
  395. package/src/dnd/DragManager.ts +693 -0
  396. package/src/dnd/DropTargetKeyboardNavigation.ts +337 -0
  397. package/src/dnd/createDrag.ts +31 -5
  398. package/src/dnd/createDraggableCollection.ts +33 -15
  399. package/src/dnd/createDraggableItem.ts +92 -5
  400. package/src/dnd/createDroppableCollection.ts +487 -373
  401. package/src/dnd/index.ts +11 -0
  402. package/src/dnd/intl/ar-AE.json +29 -0
  403. package/src/dnd/intl/bg-BG.json +29 -0
  404. package/src/dnd/intl/cs-CZ.json +29 -0
  405. package/src/dnd/intl/da-DK.json +29 -0
  406. package/src/dnd/intl/de-DE.json +29 -0
  407. package/src/dnd/intl/el-GR.json +29 -0
  408. package/src/dnd/intl/en-US.json +29 -0
  409. package/src/dnd/intl/es-ES.json +29 -0
  410. package/src/dnd/intl/et-EE.json +29 -0
  411. package/src/dnd/intl/fi-FI.json +29 -0
  412. package/src/dnd/intl/fr-FR.json +29 -0
  413. package/src/dnd/intl/he-IL.json +29 -0
  414. package/src/dnd/intl/hr-HR.json +29 -0
  415. package/src/dnd/intl/hu-HU.json +29 -0
  416. package/src/dnd/intl/index.ts +139 -0
  417. package/src/dnd/intl/it-IT.json +29 -0
  418. package/src/dnd/intl/ja-JP.json +29 -0
  419. package/src/dnd/intl/ko-KR.json +29 -0
  420. package/src/dnd/intl/lt-LT.json +29 -0
  421. package/src/dnd/intl/lv-LV.json +29 -0
  422. package/src/dnd/intl/nb-NO.json +29 -0
  423. package/src/dnd/intl/nl-NL.json +29 -0
  424. package/src/dnd/intl/pl-PL.json +29 -0
  425. package/src/dnd/intl/pt-BR.json +29 -0
  426. package/src/dnd/intl/pt-PT.json +29 -0
  427. package/src/dnd/intl/ro-RO.json +29 -0
  428. package/src/dnd/intl/ru-RU.json +29 -0
  429. package/src/dnd/intl/sk-SK.json +29 -0
  430. package/src/dnd/intl/sl-SI.json +29 -0
  431. package/src/dnd/intl/sr-SP.json +29 -0
  432. package/src/dnd/intl/sv-SE.json +29 -0
  433. package/src/dnd/intl/tr-TR.json +29 -0
  434. package/src/dnd/intl/uk-UA.json +29 -0
  435. package/src/dnd/intl/zh-CN.json +29 -0
  436. package/src/dnd/intl/zh-TW.json +29 -0
  437. package/src/dnd/utils.ts +36 -0
  438. package/src/focus/FocusScope.tsx +120 -12
  439. package/src/focus/index.ts +8 -0
  440. package/src/focus/virtualFocus.ts +55 -0
  441. package/src/gridlist/createGridList.ts +52 -16
  442. package/src/index.ts +11 -3
  443. package/src/interactions/FocusableProvider.tsx +11 -6
  444. package/src/interactions/createFocus.ts +26 -21
  445. package/src/interactions/createFocusWithin.ts +23 -24
  446. package/src/interactions/createInteractionModality.ts +5 -3
  447. package/src/label/createLabels.ts +7 -4
  448. package/src/listbox/createListBox.ts +74 -2
  449. package/src/listbox/createOption.ts +16 -1
  450. package/src/select/createSelect.ts +23 -2
  451. package/src/selection/createSelectableItem.ts +14 -0
  452. package/src/spinbutton/createSpinButton.ts +163 -0
  453. package/src/spinbutton/index.ts +10 -0
  454. package/src/spinbutton/intl.ts +115 -0
  455. package/src/table/createTable.ts +26 -1
  456. package/src/table/createTableColumnHeader.ts +10 -0
  457. package/src/table/createTableRow.ts +10 -0
  458. package/src/table/createTableSelectionCheckbox.ts +24 -1
  459. package/src/table/types.ts +8 -0
  460. package/src/table/utils.ts +41 -0
  461. package/src/tabs/createTabs.ts +53 -12
  462. package/src/tag/createTag.ts +21 -32
  463. package/src/tag/createTagGroup.ts +92 -0
  464. package/src/toolbar/createToolbar.ts +6 -58
  465. package/src/tree/createTree.ts +69 -14
  466. package/src/tree/createTreeSelectionCheckbox.ts +14 -1
  467. package/src/utils/animation.ts +119 -27
  468. package/src/utils/dom.ts +3 -2
  469. package/src/utils/index.ts +2 -0
  470. package/dist/_chunk/createLongPress.js +0 -91
  471. package/dist/_chunk/createLongPress.js.map +0 -1
  472. package/dist/_chunk/createLongPress.jsx +0 -91
  473. package/dist/_chunk/createLongPress.jsx.map +0 -1
  474. package/dist/_chunk/form.js.map +0 -1
  475. package/dist/_chunk/form.jsx.map +0 -1
  476. package/dist/_chunk/live-announcer.js.map +0 -1
  477. package/dist/_chunk/live-announcer.jsx.map +0 -1
  478. package/dist/datepicker/createTimeSegment.d.ts +0 -29
  479. package/dist/datepicker/createTimeSegment.d.ts.map +0 -1
  480. package/src/datepicker/createTimeSegment.ts +0 -352
@@ -1 +1 @@
1
- {"version":3,"file":"createFocusWithin.jsx","names":[],"sources":["../../src/interactions/createFocusWithin.ts"],"sourcesContent":["/**\n * createFocusWithin - Handles focus events for the target and its descendants.\n *\n * This is a 1-1 port of React-Aria's useFocusWithin hook adapted for SolidJS.\n */\n\nimport { JSX, onCleanup } from \"solid-js\";\nimport { getOwnerDocument, getEventTarget, nodeContains, createGlobalListeners } from \"../utils\";\nimport { setEventTarget } from \"../utils/events\";\n\nexport interface FocusWithinProps {\n /** Whether the focus within events should be disabled. */\n isDisabled?: boolean;\n /** Handler that is called when the target element or a descendant receives focus. */\n onFocusWithin?: (e: FocusEvent) => void;\n /** Handler that is called when the target element and all descendants lose focus. */\n onBlurWithin?: (e: FocusEvent) => void;\n /** Handler that is called when the focus within state changes. */\n onFocusWithinChange?: (isFocusWithin: boolean) => void;\n}\n\nexport interface FocusWithinResult {\n /** Props to spread onto the target element. */\n focusWithinProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\nfunction getActiveElement(doc: Document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement && (activeElement as Element).shadowRoot?.activeElement) {\n activeElement = (activeElement as Element).shadowRoot?.activeElement ?? null;\n }\n return activeElement;\n}\n\nfunction createSyntheticBlurHandler(): (\n _e: FocusEvent,\n target: Element,\n) => (() => void) | undefined {\n let isFocused = false;\n let observer: MutationObserver | null = null;\n\n return (_e: FocusEvent, target: Element) => {\n if (\n target instanceof HTMLButtonElement ||\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement\n ) {\n isFocused = true;\n\n const onBlurHandler = () => {\n isFocused = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n\n target.addEventListener(\"focusout\", onBlurHandler, { once: true });\n\n observer = new MutationObserver(() => {\n if (isFocused && (target as HTMLButtonElement).disabled) {\n isFocused = false;\n observer?.disconnect();\n observer = null;\n const ownerDocument = target.ownerDocument;\n const relatedTarget =\n target === ownerDocument.activeElement ? null : ownerDocument.activeElement;\n target.dispatchEvent(new FocusEvent(\"blur\", { relatedTarget }));\n target.dispatchEvent(new FocusEvent(\"focusout\", { bubbles: true, relatedTarget }));\n }\n });\n\n observer.observe(target, { attributes: true, attributeFilter: [\"disabled\"] });\n\n return () => {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n }\n\n return undefined;\n };\n}\n\n/**\n * Handles focus events for the target and its descendants.\n *\n * Based on react-aria's useFocusWithin but adapted for SolidJS.\n */\nexport function createFocusWithin(props: FocusWithinProps = {}): FocusWithinResult {\n const { isDisabled, onBlurWithin, onFocusWithin, onFocusWithinChange } = props;\n\n // State tracking\n let isFocusWithin = false;\n\n // Global listeners manager\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n const syntheticBlurHandler = createSyntheticBlurHandler();\n let cleanupRef: (() => void) | undefined;\n\n // Cleanup on unmount\n onCleanup(() => {\n cleanupRef?.();\n removeAllGlobalListeners();\n });\n\n const onBlur: JSX.EventHandler<HTMLElement, FocusEvent> = (e) => {\n // Ignore events bubbling through portals\n if (!e.currentTarget.contains(e.target as Node)) {\n return;\n }\n\n // We don't want to trigger onBlurWithin and then immediately onFocusWithin again\n // when moving focus inside the element. Only trigger if the currentTarget doesn't\n // include the relatedTarget (where focus is moving).\n if (isFocusWithin && !e.currentTarget.contains(e.relatedTarget as Node)) {\n isFocusWithin = false;\n removeAllGlobalListeners();\n cleanupRef?.();\n cleanupRef = undefined;\n\n if (onBlurWithin) {\n onBlurWithin(e);\n }\n\n if (onFocusWithinChange) {\n onFocusWithinChange(false);\n }\n }\n };\n\n const onFocus: JSX.EventHandler<HTMLElement, FocusEvent> = (e) => {\n // Ignore events bubbling through portals\n if (!e.currentTarget.contains(e.target as Node)) {\n return;\n }\n\n // Double check that document.activeElement actually matches e.target\n // in case a previously chained focus handler already moved focus somewhere else.\n const ownerDocument = getOwnerDocument(e.target);\n const activeElement = ownerDocument ? getActiveElement(ownerDocument) : null;\n\n if (!isFocusWithin && activeElement === getEventTarget(e)) {\n if (onFocusWithin) {\n onFocusWithin(e);\n }\n\n if (onFocusWithinChange) {\n onFocusWithinChange(true);\n }\n\n isFocusWithin = true;\n cleanupRef = syntheticBlurHandler(e, e.target);\n\n // Browsers don't fire blur events when elements are removed from the DOM.\n // However, if a focus event occurs outside the element we're tracking, we\n // can manually fire onBlur.\n const currentTarget = e.currentTarget;\n\n addGlobalListener(\n \"focus\",\n (focusEvent: Event) => {\n if (\n isFocusWithin &&\n !nodeContains(currentTarget, (focusEvent as FocusEvent).target as Element)\n ) {\n // Create a synthetic blur event\n const window = ownerDocument?.defaultView;\n if (window) {\n const nativeEvent = new window.FocusEvent(\"blur\", {\n relatedTarget: (focusEvent as FocusEvent).target as Element,\n });\n setEventTarget(nativeEvent, currentTarget);\n\n isFocusWithin = false;\n removeAllGlobalListeners();\n\n if (onBlurWithin) {\n onBlurWithin(nativeEvent);\n }\n\n if (onFocusWithinChange) {\n onFocusWithinChange(false);\n }\n cleanupRef?.();\n cleanupRef = undefined;\n }\n }\n },\n { capture: true },\n );\n }\n };\n\n if (isDisabled) {\n return {\n focusWithinProps: {\n onFocus: undefined,\n onBlur: undefined,\n },\n };\n }\n\n return {\n focusWithinProps: {\n onFocus,\n onBlur,\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createFocusWithin.jsx","names":[],"sources":["../../src/interactions/createFocusWithin.ts"],"sourcesContent":["/**\n * createFocusWithin - Handles focus events for the target and its descendants.\n *\n * This is a 1-1 port of React-Aria's useFocusWithin hook adapted for SolidJS.\n */\n\nimport { JSX, onCleanup } from \"solid-js\";\nimport { getOwnerDocument, getEventTarget, nodeContains, createGlobalListeners } from \"../utils\";\nimport { setEventTarget } from \"../utils/events\";\n\nexport interface FocusWithinProps {\n /** Whether the focus within events should be disabled. */\n isDisabled?: boolean;\n /** Handler that is called when the target element or a descendant receives focus. */\n onFocusWithin?: (e: FocusEvent) => void;\n /** Handler that is called when the target element and all descendants lose focus. */\n onBlurWithin?: (e: FocusEvent) => void;\n /** Handler that is called when the focus within state changes. */\n onFocusWithinChange?: (isFocusWithin: boolean) => void;\n}\n\nexport interface FocusWithinResult {\n /** Props to spread onto the target element. */\n focusWithinProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\nfunction getActiveElement(doc: Document): Element | null {\n let activeElement = doc.activeElement;\n while (activeElement && (activeElement as Element).shadowRoot?.activeElement) {\n activeElement = (activeElement as Element).shadowRoot?.activeElement ?? null;\n }\n return activeElement;\n}\n\nfunction createSyntheticBlurHandler(): (\n _e: FocusEvent,\n target: Element,\n) => (() => void) | undefined {\n let isFocused = false;\n let observer: MutationObserver | null = null;\n\n return (_e: FocusEvent, target: Element) => {\n if (\n target instanceof HTMLButtonElement ||\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement\n ) {\n isFocused = true;\n\n const onBlurHandler = () => {\n isFocused = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n\n target.addEventListener(\"focusout\", onBlurHandler, { once: true });\n\n observer = new MutationObserver(() => {\n if (isFocused && (target as HTMLButtonElement).disabled) {\n isFocused = false;\n observer?.disconnect();\n observer = null;\n const ownerDocument = target.ownerDocument;\n const relatedTarget =\n target === ownerDocument.activeElement ? null : ownerDocument.activeElement;\n target.dispatchEvent(new FocusEvent(\"blur\", { relatedTarget }));\n target.dispatchEvent(new FocusEvent(\"focusout\", { bubbles: true, relatedTarget }));\n }\n });\n\n observer.observe(target, { attributes: true, attributeFilter: [\"disabled\"] });\n\n return () => {\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n };\n }\n\n return undefined;\n };\n}\n\n/**\n * Handles focus events for the target and its descendants.\n *\n * Based on react-aria's useFocusWithin but adapted for SolidJS.\n */\nexport function createFocusWithin(props: FocusWithinProps = {}): FocusWithinResult {\n // Read isDisabled/handlers off `props` directly (not via destructure): a Solid\n // hook body runs once, so destructuring would freeze them at call time and drop\n // reactive updates — createOverlay/createVisuallyHidden pass a live isDisabled\n // getter. The handlers below read props.x live; the return is getter-based so a\n // later isDisabled flip re-computes. Mirrors upstream useFocusWithin's re-read.\n\n // State tracking\n let isFocusWithin = false;\n\n // Global listeners manager\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n const syntheticBlurHandler = createSyntheticBlurHandler();\n let cleanupRef: (() => void) | undefined;\n\n // Cleanup on unmount\n onCleanup(() => {\n cleanupRef?.();\n removeAllGlobalListeners();\n });\n\n const onBlur: JSX.EventHandler<HTMLElement, FocusEvent> = (e) => {\n // Ignore events bubbling through portals\n if (!e.currentTarget.contains(e.target as Node)) {\n return;\n }\n\n // We don't want to trigger onBlurWithin and then immediately onFocusWithin again\n // when moving focus inside the element. Only trigger if the currentTarget doesn't\n // include the relatedTarget (where focus is moving).\n if (isFocusWithin && !e.currentTarget.contains(e.relatedTarget as Node)) {\n isFocusWithin = false;\n removeAllGlobalListeners();\n cleanupRef?.();\n cleanupRef = undefined;\n\n if (props.onBlurWithin) {\n props.onBlurWithin(e);\n }\n\n if (props.onFocusWithinChange) {\n props.onFocusWithinChange(false);\n }\n }\n };\n\n const onFocus: JSX.EventHandler<HTMLElement, FocusEvent> = (e) => {\n // Ignore events bubbling through portals\n if (!e.currentTarget.contains(e.target as Node)) {\n return;\n }\n\n // Double check that document.activeElement actually matches e.target\n // in case a previously chained focus handler already moved focus somewhere else.\n const ownerDocument = getOwnerDocument(e.target);\n const activeElement = ownerDocument ? getActiveElement(ownerDocument) : null;\n\n if (!isFocusWithin && activeElement === getEventTarget(e)) {\n if (props.onFocusWithin) {\n props.onFocusWithin(e);\n }\n\n if (props.onFocusWithinChange) {\n props.onFocusWithinChange(true);\n }\n\n isFocusWithin = true;\n cleanupRef = syntheticBlurHandler(e, e.target);\n\n // Browsers don't fire blur events when elements are removed from the DOM.\n // However, if a focus event occurs outside the element we're tracking, we\n // can manually fire onBlur.\n const currentTarget = e.currentTarget;\n\n addGlobalListener(\n \"focus\",\n (focusEvent: Event) => {\n if (\n isFocusWithin &&\n !nodeContains(currentTarget, (focusEvent as FocusEvent).target as Element)\n ) {\n // Create a synthetic blur event\n const window = ownerDocument?.defaultView;\n if (window) {\n const nativeEvent = new window.FocusEvent(\"blur\", {\n relatedTarget: (focusEvent as FocusEvent).target as Element,\n });\n setEventTarget(nativeEvent, currentTarget);\n\n isFocusWithin = false;\n removeAllGlobalListeners();\n\n if (props.onBlurWithin) {\n props.onBlurWithin(nativeEvent);\n }\n\n if (props.onFocusWithinChange) {\n props.onFocusWithinChange(false);\n }\n cleanupRef?.();\n cleanupRef = undefined;\n }\n }\n },\n { capture: true },\n );\n }\n };\n\n return {\n focusWithinProps: {\n get onFocus() {\n return props.isDisabled ? undefined : onFocus;\n },\n get onBlur() {\n return props.isDisabled ? undefined : onBlur;\n },\n },\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { o as mergeProps } from "./env.js";
1
+ import { i as mergeProps$1 } from "./env.js";
2
2
  import { t as focusSafely } from "./focus.js";
3
3
  import { t as createFocus } from "./createFocus.js";
4
4
  import { createContext, onMount, useContext } from "solid-js";
@@ -107,7 +107,7 @@ function createFocusable(props = {}, ref) {
107
107
  onKeyDown: props.onKeyDown,
108
108
  onKeyUp: props.onKeyUp
109
109
  });
110
- const interactions = mergeProps(focusProps, keyboardProps);
110
+ const interactions = mergeProps$1(focusProps, keyboardProps);
111
111
  const contextProps = useFocusableContext(setRef);
112
112
  const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;
113
113
  onMount(() => {
@@ -116,7 +116,7 @@ function createFocusable(props = {}, ref) {
116
116
  autoFocusDone = true;
117
117
  }
118
118
  });
119
- return { focusableProps: mergeProps({
119
+ return { focusableProps: mergeProps$1({
120
120
  ...interactions,
121
121
  get tabIndex() {
122
122
  if (isDisabledValue(props.isDisabled)) return;
@@ -1 +1 @@
1
- {"version":3,"file":"createFocusable.js","names":[],"sources":["../../src/interactions/createKeyboard.ts","../../src/interactions/createFocusable.ts"],"sourcesContent":["/**\n * createKeyboard - Handles keyboard interactions for a focusable element.\n *\n * This is a 1-1 port of React-Aria's useKeyboard hook adapted for SolidJS.\n */\n\nimport { JSX } from \"solid-js\";\n\n/**\n * Keyboard event with continuePropagation support.\n * By default, keyboard events stop propagation.\n */\nexport interface KeyboardEvent extends globalThis.KeyboardEvent {\n /** Call this to allow the event to propagate to parent elements. */\n continuePropagation(): void;\n}\n\nexport interface KeyboardEvents {\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: KeyboardEvent) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: KeyboardEvent) => void;\n}\n\nexport interface CreateKeyboardProps extends KeyboardEvents {\n /** Whether the keyboard events should be disabled. */\n isDisabled?: boolean;\n}\n\nexport interface KeyboardResult {\n /** Props to spread onto the target element. */\n keyboardProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n/**\n * Wraps a keyboard event handler to make stopPropagation the default,\n * and support continuePropagation instead.\n */\nfunction createEventHandler<T extends globalThis.KeyboardEvent>(\n handler?: (e: KeyboardEvent) => void,\n): ((e: T) => void) | undefined {\n if (!handler) {\n return undefined;\n }\n\n return (e: T) => {\n let shouldStopPropagation = true;\n\n // A nested createEventHandler may already have installed continuePropagation\n // on this event; capture it so continuing here continues on the wrapper too.\n const parentContinuePropagation = (e as { continuePropagation?: () => void })\n .continuePropagation;\n\n // Create a wrapped event with continuePropagation\n const event = Object.assign(e, {\n continuePropagation() {\n shouldStopPropagation = false;\n // Nested createEventHandler might have set continuePropagation, so we\n // should continue propagation on the wrappers too.\n if (typeof parentContinuePropagation === \"function\") {\n parentContinuePropagation.call(e);\n }\n },\n }) as KeyboardEvent;\n\n handler(event);\n\n if (shouldStopPropagation) {\n e.stopPropagation();\n }\n };\n}\n\n/**\n * Handles keyboard interactions for a focusable element.\n *\n * Based on react-aria's useKeyboard but adapted for SolidJS.\n */\nexport function createKeyboard(props: CreateKeyboardProps = {}): KeyboardResult {\n if (props.isDisabled) {\n return {\n keyboardProps: {},\n };\n }\n\n return {\n keyboardProps: {\n onKeyDown: createEventHandler(props.onKeyDown),\n onKeyUp: createEventHandler(props.onKeyUp),\n },\n };\n}\n","/**\n * createFocusable - Makes an element focusable and capable of auto focus.\n *\n * This is a 1-1 port of React-Aria's useFocusable hook adapted for SolidJS.\n */\n\nimport { JSX, Accessor, createContext, useContext, onMount } from \"solid-js\";\nimport { createFocus, type FocusEvents } from \"./createFocus\";\nimport { createKeyboard, type KeyboardEvents } from \"./createKeyboard\";\nimport { mergeProps, focusSafely } from \"../utils\";\n\nexport interface FocusableDOMProps {\n /** Whether to exclude the element from the sequential tab order. */\n excludeFromTabOrder?: boolean;\n}\n\nexport interface FocusableProps extends FocusEvents, KeyboardEvents {\n /** Whether the element should receive focus on mount. */\n autoFocus?: boolean;\n}\n\nexport interface CreateFocusableProps extends FocusableProps, FocusableDOMProps {\n /** Whether focus should be disabled. */\n isDisabled?: Accessor<boolean> | boolean;\n}\n\nexport interface FocusableResult {\n /** Props to spread on the focusable element. */\n focusableProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n// --- FocusableContext ---\n\nexport interface FocusableContextValue {\n ref?: (el: HTMLElement) => void;\n [key: string]: unknown;\n}\n\n/**\n * Context for passing focusable props to nested focusable children.\n * Used by FocusableProvider to pass DOM props to the nearest focusable child.\n */\nexport const FocusableContext = createContext<FocusableContextValue | null>(null);\n\n/**\n * Hook to consume the FocusableContext and sync the ref.\n */\nfunction useFocusableContext(\n setRef: (el: HTMLElement) => void,\n): Omit<FocusableContextValue, \"ref\"> {\n const context = useContext(FocusableContext) || {};\n\n // If context has a ref, sync our ref to it\n if (context.ref) {\n const contextRef = context.ref;\n // Create a combined ref that calls both\n const originalSetRef = setRef;\n setRef = (el: HTMLElement) => {\n originalSetRef(el);\n contextRef(el);\n };\n }\n\n // Return context without the ref\n const { ref: _, ...otherProps } = context;\n return otherProps;\n}\n\nexport interface FocusableProviderProps {\n /** The child element to provide DOM props to. */\n children?: JSX.Element;\n}\n\nfunction isDisabledValue(isDisabled: Accessor<boolean> | boolean | undefined): boolean {\n if (typeof isDisabled === \"function\") {\n return isDisabled();\n }\n return isDisabled ?? false;\n}\n\n/**\n * Makes an element focusable, handling disabled state and tab order.\n * Provides focus state tracking and autoFocus support.\n *\n * Based on react-aria's useFocusable but adapted for SolidJS.\n *\n * @example\n * ```tsx\n * import { createFocusable } from 'solidaria';\n *\n * function FocusableInput(props) {\n * let ref;\n * const { focusableProps } = createFocusable({\n * autoFocus: props.autoFocus,\n * onFocusChange: (focused) => console.log('Focus:', focused),\n * });\n *\n * return (\n * <input\n * {...focusableProps}\n * ref={(el) => { ref = el; focusableProps.ref?.(el); }}\n * />\n * );\n * }\n * ```\n */\nexport function createFocusable(\n props: CreateFocusableProps = {},\n ref?: (el: HTMLElement) => void,\n): FocusableResult {\n let elementRef: HTMLElement | null = null;\n let autoFocusDone = false;\n\n // Set up ref handler\n const setRef = (el: HTMLElement) => {\n elementRef = el;\n ref?.(el);\n };\n\n // Get focus and keyboard props from the respective hooks\n const { focusProps } = createFocus({\n isDisabled: isDisabledValue(props.isDisabled),\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n onFocusChange: props.onFocusChange,\n });\n\n const { keyboardProps } = createKeyboard({\n isDisabled: isDisabledValue(props.isDisabled),\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n });\n\n // Merge focus and keyboard interactions\n const interactions = mergeProps(focusProps, keyboardProps);\n\n // Get context props (from FocusableProvider if present)\n const contextProps = useFocusableContext(setRef);\n const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;\n\n // Handle autoFocus\n onMount(() => {\n if (props.autoFocus && elementRef && !autoFocusDone) {\n focusSafely(elementRef);\n autoFocusDone = true;\n }\n });\n\n // Build final focusable props\n const focusableProps = mergeProps(\n {\n ...interactions,\n get tabIndex() {\n if (isDisabledValue(props.isDisabled)) {\n return undefined;\n }\n return props.excludeFromTabOrder ? -1 : 0;\n },\n ref: setRef,\n },\n interactionProps,\n ) as JSX.HTMLAttributes<HTMLElement>;\n\n return {\n focusableProps,\n };\n}\n"],"mappings":";;;;;;;;;AAsCA,SAAS,mBACP,SAC8B;CAC9B,IAAI,CAAC,SACH;CAGF,QAAQ,MAAS;EACf,IAAI,wBAAwB;EAI5B,MAAM,4BAA6B,EAChC;EAcH,QAXc,OAAO,OAAO,GAAG,EAC7B,sBAAsB;GACpB,wBAAwB;GAGxB,IAAI,OAAO,8BAA8B,YACvC,0BAA0B,KAAK,CAAC;EAEpC,EACF,CAEY,CAAC;EAEb,IAAI,uBACF,EAAE,gBAAgB;CAEtB;AACF;;;;;;AAOA,SAAgB,eAAe,QAA6B,CAAC,GAAmB;CAC9E,IAAI,MAAM,YACR,OAAO,EACL,eAAe,CAAC,EAClB;CAGF,OAAO,EACL,eAAe;EACb,WAAW,mBAAmB,MAAM,SAAS;EAC7C,SAAS,mBAAmB,MAAM,OAAO;CAC3C,EACF;AACF;;;;;;;;;;;;ACjDA,MAAa,mBAAmB,cAA4C,IAAI;;;;AAKhF,SAAS,oBACP,QACoC;CACpC,MAAM,UAAU,WAAW,gBAAgB,KAAK,CAAC;CAGjD,IAAI,QAAQ,KAAK;EACf,MAAM,aAAa,QAAQ;EAE3B,MAAM,iBAAiB;EACvB,UAAU,OAAoB;GAC5B,eAAe,EAAE;GACjB,WAAW,EAAE;EACf;CACF;CAGA,MAAM,EAAE,KAAK,GAAG,GAAG,eAAe;CAClC,OAAO;AACT;AAOA,SAAS,gBAAgB,YAA8D;CACrF,IAAI,OAAO,eAAe,YACxB,OAAO,WAAW;CAEpB,OAAO,cAAc;AACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,QAA8B,CAAC,GAC/B,KACiB;CACjB,IAAI,aAAiC;CACrC,IAAI,gBAAgB;CAGpB,MAAM,UAAU,OAAoB;EAClC,aAAa;EACb,MAAM,EAAE;CACV;CAGA,MAAM,EAAE,eAAe,YAAY;EACjC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,eAAe,MAAM;CACvB,CAAC;CAED,MAAM,EAAE,kBAAkB,eAAe;EACvC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,WAAW,MAAM;EACjB,SAAS,MAAM;CACjB,CAAC;CAGD,MAAM,eAAe,WAAW,YAAY,aAAa;CAGzD,MAAM,eAAe,oBAAoB,MAAM;CAC/C,MAAM,mBAAmB,gBAAgB,MAAM,UAAU,IAAI,CAAC,IAAI;CAGlE,cAAc;EACZ,IAAI,MAAM,aAAa,cAAc,CAAC,eAAe;GACnD,YAAY,UAAU;GACtB,gBAAgB;EAClB;CACF,CAAC;CAiBD,OAAO,EACL,gBAfqB,WACrB;EACE,GAAG;EACH,IAAI,WAAW;GACb,IAAI,gBAAgB,MAAM,UAAU,GAClC;GAEF,OAAO,MAAM,sBAAsB,KAAK;EAC1C;EACA,KAAK;CACP,GACA,gBAIa,EACf;AACF"}
1
+ {"version":3,"file":"createFocusable.js","names":["mergeProps"],"sources":["../../src/interactions/createKeyboard.ts","../../src/interactions/createFocusable.ts"],"sourcesContent":["/**\n * createKeyboard - Handles keyboard interactions for a focusable element.\n *\n * This is a 1-1 port of React-Aria's useKeyboard hook adapted for SolidJS.\n */\n\nimport { JSX } from \"solid-js\";\n\n/**\n * Keyboard event with continuePropagation support.\n * By default, keyboard events stop propagation.\n */\nexport interface KeyboardEvent extends globalThis.KeyboardEvent {\n /** Call this to allow the event to propagate to parent elements. */\n continuePropagation(): void;\n}\n\nexport interface KeyboardEvents {\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: KeyboardEvent) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: KeyboardEvent) => void;\n}\n\nexport interface CreateKeyboardProps extends KeyboardEvents {\n /** Whether the keyboard events should be disabled. */\n isDisabled?: boolean;\n}\n\nexport interface KeyboardResult {\n /** Props to spread onto the target element. */\n keyboardProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n/**\n * Wraps a keyboard event handler to make stopPropagation the default,\n * and support continuePropagation instead.\n */\nfunction createEventHandler<T extends globalThis.KeyboardEvent>(\n handler?: (e: KeyboardEvent) => void,\n): ((e: T) => void) | undefined {\n if (!handler) {\n return undefined;\n }\n\n return (e: T) => {\n let shouldStopPropagation = true;\n\n // A nested createEventHandler may already have installed continuePropagation\n // on this event; capture it so continuing here continues on the wrapper too.\n const parentContinuePropagation = (e as { continuePropagation?: () => void })\n .continuePropagation;\n\n // Create a wrapped event with continuePropagation\n const event = Object.assign(e, {\n continuePropagation() {\n shouldStopPropagation = false;\n // Nested createEventHandler might have set continuePropagation, so we\n // should continue propagation on the wrappers too.\n if (typeof parentContinuePropagation === \"function\") {\n parentContinuePropagation.call(e);\n }\n },\n }) as KeyboardEvent;\n\n handler(event);\n\n if (shouldStopPropagation) {\n e.stopPropagation();\n }\n };\n}\n\n/**\n * Handles keyboard interactions for a focusable element.\n *\n * Based on react-aria's useKeyboard but adapted for SolidJS.\n */\nexport function createKeyboard(props: CreateKeyboardProps = {}): KeyboardResult {\n if (props.isDisabled) {\n return {\n keyboardProps: {},\n };\n }\n\n return {\n keyboardProps: {\n onKeyDown: createEventHandler(props.onKeyDown),\n onKeyUp: createEventHandler(props.onKeyUp),\n },\n };\n}\n","/**\n * createFocusable - Makes an element focusable and capable of auto focus.\n *\n * This is a 1-1 port of React-Aria's useFocusable hook adapted for SolidJS.\n */\n\nimport { JSX, Accessor, createContext, useContext, onMount } from \"solid-js\";\nimport { createFocus, type FocusEvents } from \"./createFocus\";\nimport { createKeyboard, type KeyboardEvents } from \"./createKeyboard\";\nimport { mergeProps, focusSafely } from \"../utils\";\n\nexport interface FocusableDOMProps {\n /** Whether to exclude the element from the sequential tab order. */\n excludeFromTabOrder?: boolean;\n}\n\nexport interface FocusableProps extends FocusEvents, KeyboardEvents {\n /** Whether the element should receive focus on mount. */\n autoFocus?: boolean;\n}\n\nexport interface CreateFocusableProps extends FocusableProps, FocusableDOMProps {\n /** Whether focus should be disabled. */\n isDisabled?: Accessor<boolean> | boolean;\n}\n\nexport interface FocusableResult {\n /** Props to spread on the focusable element. */\n focusableProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n// --- FocusableContext ---\n\nexport interface FocusableContextValue {\n ref?: (el: HTMLElement) => void;\n [key: string]: unknown;\n}\n\n/**\n * Context for passing focusable props to nested focusable children.\n * Used by FocusableProvider to pass DOM props to the nearest focusable child.\n */\nexport const FocusableContext = createContext<FocusableContextValue | null>(null);\n\n/**\n * Hook to consume the FocusableContext and sync the ref.\n */\nfunction useFocusableContext(\n setRef: (el: HTMLElement) => void,\n): Omit<FocusableContextValue, \"ref\"> {\n const context = useContext(FocusableContext) || {};\n\n // If context has a ref, sync our ref to it\n if (context.ref) {\n const contextRef = context.ref;\n // Create a combined ref that calls both\n const originalSetRef = setRef;\n setRef = (el: HTMLElement) => {\n originalSetRef(el);\n contextRef(el);\n };\n }\n\n // Return context without the ref\n const { ref: _, ...otherProps } = context;\n return otherProps;\n}\n\nexport interface FocusableProviderProps {\n /** The child element to provide DOM props to. */\n children?: JSX.Element;\n}\n\nfunction isDisabledValue(isDisabled: Accessor<boolean> | boolean | undefined): boolean {\n if (typeof isDisabled === \"function\") {\n return isDisabled();\n }\n return isDisabled ?? false;\n}\n\n/**\n * Makes an element focusable, handling disabled state and tab order.\n * Provides focus state tracking and autoFocus support.\n *\n * Based on react-aria's useFocusable but adapted for SolidJS.\n *\n * @example\n * ```tsx\n * import { createFocusable } from 'solidaria';\n *\n * function FocusableInput(props) {\n * let ref;\n * const { focusableProps } = createFocusable({\n * autoFocus: props.autoFocus,\n * onFocusChange: (focused) => console.log('Focus:', focused),\n * });\n *\n * return (\n * <input\n * {...focusableProps}\n * ref={(el) => { ref = el; focusableProps.ref?.(el); }}\n * />\n * );\n * }\n * ```\n */\nexport function createFocusable(\n props: CreateFocusableProps = {},\n ref?: (el: HTMLElement) => void,\n): FocusableResult {\n let elementRef: HTMLElement | null = null;\n let autoFocusDone = false;\n\n // Set up ref handler\n const setRef = (el: HTMLElement) => {\n elementRef = el;\n ref?.(el);\n };\n\n // Get focus and keyboard props from the respective hooks\n const { focusProps } = createFocus({\n isDisabled: isDisabledValue(props.isDisabled),\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n onFocusChange: props.onFocusChange,\n });\n\n const { keyboardProps } = createKeyboard({\n isDisabled: isDisabledValue(props.isDisabled),\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n });\n\n // Merge focus and keyboard interactions\n const interactions = mergeProps(focusProps, keyboardProps);\n\n // Get context props (from FocusableProvider if present)\n const contextProps = useFocusableContext(setRef);\n const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;\n\n // Handle autoFocus\n onMount(() => {\n if (props.autoFocus && elementRef && !autoFocusDone) {\n focusSafely(elementRef);\n autoFocusDone = true;\n }\n });\n\n // Build final focusable props\n const focusableProps = mergeProps(\n {\n ...interactions,\n get tabIndex() {\n if (isDisabledValue(props.isDisabled)) {\n return undefined;\n }\n return props.excludeFromTabOrder ? -1 : 0;\n },\n ref: setRef,\n },\n interactionProps,\n ) as JSX.HTMLAttributes<HTMLElement>;\n\n return {\n focusableProps,\n };\n}\n"],"mappings":";;;;;;;;;AAsCA,SAAS,mBACP,SAC8B;CAC9B,IAAI,CAAC,SACH;CAGF,QAAQ,MAAS;EACf,IAAI,wBAAwB;EAI5B,MAAM,4BAA6B,EAChC;EAcH,QAXc,OAAO,OAAO,GAAG,EAC7B,sBAAsB;GACpB,wBAAwB;GAGxB,IAAI,OAAO,8BAA8B,YACvC,0BAA0B,KAAK,CAAC;EAEpC,EACF,CAEY,CAAC;EAEb,IAAI,uBACF,EAAE,gBAAgB;CAEtB;AACF;;;;;;AAOA,SAAgB,eAAe,QAA6B,CAAC,GAAmB;CAC9E,IAAI,MAAM,YACR,OAAO,EACL,eAAe,CAAC,EAClB;CAGF,OAAO,EACL,eAAe;EACb,WAAW,mBAAmB,MAAM,SAAS;EAC7C,SAAS,mBAAmB,MAAM,OAAO;CAC3C,EACF;AACF;;;;;;;;;;;;ACjDA,MAAa,mBAAmB,cAA4C,IAAI;;;;AAKhF,SAAS,oBACP,QACoC;CACpC,MAAM,UAAU,WAAW,gBAAgB,KAAK,CAAC;CAGjD,IAAI,QAAQ,KAAK;EACf,MAAM,aAAa,QAAQ;EAE3B,MAAM,iBAAiB;EACvB,UAAU,OAAoB;GAC5B,eAAe,EAAE;GACjB,WAAW,EAAE;EACf;CACF;CAGA,MAAM,EAAE,KAAK,GAAG,GAAG,eAAe;CAClC,OAAO;AACT;AAOA,SAAS,gBAAgB,YAA8D;CACrF,IAAI,OAAO,eAAe,YACxB,OAAO,WAAW;CAEpB,OAAO,cAAc;AACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,QAA8B,CAAC,GAC/B,KACiB;CACjB,IAAI,aAAiC;CACrC,IAAI,gBAAgB;CAGpB,MAAM,UAAU,OAAoB;EAClC,aAAa;EACb,MAAM,EAAE;CACV;CAGA,MAAM,EAAE,eAAe,YAAY;EACjC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,eAAe,MAAM;CACvB,CAAC;CAED,MAAM,EAAE,kBAAkB,eAAe;EACvC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,WAAW,MAAM;EACjB,SAAS,MAAM;CACjB,CAAC;CAGD,MAAM,eAAeA,aAAW,YAAY,aAAa;CAGzD,MAAM,eAAe,oBAAoB,MAAM;CAC/C,MAAM,mBAAmB,gBAAgB,MAAM,UAAU,IAAI,CAAC,IAAI;CAGlE,cAAc;EACZ,IAAI,MAAM,aAAa,cAAc,CAAC,eAAe;GACnD,YAAY,UAAU;GACtB,gBAAgB;EAClB;CACF,CAAC;CAiBD,OAAO,EACL,gBAfqBA,aACrB;EACE,GAAG;EACH,IAAI,WAAW;GACb,IAAI,gBAAgB,MAAM,UAAU,GAClC;GAEF,OAAO,MAAM,sBAAsB,KAAK;EAC1C;EACA,KAAK;CACP,GACA,gBAIa,EACf;AACF"}
@@ -1,4 +1,4 @@
1
- import { o as mergeProps } from "./env.jsx";
1
+ import { i as mergeProps$1 } from "./env.jsx";
2
2
  import { t as focusSafely } from "./focus.jsx";
3
3
  import { t as createFocus } from "./createFocus.jsx";
4
4
  import { createContext, onMount, useContext } from "solid-js";
@@ -107,7 +107,7 @@ function createFocusable(props = {}, ref) {
107
107
  onKeyDown: props.onKeyDown,
108
108
  onKeyUp: props.onKeyUp
109
109
  });
110
- const interactions = mergeProps(focusProps, keyboardProps);
110
+ const interactions = mergeProps$1(focusProps, keyboardProps);
111
111
  const contextProps = useFocusableContext(setRef);
112
112
  const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;
113
113
  onMount(() => {
@@ -116,7 +116,7 @@ function createFocusable(props = {}, ref) {
116
116
  autoFocusDone = true;
117
117
  }
118
118
  });
119
- return { focusableProps: mergeProps({
119
+ return { focusableProps: mergeProps$1({
120
120
  ...interactions,
121
121
  get tabIndex() {
122
122
  if (isDisabledValue(props.isDisabled)) return;
@@ -1 +1 @@
1
- {"version":3,"file":"createFocusable.jsx","names":[],"sources":["../../src/interactions/createKeyboard.ts","../../src/interactions/createFocusable.ts"],"sourcesContent":["/**\n * createKeyboard - Handles keyboard interactions for a focusable element.\n *\n * This is a 1-1 port of React-Aria's useKeyboard hook adapted for SolidJS.\n */\n\nimport { JSX } from \"solid-js\";\n\n/**\n * Keyboard event with continuePropagation support.\n * By default, keyboard events stop propagation.\n */\nexport interface KeyboardEvent extends globalThis.KeyboardEvent {\n /** Call this to allow the event to propagate to parent elements. */\n continuePropagation(): void;\n}\n\nexport interface KeyboardEvents {\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: KeyboardEvent) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: KeyboardEvent) => void;\n}\n\nexport interface CreateKeyboardProps extends KeyboardEvents {\n /** Whether the keyboard events should be disabled. */\n isDisabled?: boolean;\n}\n\nexport interface KeyboardResult {\n /** Props to spread onto the target element. */\n keyboardProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n/**\n * Wraps a keyboard event handler to make stopPropagation the default,\n * and support continuePropagation instead.\n */\nfunction createEventHandler<T extends globalThis.KeyboardEvent>(\n handler?: (e: KeyboardEvent) => void,\n): ((e: T) => void) | undefined {\n if (!handler) {\n return undefined;\n }\n\n return (e: T) => {\n let shouldStopPropagation = true;\n\n // A nested createEventHandler may already have installed continuePropagation\n // on this event; capture it so continuing here continues on the wrapper too.\n const parentContinuePropagation = (e as { continuePropagation?: () => void })\n .continuePropagation;\n\n // Create a wrapped event with continuePropagation\n const event = Object.assign(e, {\n continuePropagation() {\n shouldStopPropagation = false;\n // Nested createEventHandler might have set continuePropagation, so we\n // should continue propagation on the wrappers too.\n if (typeof parentContinuePropagation === \"function\") {\n parentContinuePropagation.call(e);\n }\n },\n }) as KeyboardEvent;\n\n handler(event);\n\n if (shouldStopPropagation) {\n e.stopPropagation();\n }\n };\n}\n\n/**\n * Handles keyboard interactions for a focusable element.\n *\n * Based on react-aria's useKeyboard but adapted for SolidJS.\n */\nexport function createKeyboard(props: CreateKeyboardProps = {}): KeyboardResult {\n if (props.isDisabled) {\n return {\n keyboardProps: {},\n };\n }\n\n return {\n keyboardProps: {\n onKeyDown: createEventHandler(props.onKeyDown),\n onKeyUp: createEventHandler(props.onKeyUp),\n },\n };\n}\n","/**\n * createFocusable - Makes an element focusable and capable of auto focus.\n *\n * This is a 1-1 port of React-Aria's useFocusable hook adapted for SolidJS.\n */\n\nimport { JSX, Accessor, createContext, useContext, onMount } from \"solid-js\";\nimport { createFocus, type FocusEvents } from \"./createFocus\";\nimport { createKeyboard, type KeyboardEvents } from \"./createKeyboard\";\nimport { mergeProps, focusSafely } from \"../utils\";\n\nexport interface FocusableDOMProps {\n /** Whether to exclude the element from the sequential tab order. */\n excludeFromTabOrder?: boolean;\n}\n\nexport interface FocusableProps extends FocusEvents, KeyboardEvents {\n /** Whether the element should receive focus on mount. */\n autoFocus?: boolean;\n}\n\nexport interface CreateFocusableProps extends FocusableProps, FocusableDOMProps {\n /** Whether focus should be disabled. */\n isDisabled?: Accessor<boolean> | boolean;\n}\n\nexport interface FocusableResult {\n /** Props to spread on the focusable element. */\n focusableProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n// --- FocusableContext ---\n\nexport interface FocusableContextValue {\n ref?: (el: HTMLElement) => void;\n [key: string]: unknown;\n}\n\n/**\n * Context for passing focusable props to nested focusable children.\n * Used by FocusableProvider to pass DOM props to the nearest focusable child.\n */\nexport const FocusableContext = createContext<FocusableContextValue | null>(null);\n\n/**\n * Hook to consume the FocusableContext and sync the ref.\n */\nfunction useFocusableContext(\n setRef: (el: HTMLElement) => void,\n): Omit<FocusableContextValue, \"ref\"> {\n const context = useContext(FocusableContext) || {};\n\n // If context has a ref, sync our ref to it\n if (context.ref) {\n const contextRef = context.ref;\n // Create a combined ref that calls both\n const originalSetRef = setRef;\n setRef = (el: HTMLElement) => {\n originalSetRef(el);\n contextRef(el);\n };\n }\n\n // Return context without the ref\n const { ref: _, ...otherProps } = context;\n return otherProps;\n}\n\nexport interface FocusableProviderProps {\n /** The child element to provide DOM props to. */\n children?: JSX.Element;\n}\n\nfunction isDisabledValue(isDisabled: Accessor<boolean> | boolean | undefined): boolean {\n if (typeof isDisabled === \"function\") {\n return isDisabled();\n }\n return isDisabled ?? false;\n}\n\n/**\n * Makes an element focusable, handling disabled state and tab order.\n * Provides focus state tracking and autoFocus support.\n *\n * Based on react-aria's useFocusable but adapted for SolidJS.\n *\n * @example\n * ```tsx\n * import { createFocusable } from 'solidaria';\n *\n * function FocusableInput(props) {\n * let ref;\n * const { focusableProps } = createFocusable({\n * autoFocus: props.autoFocus,\n * onFocusChange: (focused) => console.log('Focus:', focused),\n * });\n *\n * return (\n * <input\n * {...focusableProps}\n * ref={(el) => { ref = el; focusableProps.ref?.(el); }}\n * />\n * );\n * }\n * ```\n */\nexport function createFocusable(\n props: CreateFocusableProps = {},\n ref?: (el: HTMLElement) => void,\n): FocusableResult {\n let elementRef: HTMLElement | null = null;\n let autoFocusDone = false;\n\n // Set up ref handler\n const setRef = (el: HTMLElement) => {\n elementRef = el;\n ref?.(el);\n };\n\n // Get focus and keyboard props from the respective hooks\n const { focusProps } = createFocus({\n isDisabled: isDisabledValue(props.isDisabled),\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n onFocusChange: props.onFocusChange,\n });\n\n const { keyboardProps } = createKeyboard({\n isDisabled: isDisabledValue(props.isDisabled),\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n });\n\n // Merge focus and keyboard interactions\n const interactions = mergeProps(focusProps, keyboardProps);\n\n // Get context props (from FocusableProvider if present)\n const contextProps = useFocusableContext(setRef);\n const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;\n\n // Handle autoFocus\n onMount(() => {\n if (props.autoFocus && elementRef && !autoFocusDone) {\n focusSafely(elementRef);\n autoFocusDone = true;\n }\n });\n\n // Build final focusable props\n const focusableProps = mergeProps(\n {\n ...interactions,\n get tabIndex() {\n if (isDisabledValue(props.isDisabled)) {\n return undefined;\n }\n return props.excludeFromTabOrder ? -1 : 0;\n },\n ref: setRef,\n },\n interactionProps,\n ) as JSX.HTMLAttributes<HTMLElement>;\n\n return {\n focusableProps,\n };\n}\n"],"mappings":";;;;;;;;;AAsCA,SAAS,mBACP,SAC8B;CAC9B,IAAI,CAAC,SACH;CAGF,QAAQ,MAAS;EACf,IAAI,wBAAwB;EAI5B,MAAM,4BAA6B,EAChC;EAcH,QAXc,OAAO,OAAO,GAAG,EAC7B,sBAAsB;GACpB,wBAAwB;GAGxB,IAAI,OAAO,8BAA8B,YACvC,0BAA0B,KAAK,CAAC;EAEpC,EACF,CAEY,CAAC;EAEb,IAAI,uBACF,EAAE,gBAAgB;CAEtB;AACF;;;;;;AAOA,SAAgB,eAAe,QAA6B,CAAC,GAAmB;CAC9E,IAAI,MAAM,YACR,OAAO,EACL,eAAe,CAAC,EAClB;CAGF,OAAO,EACL,eAAe;EACb,WAAW,mBAAmB,MAAM,SAAS;EAC7C,SAAS,mBAAmB,MAAM,OAAO;CAC3C,EACF;AACF;;;;;;;;;;;;ACjDA,MAAa,mBAAmB,cAA4C,IAAI;;;;AAKhF,SAAS,oBACP,QACoC;CACpC,MAAM,UAAU,WAAW,gBAAgB,KAAK,CAAC;CAGjD,IAAI,QAAQ,KAAK;EACf,MAAM,aAAa,QAAQ;EAE3B,MAAM,iBAAiB;EACvB,UAAU,OAAoB;GAC5B,eAAe,EAAE;GACjB,WAAW,EAAE;EACf;CACF;CAGA,MAAM,EAAE,KAAK,GAAG,GAAG,eAAe;CAClC,OAAO;AACT;AAOA,SAAS,gBAAgB,YAA8D;CACrF,IAAI,OAAO,eAAe,YACxB,OAAO,WAAW;CAEpB,OAAO,cAAc;AACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,QAA8B,CAAC,GAC/B,KACiB;CACjB,IAAI,aAAiC;CACrC,IAAI,gBAAgB;CAGpB,MAAM,UAAU,OAAoB;EAClC,aAAa;EACb,MAAM,EAAE;CACV;CAGA,MAAM,EAAE,eAAe,YAAY;EACjC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,eAAe,MAAM;CACvB,CAAC;CAED,MAAM,EAAE,kBAAkB,eAAe;EACvC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,WAAW,MAAM;EACjB,SAAS,MAAM;CACjB,CAAC;CAGD,MAAM,eAAe,WAAW,YAAY,aAAa;CAGzD,MAAM,eAAe,oBAAoB,MAAM;CAC/C,MAAM,mBAAmB,gBAAgB,MAAM,UAAU,IAAI,CAAC,IAAI;CAGlE,cAAc;EACZ,IAAI,MAAM,aAAa,cAAc,CAAC,eAAe;GACnD,YAAY,UAAU;GACtB,gBAAgB;EAClB;CACF,CAAC;CAiBD,OAAO,EACL,gBAfqB,WACrB;EACE,GAAG;EACH,IAAI,WAAW;GACb,IAAI,gBAAgB,MAAM,UAAU,GAClC;GAEF,OAAO,MAAM,sBAAsB,KAAK;EAC1C;EACA,KAAK;CACP,GACA,gBAIa,EACf;AACF"}
1
+ {"version":3,"file":"createFocusable.jsx","names":["mergeProps"],"sources":["../../src/interactions/createKeyboard.ts","../../src/interactions/createFocusable.ts"],"sourcesContent":["/**\n * createKeyboard - Handles keyboard interactions for a focusable element.\n *\n * This is a 1-1 port of React-Aria's useKeyboard hook adapted for SolidJS.\n */\n\nimport { JSX } from \"solid-js\";\n\n/**\n * Keyboard event with continuePropagation support.\n * By default, keyboard events stop propagation.\n */\nexport interface KeyboardEvent extends globalThis.KeyboardEvent {\n /** Call this to allow the event to propagate to parent elements. */\n continuePropagation(): void;\n}\n\nexport interface KeyboardEvents {\n /** Handler that is called when a key is pressed. */\n onKeyDown?: (e: KeyboardEvent) => void;\n /** Handler that is called when a key is released. */\n onKeyUp?: (e: KeyboardEvent) => void;\n}\n\nexport interface CreateKeyboardProps extends KeyboardEvents {\n /** Whether the keyboard events should be disabled. */\n isDisabled?: boolean;\n}\n\nexport interface KeyboardResult {\n /** Props to spread onto the target element. */\n keyboardProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n/**\n * Wraps a keyboard event handler to make stopPropagation the default,\n * and support continuePropagation instead.\n */\nfunction createEventHandler<T extends globalThis.KeyboardEvent>(\n handler?: (e: KeyboardEvent) => void,\n): ((e: T) => void) | undefined {\n if (!handler) {\n return undefined;\n }\n\n return (e: T) => {\n let shouldStopPropagation = true;\n\n // A nested createEventHandler may already have installed continuePropagation\n // on this event; capture it so continuing here continues on the wrapper too.\n const parentContinuePropagation = (e as { continuePropagation?: () => void })\n .continuePropagation;\n\n // Create a wrapped event with continuePropagation\n const event = Object.assign(e, {\n continuePropagation() {\n shouldStopPropagation = false;\n // Nested createEventHandler might have set continuePropagation, so we\n // should continue propagation on the wrappers too.\n if (typeof parentContinuePropagation === \"function\") {\n parentContinuePropagation.call(e);\n }\n },\n }) as KeyboardEvent;\n\n handler(event);\n\n if (shouldStopPropagation) {\n e.stopPropagation();\n }\n };\n}\n\n/**\n * Handles keyboard interactions for a focusable element.\n *\n * Based on react-aria's useKeyboard but adapted for SolidJS.\n */\nexport function createKeyboard(props: CreateKeyboardProps = {}): KeyboardResult {\n if (props.isDisabled) {\n return {\n keyboardProps: {},\n };\n }\n\n return {\n keyboardProps: {\n onKeyDown: createEventHandler(props.onKeyDown),\n onKeyUp: createEventHandler(props.onKeyUp),\n },\n };\n}\n","/**\n * createFocusable - Makes an element focusable and capable of auto focus.\n *\n * This is a 1-1 port of React-Aria's useFocusable hook adapted for SolidJS.\n */\n\nimport { JSX, Accessor, createContext, useContext, onMount } from \"solid-js\";\nimport { createFocus, type FocusEvents } from \"./createFocus\";\nimport { createKeyboard, type KeyboardEvents } from \"./createKeyboard\";\nimport { mergeProps, focusSafely } from \"../utils\";\n\nexport interface FocusableDOMProps {\n /** Whether to exclude the element from the sequential tab order. */\n excludeFromTabOrder?: boolean;\n}\n\nexport interface FocusableProps extends FocusEvents, KeyboardEvents {\n /** Whether the element should receive focus on mount. */\n autoFocus?: boolean;\n}\n\nexport interface CreateFocusableProps extends FocusableProps, FocusableDOMProps {\n /** Whether focus should be disabled. */\n isDisabled?: Accessor<boolean> | boolean;\n}\n\nexport interface FocusableResult {\n /** Props to spread on the focusable element. */\n focusableProps: JSX.HTMLAttributes<HTMLElement>;\n}\n\n// --- FocusableContext ---\n\nexport interface FocusableContextValue {\n ref?: (el: HTMLElement) => void;\n [key: string]: unknown;\n}\n\n/**\n * Context for passing focusable props to nested focusable children.\n * Used by FocusableProvider to pass DOM props to the nearest focusable child.\n */\nexport const FocusableContext = createContext<FocusableContextValue | null>(null);\n\n/**\n * Hook to consume the FocusableContext and sync the ref.\n */\nfunction useFocusableContext(\n setRef: (el: HTMLElement) => void,\n): Omit<FocusableContextValue, \"ref\"> {\n const context = useContext(FocusableContext) || {};\n\n // If context has a ref, sync our ref to it\n if (context.ref) {\n const contextRef = context.ref;\n // Create a combined ref that calls both\n const originalSetRef = setRef;\n setRef = (el: HTMLElement) => {\n originalSetRef(el);\n contextRef(el);\n };\n }\n\n // Return context without the ref\n const { ref: _, ...otherProps } = context;\n return otherProps;\n}\n\nexport interface FocusableProviderProps {\n /** The child element to provide DOM props to. */\n children?: JSX.Element;\n}\n\nfunction isDisabledValue(isDisabled: Accessor<boolean> | boolean | undefined): boolean {\n if (typeof isDisabled === \"function\") {\n return isDisabled();\n }\n return isDisabled ?? false;\n}\n\n/**\n * Makes an element focusable, handling disabled state and tab order.\n * Provides focus state tracking and autoFocus support.\n *\n * Based on react-aria's useFocusable but adapted for SolidJS.\n *\n * @example\n * ```tsx\n * import { createFocusable } from 'solidaria';\n *\n * function FocusableInput(props) {\n * let ref;\n * const { focusableProps } = createFocusable({\n * autoFocus: props.autoFocus,\n * onFocusChange: (focused) => console.log('Focus:', focused),\n * });\n *\n * return (\n * <input\n * {...focusableProps}\n * ref={(el) => { ref = el; focusableProps.ref?.(el); }}\n * />\n * );\n * }\n * ```\n */\nexport function createFocusable(\n props: CreateFocusableProps = {},\n ref?: (el: HTMLElement) => void,\n): FocusableResult {\n let elementRef: HTMLElement | null = null;\n let autoFocusDone = false;\n\n // Set up ref handler\n const setRef = (el: HTMLElement) => {\n elementRef = el;\n ref?.(el);\n };\n\n // Get focus and keyboard props from the respective hooks\n const { focusProps } = createFocus({\n isDisabled: isDisabledValue(props.isDisabled),\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n onFocusChange: props.onFocusChange,\n });\n\n const { keyboardProps } = createKeyboard({\n isDisabled: isDisabledValue(props.isDisabled),\n onKeyDown: props.onKeyDown,\n onKeyUp: props.onKeyUp,\n });\n\n // Merge focus and keyboard interactions\n const interactions = mergeProps(focusProps, keyboardProps);\n\n // Get context props (from FocusableProvider if present)\n const contextProps = useFocusableContext(setRef);\n const interactionProps = isDisabledValue(props.isDisabled) ? {} : contextProps;\n\n // Handle autoFocus\n onMount(() => {\n if (props.autoFocus && elementRef && !autoFocusDone) {\n focusSafely(elementRef);\n autoFocusDone = true;\n }\n });\n\n // Build final focusable props\n const focusableProps = mergeProps(\n {\n ...interactions,\n get tabIndex() {\n if (isDisabledValue(props.isDisabled)) {\n return undefined;\n }\n return props.excludeFromTabOrder ? -1 : 0;\n },\n ref: setRef,\n },\n interactionProps,\n ) as JSX.HTMLAttributes<HTMLElement>;\n\n return {\n focusableProps,\n };\n}\n"],"mappings":";;;;;;;;;AAsCA,SAAS,mBACP,SAC8B;CAC9B,IAAI,CAAC,SACH;CAGF,QAAQ,MAAS;EACf,IAAI,wBAAwB;EAI5B,MAAM,4BAA6B,EAChC;EAcH,QAXc,OAAO,OAAO,GAAG,EAC7B,sBAAsB;GACpB,wBAAwB;GAGxB,IAAI,OAAO,8BAA8B,YACvC,0BAA0B,KAAK,CAAC;EAEpC,EACF,CAEY,CAAC;EAEb,IAAI,uBACF,EAAE,gBAAgB;CAEtB;AACF;;;;;;AAOA,SAAgB,eAAe,QAA6B,CAAC,GAAmB;CAC9E,IAAI,MAAM,YACR,OAAO,EACL,eAAe,CAAC,EAClB;CAGF,OAAO,EACL,eAAe;EACb,WAAW,mBAAmB,MAAM,SAAS;EAC7C,SAAS,mBAAmB,MAAM,OAAO;CAC3C,EACF;AACF;;;;;;;;;;;;ACjDA,MAAa,mBAAmB,cAA4C,IAAI;;;;AAKhF,SAAS,oBACP,QACoC;CACpC,MAAM,UAAU,WAAW,gBAAgB,KAAK,CAAC;CAGjD,IAAI,QAAQ,KAAK;EACf,MAAM,aAAa,QAAQ;EAE3B,MAAM,iBAAiB;EACvB,UAAU,OAAoB;GAC5B,eAAe,EAAE;GACjB,WAAW,EAAE;EACf;CACF;CAGA,MAAM,EAAE,KAAK,GAAG,GAAG,eAAe;CAClC,OAAO;AACT;AAOA,SAAS,gBAAgB,YAA8D;CACrF,IAAI,OAAO,eAAe,YACxB,OAAO,WAAW;CAEpB,OAAO,cAAc;AACvB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,QAA8B,CAAC,GAC/B,KACiB;CACjB,IAAI,aAAiC;CACrC,IAAI,gBAAgB;CAGpB,MAAM,UAAU,OAAoB;EAClC,aAAa;EACb,MAAM,EAAE;CACV;CAGA,MAAM,EAAE,eAAe,YAAY;EACjC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,eAAe,MAAM;CACvB,CAAC;CAED,MAAM,EAAE,kBAAkB,eAAe;EACvC,YAAY,gBAAgB,MAAM,UAAU;EAC5C,WAAW,MAAM;EACjB,SAAS,MAAM;CACjB,CAAC;CAGD,MAAM,eAAeA,aAAW,YAAY,aAAa;CAGzD,MAAM,eAAe,oBAAoB,MAAM;CAC/C,MAAM,mBAAmB,gBAAgB,MAAM,UAAU,IAAI,CAAC,IAAI;CAGlE,cAAc;EACZ,IAAI,MAAM,aAAa,cAAc,CAAC,eAAe;GACnD,YAAY,UAAU;GACtB,gBAAgB;EAClB;CACF,CAAC;CAiBD,OAAO,EACL,gBAfqBA,aACrB;EACE,GAAG;EACH,IAAI,WAAW;GACb,IAAI,gBAAgB,MAAM,UAAU,GAClC;GAEF,OAAO,MAAM,sBAAsB,KAAK;EAC1C;EACA,KAAK;CACP,GACA,gBAIa,EACf;AACF"}
@@ -36,4 +36,4 @@ function createFormReset(ref, defaultValue, onReset) {
36
36
  //#endregion
37
37
  export { createFormReset as t };
38
38
 
39
- //# sourceMappingURL=form.js.map
39
+ //# sourceMappingURL=createFormReset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormReset.js","names":[],"sources":["../../src/form/createFormReset.ts"],"sourcesContent":["/**\n * createFormReset - Handles form reset events for form fields.\n *\n * Resets the field value to its default when the containing form is reset.\n * Port of @react-aria/utils useFormReset.\n */\n\nimport { type Accessor, createEffect, onCleanup } from \"solid-js\";\n\nexport interface FormResetOptions<T> {\n /** The default value to reset to. */\n defaultValue: T;\n /** Function to set the current value. */\n onReset: (value: T) => void;\n}\n\n/**\n * Listens for form reset events and resets the field value to its default.\n *\n * @example\n * ```tsx\n * createFormReset(\n * () => inputRef,\n * { label: 'Default' },\n * (value) => state.setSelectedKey(value.key)\n * );\n * ```\n */\nexport function createFormReset<T>(\n ref: Accessor<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | undefined>,\n defaultValue: T,\n onReset: (value: T) => void,\n): void {\n createEffect(() => {\n const element = ref();\n if (!element) return;\n\n const form = element.form;\n if (!form) return;\n\n const handleReset = () => {\n onReset(defaultValue);\n };\n\n form.addEventListener(\"reset\", handleReset);\n\n onCleanup(() => {\n form.removeEventListener(\"reset\", handleReset);\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,KACA,cACA,SACM;CACN,mBAAmB;EACjB,MAAM,UAAU,IAAI;EACpB,IAAI,CAAC,SAAS;EAEd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,MAAM;EAEX,MAAM,oBAAoB;GACxB,QAAQ,YAAY;EACtB;EAEA,KAAK,iBAAiB,SAAS,WAAW;EAE1C,gBAAgB;GACd,KAAK,oBAAoB,SAAS,WAAW;EAC/C,CAAC;CACH,CAAC;AACH"}
@@ -36,4 +36,4 @@ function createFormReset(ref, defaultValue, onReset) {
36
36
  //#endregion
37
37
  export { createFormReset as t };
38
38
 
39
- //# sourceMappingURL=form.jsx.map
39
+ //# sourceMappingURL=createFormReset.jsx.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFormReset.jsx","names":[],"sources":["../../src/form/createFormReset.ts"],"sourcesContent":["/**\n * createFormReset - Handles form reset events for form fields.\n *\n * Resets the field value to its default when the containing form is reset.\n * Port of @react-aria/utils useFormReset.\n */\n\nimport { type Accessor, createEffect, onCleanup } from \"solid-js\";\n\nexport interface FormResetOptions<T> {\n /** The default value to reset to. */\n defaultValue: T;\n /** Function to set the current value. */\n onReset: (value: T) => void;\n}\n\n/**\n * Listens for form reset events and resets the field value to its default.\n *\n * @example\n * ```tsx\n * createFormReset(\n * () => inputRef,\n * { label: 'Default' },\n * (value) => state.setSelectedKey(value.key)\n * );\n * ```\n */\nexport function createFormReset<T>(\n ref: Accessor<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | undefined>,\n defaultValue: T,\n onReset: (value: T) => void,\n): void {\n createEffect(() => {\n const element = ref();\n if (!element) return;\n\n const form = element.form;\n if (!form) return;\n\n const handleReset = () => {\n onReset(defaultValue);\n };\n\n form.addEventListener(\"reset\", handleReset);\n\n onCleanup(() => {\n form.removeEventListener(\"reset\", handleReset);\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,gBACd,KACA,cACA,SACM;CACN,mBAAmB;EACjB,MAAM,UAAU,IAAI;EACpB,IAAI,CAAC,SAAS;EAEd,MAAM,OAAO,QAAQ;EACrB,IAAI,CAAC,MAAM;EAEX,MAAM,oBAAoB;GACxB,QAAQ,YAAY;EACtB;EAEA,KAAK,iBAAiB,SAAS,WAAW;EAE1C,gBAAgB;GACd,KAAK,oBAAoB,SAAS,WAAW;EAC/C,CAAC;CACH,CAAC;AACH"}
@@ -1,4 +1,5 @@
1
- import { i as access, r as isTestEnv } from "./env.js";
1
+ import { r as isTestEnv } from "./env.js";
2
+ import { t as access } from "./reactivity.js";
2
3
  import { s as createGlobalListeners } from "./utils.js";
3
4
  import { y as nodeContains } from "./focus.js";
4
5
  import { createEffect, createMemo, createSignal, onCleanup } from "solid-js";
@@ -1 +1 @@
1
- {"version":3,"file":"createHover.js","names":[],"sources":["../../src/interactions/createHover.ts"],"sourcesContent":["/**\n * createHover hook for Solidaria\n *\n * Handles pointer hover interactions for an element. Normalizes behavior\n * across browsers and platforms, and ignores emulated mouse events on touch devices.\n *\n * Port of @react-aria/interactions useHover.\n */\n\nimport {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n createMemo,\n} from \"solid-js\";\nimport { type MaybeAccessor, access } from \"../utils/reactivity\";\nimport { isTestEnv } from \"../utils/env\";\nimport { createGlobalListeners, nodeContains } from \"../utils\";\n\nexport interface HoverEvent {\n /** The type of hover event being fired. */\n type: \"hoverstart\" | \"hoverend\";\n /** The pointer type that triggered the hover event. */\n pointerType: \"mouse\" | \"pen\";\n /** The target element of the hover event. */\n target: Element;\n}\n\nexport interface HoverEvents {\n /** Handler called when the hover starts. */\n onHoverStart?: (e: HoverEvent) => void;\n /** Handler called when the hover ends. */\n onHoverEnd?: (e: HoverEvent) => void;\n /** Handler called when the hover state changes. */\n onHoverChange?: (isHovering: boolean) => void;\n}\n\nexport interface CreateHoverProps extends HoverEvents {\n /** Whether the hover events should be disabled. */\n isDisabled?: boolean;\n}\n\n/** Event handler props returned by createHover - safe to spread on any element */\nexport type HoverProps = Pick<\n JSX.HTMLAttributes<HTMLElement>,\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onPointerOver\"\n | \"onPointerOut\"\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n>;\n\nexport interface HoverResult {\n /** Props to spread on the target element. */\n hoverProps: HoverProps;\n /** Whether the element is currently hovered. */\n isHovered: Accessor<boolean>;\n}\n\n// iOS fires onPointerEnter twice: once with pointerType=\"touch\" and again with pointerType=\"mouse\".\n// We want to ignore these emulated events so they do not trigger hover behavior.\nlet globalIgnoreEmulatedMouseEvents = false;\nlet hoverCount = 0;\n\nfunction setGlobalIgnoreEmulatedMouseEvents() {\n globalIgnoreEmulatedMouseEvents = true;\n setTimeout(() => {\n globalIgnoreEmulatedMouseEvents = false;\n }, 50);\n}\n\nfunction handleGlobalPointerEvent(e: PointerEvent) {\n if (e.pointerType === \"touch\") {\n setGlobalIgnoreEmulatedMouseEvents();\n }\n}\n\nfunction setupGlobalTouchEvents() {\n if (typeof document === \"undefined\") {\n return () => {};\n }\n\n if (hoverCount === 0) {\n if (typeof PointerEvent !== \"undefined\") {\n document.addEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.addEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n }\n\n hoverCount++;\n return () => {\n hoverCount--;\n if (hoverCount > 0) {\n return;\n }\n\n if (typeof PointerEvent !== \"undefined\") {\n document.removeEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.removeEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n };\n}\n\n/**\n * Handles pointer hover interactions for an element.\n */\nexport function createHover(props: MaybeAccessor<CreateHoverProps> = {}): HoverResult {\n const getProps = () => access(props);\n const [isHovered, setIsHovered] = createSignal(false);\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n\n // Track internal hover state\n let state = {\n isHovered: false,\n ignoreEmulatedMouseEvents: false,\n pointerType: \"\" as \"mouse\" | \"pen\" | \"\",\n target: null as Element | null,\n };\n\n // Setup global touch events\n createEffect(() => {\n const cleanup = setupGlobalTouchEvents();\n onCleanup(cleanup);\n });\n\n // Reset hover when disabled\n createEffect(() => {\n const p = getProps();\n if (p.isDisabled && state.isHovered) {\n triggerHoverEnd(state.target as Element, state.pointerType as \"mouse\" | \"pen\");\n }\n });\n\n function triggerHoverStart(\n target: Element,\n pointerType: \"mouse\" | \"pen\",\n eventTarget: Element | null,\n ) {\n const p = getProps();\n state.pointerType = pointerType;\n\n const isOverTarget = eventTarget instanceof Element ? target.contains(eventTarget) : true;\n if (p.isDisabled || state.isHovered || !isOverTarget) {\n return;\n }\n\n state.isHovered = true;\n state.target = target;\n\n addGlobalListener(\n \"pointerover\",\n (event: PointerEvent) => {\n if (\n state.isHovered &&\n state.target &&\n !nodeContains(state.target, event.target as Element)\n ) {\n triggerHoverEnd(event.target as Element, event.pointerType as \"mouse\" | \"pen\");\n }\n },\n { capture: true },\n );\n\n p.onHoverStart?.({\n type: \"hoverstart\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(true);\n setIsHovered(true);\n }\n\n function triggerHoverEnd(target: Element | null, pointerType: \"mouse\" | \"pen\") {\n const p = getProps();\n state.pointerType = \"\";\n state.target = null;\n\n if (!state.isHovered || !target) {\n return;\n }\n\n state.isHovered = false;\n removeAllGlobalListeners();\n\n p.onHoverEnd?.({\n type: \"hoverend\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(false);\n setIsHovered(false);\n }\n\n const hoverProps = createMemo<JSX.HTMLAttributes<HTMLElement>>(() => {\n if (typeof PointerEvent !== \"undefined\") {\n return {\n onPointerEnter: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerLeave: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n onPointerOver: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerOut: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n };\n }\n\n // Fallback for environments without PointerEvent (mainly tests)\n return {\n onTouchStart: () => {\n state.ignoreEmulatedMouseEvents = true;\n },\n onMouseEnter: (e: MouseEvent) => {\n if (!state.ignoreEmulatedMouseEvents && !globalIgnoreEmulatedMouseEvents) {\n triggerHoverStart(e.currentTarget as Element, \"mouse\", e.target as Element);\n }\n state.ignoreEmulatedMouseEvents = false;\n },\n onMouseLeave: (e: MouseEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, \"mouse\");\n }\n },\n };\n });\n\n return {\n hoverProps: hoverProps() as HoverProps,\n isHovered,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createHover.js","names":[],"sources":["../../src/interactions/createHover.ts"],"sourcesContent":["/**\n * createHover hook for Solidaria\n *\n * Handles pointer hover interactions for an element. Normalizes behavior\n * across browsers and platforms, and ignores emulated mouse events on touch devices.\n *\n * Port of @react-aria/interactions useHover.\n */\n\nimport {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n createMemo,\n} from \"solid-js\";\nimport { type MaybeAccessor, access } from \"../utils/reactivity\";\nimport { isTestEnv } from \"../utils/env\";\nimport { createGlobalListeners, nodeContains } from \"../utils\";\n\nexport interface HoverEvent {\n /** The type of hover event being fired. */\n type: \"hoverstart\" | \"hoverend\";\n /** The pointer type that triggered the hover event. */\n pointerType: \"mouse\" | \"pen\";\n /** The target element of the hover event. */\n target: Element;\n}\n\nexport interface HoverEvents {\n /** Handler called when the hover starts. */\n onHoverStart?: (e: HoverEvent) => void;\n /** Handler called when the hover ends. */\n onHoverEnd?: (e: HoverEvent) => void;\n /** Handler called when the hover state changes. */\n onHoverChange?: (isHovering: boolean) => void;\n}\n\nexport interface CreateHoverProps extends HoverEvents {\n /** Whether the hover events should be disabled. */\n isDisabled?: boolean;\n}\n\n/** Event handler props returned by createHover - safe to spread on any element */\nexport type HoverProps = Pick<\n JSX.HTMLAttributes<HTMLElement>,\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onPointerOver\"\n | \"onPointerOut\"\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n>;\n\nexport interface HoverResult {\n /** Props to spread on the target element. */\n hoverProps: HoverProps;\n /** Whether the element is currently hovered. */\n isHovered: Accessor<boolean>;\n}\n\n// iOS fires onPointerEnter twice: once with pointerType=\"touch\" and again with pointerType=\"mouse\".\n// We want to ignore these emulated events so they do not trigger hover behavior.\nlet globalIgnoreEmulatedMouseEvents = false;\nlet hoverCount = 0;\n\nfunction setGlobalIgnoreEmulatedMouseEvents() {\n globalIgnoreEmulatedMouseEvents = true;\n setTimeout(() => {\n globalIgnoreEmulatedMouseEvents = false;\n }, 50);\n}\n\nfunction handleGlobalPointerEvent(e: PointerEvent) {\n if (e.pointerType === \"touch\") {\n setGlobalIgnoreEmulatedMouseEvents();\n }\n}\n\nfunction setupGlobalTouchEvents() {\n if (typeof document === \"undefined\") {\n return () => {};\n }\n\n if (hoverCount === 0) {\n if (typeof PointerEvent !== \"undefined\") {\n document.addEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.addEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n }\n\n hoverCount++;\n return () => {\n hoverCount--;\n if (hoverCount > 0) {\n return;\n }\n\n if (typeof PointerEvent !== \"undefined\") {\n document.removeEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.removeEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n };\n}\n\n/**\n * Handles pointer hover interactions for an element.\n */\nexport function createHover(props: MaybeAccessor<CreateHoverProps> = {}): HoverResult {\n const getProps = () => access(props);\n const [isHovered, setIsHovered] = createSignal(false);\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n\n // Track internal hover state\n let state = {\n isHovered: false,\n ignoreEmulatedMouseEvents: false,\n pointerType: \"\" as \"mouse\" | \"pen\" | \"\",\n target: null as Element | null,\n };\n\n // Setup global touch events\n createEffect(() => {\n const cleanup = setupGlobalTouchEvents();\n onCleanup(cleanup);\n });\n\n // Reset hover when disabled\n createEffect(() => {\n const p = getProps();\n if (p.isDisabled && state.isHovered) {\n triggerHoverEnd(state.target as Element, state.pointerType as \"mouse\" | \"pen\");\n }\n });\n\n function triggerHoverStart(\n target: Element,\n pointerType: \"mouse\" | \"pen\",\n eventTarget: Element | null,\n ) {\n const p = getProps();\n state.pointerType = pointerType;\n\n const isOverTarget = eventTarget instanceof Element ? target.contains(eventTarget) : true;\n if (p.isDisabled || state.isHovered || !isOverTarget) {\n return;\n }\n\n state.isHovered = true;\n state.target = target;\n\n addGlobalListener(\n \"pointerover\",\n (event: PointerEvent) => {\n if (\n state.isHovered &&\n state.target &&\n !nodeContains(state.target, event.target as Element)\n ) {\n triggerHoverEnd(event.target as Element, event.pointerType as \"mouse\" | \"pen\");\n }\n },\n { capture: true },\n );\n\n p.onHoverStart?.({\n type: \"hoverstart\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(true);\n setIsHovered(true);\n }\n\n function triggerHoverEnd(target: Element | null, pointerType: \"mouse\" | \"pen\") {\n const p = getProps();\n state.pointerType = \"\";\n state.target = null;\n\n if (!state.isHovered || !target) {\n return;\n }\n\n state.isHovered = false;\n removeAllGlobalListeners();\n\n p.onHoverEnd?.({\n type: \"hoverend\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(false);\n setIsHovered(false);\n }\n\n const hoverProps = createMemo<JSX.HTMLAttributes<HTMLElement>>(() => {\n if (typeof PointerEvent !== \"undefined\") {\n return {\n onPointerEnter: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerLeave: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n onPointerOver: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerOut: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n };\n }\n\n // Fallback for environments without PointerEvent (mainly tests)\n return {\n onTouchStart: () => {\n state.ignoreEmulatedMouseEvents = true;\n },\n onMouseEnter: (e: MouseEvent) => {\n if (!state.ignoreEmulatedMouseEvents && !globalIgnoreEmulatedMouseEvents) {\n triggerHoverStart(e.currentTarget as Element, \"mouse\", e.target as Element);\n }\n state.ignoreEmulatedMouseEvents = false;\n },\n onMouseLeave: (e: MouseEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, \"mouse\");\n }\n },\n };\n });\n\n return {\n hoverProps: hoverProps() as HoverProps,\n isHovered,\n };\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { i as access, r as isTestEnv } from "./env.jsx";
1
+ import { r as isTestEnv } from "./env.jsx";
2
+ import { t as access } from "./reactivity.jsx";
2
3
  import { s as createGlobalListeners } from "./utils.jsx";
3
4
  import { y as nodeContains } from "./focus.jsx";
4
5
  import { createEffect, createMemo, createSignal, onCleanup } from "solid-js";
@@ -1 +1 @@
1
- {"version":3,"file":"createHover.jsx","names":[],"sources":["../../src/interactions/createHover.ts"],"sourcesContent":["/**\n * createHover hook for Solidaria\n *\n * Handles pointer hover interactions for an element. Normalizes behavior\n * across browsers and platforms, and ignores emulated mouse events on touch devices.\n *\n * Port of @react-aria/interactions useHover.\n */\n\nimport {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n createMemo,\n} from \"solid-js\";\nimport { type MaybeAccessor, access } from \"../utils/reactivity\";\nimport { isTestEnv } from \"../utils/env\";\nimport { createGlobalListeners, nodeContains } from \"../utils\";\n\nexport interface HoverEvent {\n /** The type of hover event being fired. */\n type: \"hoverstart\" | \"hoverend\";\n /** The pointer type that triggered the hover event. */\n pointerType: \"mouse\" | \"pen\";\n /** The target element of the hover event. */\n target: Element;\n}\n\nexport interface HoverEvents {\n /** Handler called when the hover starts. */\n onHoverStart?: (e: HoverEvent) => void;\n /** Handler called when the hover ends. */\n onHoverEnd?: (e: HoverEvent) => void;\n /** Handler called when the hover state changes. */\n onHoverChange?: (isHovering: boolean) => void;\n}\n\nexport interface CreateHoverProps extends HoverEvents {\n /** Whether the hover events should be disabled. */\n isDisabled?: boolean;\n}\n\n/** Event handler props returned by createHover - safe to spread on any element */\nexport type HoverProps = Pick<\n JSX.HTMLAttributes<HTMLElement>,\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onPointerOver\"\n | \"onPointerOut\"\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n>;\n\nexport interface HoverResult {\n /** Props to spread on the target element. */\n hoverProps: HoverProps;\n /** Whether the element is currently hovered. */\n isHovered: Accessor<boolean>;\n}\n\n// iOS fires onPointerEnter twice: once with pointerType=\"touch\" and again with pointerType=\"mouse\".\n// We want to ignore these emulated events so they do not trigger hover behavior.\nlet globalIgnoreEmulatedMouseEvents = false;\nlet hoverCount = 0;\n\nfunction setGlobalIgnoreEmulatedMouseEvents() {\n globalIgnoreEmulatedMouseEvents = true;\n setTimeout(() => {\n globalIgnoreEmulatedMouseEvents = false;\n }, 50);\n}\n\nfunction handleGlobalPointerEvent(e: PointerEvent) {\n if (e.pointerType === \"touch\") {\n setGlobalIgnoreEmulatedMouseEvents();\n }\n}\n\nfunction setupGlobalTouchEvents() {\n if (typeof document === \"undefined\") {\n return () => {};\n }\n\n if (hoverCount === 0) {\n if (typeof PointerEvent !== \"undefined\") {\n document.addEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.addEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n }\n\n hoverCount++;\n return () => {\n hoverCount--;\n if (hoverCount > 0) {\n return;\n }\n\n if (typeof PointerEvent !== \"undefined\") {\n document.removeEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.removeEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n };\n}\n\n/**\n * Handles pointer hover interactions for an element.\n */\nexport function createHover(props: MaybeAccessor<CreateHoverProps> = {}): HoverResult {\n const getProps = () => access(props);\n const [isHovered, setIsHovered] = createSignal(false);\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n\n // Track internal hover state\n let state = {\n isHovered: false,\n ignoreEmulatedMouseEvents: false,\n pointerType: \"\" as \"mouse\" | \"pen\" | \"\",\n target: null as Element | null,\n };\n\n // Setup global touch events\n createEffect(() => {\n const cleanup = setupGlobalTouchEvents();\n onCleanup(cleanup);\n });\n\n // Reset hover when disabled\n createEffect(() => {\n const p = getProps();\n if (p.isDisabled && state.isHovered) {\n triggerHoverEnd(state.target as Element, state.pointerType as \"mouse\" | \"pen\");\n }\n });\n\n function triggerHoverStart(\n target: Element,\n pointerType: \"mouse\" | \"pen\",\n eventTarget: Element | null,\n ) {\n const p = getProps();\n state.pointerType = pointerType;\n\n const isOverTarget = eventTarget instanceof Element ? target.contains(eventTarget) : true;\n if (p.isDisabled || state.isHovered || !isOverTarget) {\n return;\n }\n\n state.isHovered = true;\n state.target = target;\n\n addGlobalListener(\n \"pointerover\",\n (event: PointerEvent) => {\n if (\n state.isHovered &&\n state.target &&\n !nodeContains(state.target, event.target as Element)\n ) {\n triggerHoverEnd(event.target as Element, event.pointerType as \"mouse\" | \"pen\");\n }\n },\n { capture: true },\n );\n\n p.onHoverStart?.({\n type: \"hoverstart\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(true);\n setIsHovered(true);\n }\n\n function triggerHoverEnd(target: Element | null, pointerType: \"mouse\" | \"pen\") {\n const p = getProps();\n state.pointerType = \"\";\n state.target = null;\n\n if (!state.isHovered || !target) {\n return;\n }\n\n state.isHovered = false;\n removeAllGlobalListeners();\n\n p.onHoverEnd?.({\n type: \"hoverend\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(false);\n setIsHovered(false);\n }\n\n const hoverProps = createMemo<JSX.HTMLAttributes<HTMLElement>>(() => {\n if (typeof PointerEvent !== \"undefined\") {\n return {\n onPointerEnter: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerLeave: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n onPointerOver: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerOut: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n };\n }\n\n // Fallback for environments without PointerEvent (mainly tests)\n return {\n onTouchStart: () => {\n state.ignoreEmulatedMouseEvents = true;\n },\n onMouseEnter: (e: MouseEvent) => {\n if (!state.ignoreEmulatedMouseEvents && !globalIgnoreEmulatedMouseEvents) {\n triggerHoverStart(e.currentTarget as Element, \"mouse\", e.target as Element);\n }\n state.ignoreEmulatedMouseEvents = false;\n },\n onMouseLeave: (e: MouseEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, \"mouse\");\n }\n },\n };\n });\n\n return {\n hoverProps: hoverProps() as HoverProps,\n isHovered,\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAgEA,IAAI,kCAAkC;AACtC,IAAI,aAAa;AAEjB,SAAS,qCAAqC;CAC5C,kCAAkC;CAClC,iBAAiB;EACf,kCAAkC;CACpC,GAAG,EAAE;AACP;AAEA,SAAS,yBAAyB,GAAiB;CACjD,IAAI,EAAE,gBAAgB,SACpB,mCAAmC;AAEvC;AAEA,SAAS,yBAAyB;CAChC,IAAI,OAAO,aAAa,aACtB,aAAa,CAAC;CAGhB,IAAI,eAAe;MACb,OAAO,iBAAiB,aAC1B,SAAS,iBAAiB,aAAa,wBAAwB;OAC1D,IAAI,UAAU,GACnB,SAAS,iBAAiB,YAAY,kCAAkC;CAAA;CAI5E;CACA,aAAa;EACX;EACA,IAAI,aAAa,GACf;EAGF,IAAI,OAAO,iBAAiB,aAC1B,SAAS,oBAAoB,aAAa,wBAAwB;OAC7D,IAAI,UAAU,GACnB,SAAS,oBAAoB,YAAY,kCAAkC;CAE/E;AACF;;;;AAKA,SAAgB,YAAY,QAAyC,CAAC,GAAgB;CACpF,MAAM,iBAAiB,OAAO,KAAK;CACnC,MAAM,CAAC,WAAW,gBAAgB,aAAa,KAAK;CACpD,MAAM,EAAE,mBAAmB,6BAA6B,sBAAsB;CAG9E,IAAI,QAAQ;EACV,WAAW;EACX,2BAA2B;EAC3B,aAAa;EACb,QAAQ;CACV;CAGA,mBAAmB;EAEjB,UADgB,uBACA,CAAC;CACnB,CAAC;CAGD,mBAAmB;EAEjB,IADU,SACN,CAAC,CAAC,cAAc,MAAM,WACxB,gBAAgB,MAAM,QAAmB,MAAM,WAA8B;CAEjF,CAAC;CAED,SAAS,kBACP,QACA,aACA,aACA;EACA,MAAM,IAAI,SAAS;EACnB,MAAM,cAAc;EAEpB,MAAM,eAAe,uBAAuB,UAAU,OAAO,SAAS,WAAW,IAAI;EACrF,IAAI,EAAE,cAAc,MAAM,aAAa,CAAC,cACtC;EAGF,MAAM,YAAY;EAClB,MAAM,SAAS;EAEf,kBACE,gBACC,UAAwB;GACvB,IACE,MAAM,aACN,MAAM,UACN,CAAC,aAAa,MAAM,QAAQ,MAAM,MAAiB,GAEnD,gBAAgB,MAAM,QAAmB,MAAM,WAA8B;EAEjF,GACA,EAAE,SAAS,KAAK,CAClB;EAEA,EAAE,eAAe;GACf,MAAM;GACN;GACA;EACF,CAAC;EAED,EAAE,gBAAgB,IAAI;EACtB,aAAa,IAAI;CACnB;CAEA,SAAS,gBAAgB,QAAwB,aAA8B;EAC7E,MAAM,IAAI,SAAS;EACnB,MAAM,cAAc;EACpB,MAAM,SAAS;EAEf,IAAI,CAAC,MAAM,aAAa,CAAC,QACvB;EAGF,MAAM,YAAY;EAClB,yBAAyB;EAEzB,EAAE,aAAa;GACb,MAAM;GACN;GACA;EACF,CAAC;EAED,EAAE,gBAAgB,KAAK;EACvB,aAAa,KAAK;CACpB;CAkEA,OAAO;EACL,YAjEiB,iBAAkD;GACnE,IAAI,OAAO,iBAAiB,aAC1B,OAAO;IACL,iBAAiB,MAAoB;KACnC,IAAI,mCAAmC,EAAE,gBAAgB,SACvD;KAEF,IAAI,EAAE,gBAAgB,SACpB;KAEF,kBACE,EAAE,eACF,EAAE,aACF,EAAE,MACJ;IACF;IACA,iBAAiB,MAAoB;KAEnC,IAAI,CADM,SACL,CAAC,CAAC,cAAe,EAAE,cAA0B,SAAS,EAAE,MAAiB,GAC5E,gBAAgB,EAAE,eAA0B,EAAE,WAA8B;IAEhF;IACA,gBAAgB,MAAoB;KAClC,IAAI,mCAAmC,EAAE,gBAAgB,SACvD;KAEF,IAAI,EAAE,gBAAgB,SACpB;KAEF,kBACE,EAAE,eACF,EAAE,aACF,EAAE,MACJ;IACF;IACA,eAAe,MAAoB;KAEjC,IAAI,CADM,SACL,CAAC,CAAC,cAAe,EAAE,cAA0B,SAAS,EAAE,MAAiB,GAC5E,gBAAgB,EAAE,eAA0B,EAAE,WAA8B;IAEhF;GACF;GAIF,OAAO;IACL,oBAAoB;KAClB,MAAM,4BAA4B;IACpC;IACA,eAAe,MAAkB;KAC/B,IAAI,CAAC,MAAM,6BAA6B,CAAC,iCACvC,kBAAkB,EAAE,eAA0B,SAAS,EAAE,MAAiB;KAE5E,MAAM,4BAA4B;IACpC;IACA,eAAe,MAAkB;KAE/B,IAAI,CADM,SACL,CAAC,CAAC,cAAe,EAAE,cAA0B,SAAS,EAAE,MAAiB,GAC5E,gBAAgB,EAAE,eAA0B,OAAO;IAEvD;GACF;EACF,CAGuB,CAAC,CAAC;EACvB;CACF;AACF"}
1
+ {"version":3,"file":"createHover.jsx","names":[],"sources":["../../src/interactions/createHover.ts"],"sourcesContent":["/**\n * createHover hook for Solidaria\n *\n * Handles pointer hover interactions for an element. Normalizes behavior\n * across browsers and platforms, and ignores emulated mouse events on touch devices.\n *\n * Port of @react-aria/interactions useHover.\n */\n\nimport {\n type JSX,\n type Accessor,\n createSignal,\n createEffect,\n onCleanup,\n createMemo,\n} from \"solid-js\";\nimport { type MaybeAccessor, access } from \"../utils/reactivity\";\nimport { isTestEnv } from \"../utils/env\";\nimport { createGlobalListeners, nodeContains } from \"../utils\";\n\nexport interface HoverEvent {\n /** The type of hover event being fired. */\n type: \"hoverstart\" | \"hoverend\";\n /** The pointer type that triggered the hover event. */\n pointerType: \"mouse\" | \"pen\";\n /** The target element of the hover event. */\n target: Element;\n}\n\nexport interface HoverEvents {\n /** Handler called when the hover starts. */\n onHoverStart?: (e: HoverEvent) => void;\n /** Handler called when the hover ends. */\n onHoverEnd?: (e: HoverEvent) => void;\n /** Handler called when the hover state changes. */\n onHoverChange?: (isHovering: boolean) => void;\n}\n\nexport interface CreateHoverProps extends HoverEvents {\n /** Whether the hover events should be disabled. */\n isDisabled?: boolean;\n}\n\n/** Event handler props returned by createHover - safe to spread on any element */\nexport type HoverProps = Pick<\n JSX.HTMLAttributes<HTMLElement>,\n | \"onPointerEnter\"\n | \"onPointerLeave\"\n | \"onPointerOver\"\n | \"onPointerOut\"\n | \"onMouseEnter\"\n | \"onMouseLeave\"\n>;\n\nexport interface HoverResult {\n /** Props to spread on the target element. */\n hoverProps: HoverProps;\n /** Whether the element is currently hovered. */\n isHovered: Accessor<boolean>;\n}\n\n// iOS fires onPointerEnter twice: once with pointerType=\"touch\" and again with pointerType=\"mouse\".\n// We want to ignore these emulated events so they do not trigger hover behavior.\nlet globalIgnoreEmulatedMouseEvents = false;\nlet hoverCount = 0;\n\nfunction setGlobalIgnoreEmulatedMouseEvents() {\n globalIgnoreEmulatedMouseEvents = true;\n setTimeout(() => {\n globalIgnoreEmulatedMouseEvents = false;\n }, 50);\n}\n\nfunction handleGlobalPointerEvent(e: PointerEvent) {\n if (e.pointerType === \"touch\") {\n setGlobalIgnoreEmulatedMouseEvents();\n }\n}\n\nfunction setupGlobalTouchEvents() {\n if (typeof document === \"undefined\") {\n return () => {};\n }\n\n if (hoverCount === 0) {\n if (typeof PointerEvent !== \"undefined\") {\n document.addEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.addEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n }\n\n hoverCount++;\n return () => {\n hoverCount--;\n if (hoverCount > 0) {\n return;\n }\n\n if (typeof PointerEvent !== \"undefined\") {\n document.removeEventListener(\"pointerup\", handleGlobalPointerEvent);\n } else if (isTestEnv()) {\n document.removeEventListener(\"touchend\", setGlobalIgnoreEmulatedMouseEvents);\n }\n };\n}\n\n/**\n * Handles pointer hover interactions for an element.\n */\nexport function createHover(props: MaybeAccessor<CreateHoverProps> = {}): HoverResult {\n const getProps = () => access(props);\n const [isHovered, setIsHovered] = createSignal(false);\n const { addGlobalListener, removeAllGlobalListeners } = createGlobalListeners();\n\n // Track internal hover state\n let state = {\n isHovered: false,\n ignoreEmulatedMouseEvents: false,\n pointerType: \"\" as \"mouse\" | \"pen\" | \"\",\n target: null as Element | null,\n };\n\n // Setup global touch events\n createEffect(() => {\n const cleanup = setupGlobalTouchEvents();\n onCleanup(cleanup);\n });\n\n // Reset hover when disabled\n createEffect(() => {\n const p = getProps();\n if (p.isDisabled && state.isHovered) {\n triggerHoverEnd(state.target as Element, state.pointerType as \"mouse\" | \"pen\");\n }\n });\n\n function triggerHoverStart(\n target: Element,\n pointerType: \"mouse\" | \"pen\",\n eventTarget: Element | null,\n ) {\n const p = getProps();\n state.pointerType = pointerType;\n\n const isOverTarget = eventTarget instanceof Element ? target.contains(eventTarget) : true;\n if (p.isDisabled || state.isHovered || !isOverTarget) {\n return;\n }\n\n state.isHovered = true;\n state.target = target;\n\n addGlobalListener(\n \"pointerover\",\n (event: PointerEvent) => {\n if (\n state.isHovered &&\n state.target &&\n !nodeContains(state.target, event.target as Element)\n ) {\n triggerHoverEnd(event.target as Element, event.pointerType as \"mouse\" | \"pen\");\n }\n },\n { capture: true },\n );\n\n p.onHoverStart?.({\n type: \"hoverstart\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(true);\n setIsHovered(true);\n }\n\n function triggerHoverEnd(target: Element | null, pointerType: \"mouse\" | \"pen\") {\n const p = getProps();\n state.pointerType = \"\";\n state.target = null;\n\n if (!state.isHovered || !target) {\n return;\n }\n\n state.isHovered = false;\n removeAllGlobalListeners();\n\n p.onHoverEnd?.({\n type: \"hoverend\",\n target,\n pointerType,\n });\n\n p.onHoverChange?.(false);\n setIsHovered(false);\n }\n\n const hoverProps = createMemo<JSX.HTMLAttributes<HTMLElement>>(() => {\n if (typeof PointerEvent !== \"undefined\") {\n return {\n onPointerEnter: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerLeave: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n onPointerOver: (e: PointerEvent) => {\n if (globalIgnoreEmulatedMouseEvents && e.pointerType === \"mouse\") {\n return;\n }\n if (e.pointerType === \"touch\") {\n return;\n }\n triggerHoverStart(\n e.currentTarget as Element,\n e.pointerType as \"mouse\" | \"pen\",\n e.target as Element,\n );\n },\n onPointerOut: (e: PointerEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, e.pointerType as \"mouse\" | \"pen\");\n }\n },\n };\n }\n\n // Fallback for environments without PointerEvent (mainly tests)\n return {\n onTouchStart: () => {\n state.ignoreEmulatedMouseEvents = true;\n },\n onMouseEnter: (e: MouseEvent) => {\n if (!state.ignoreEmulatedMouseEvents && !globalIgnoreEmulatedMouseEvents) {\n triggerHoverStart(e.currentTarget as Element, \"mouse\", e.target as Element);\n }\n state.ignoreEmulatedMouseEvents = false;\n },\n onMouseLeave: (e: MouseEvent) => {\n const p = getProps();\n if (!p.isDisabled && (e.currentTarget as Element).contains(e.target as Element)) {\n triggerHoverEnd(e.currentTarget as Element, \"mouse\");\n }\n },\n };\n });\n\n return {\n hoverProps: hoverProps() as HoverProps,\n isHovered,\n };\n}\n"],"mappings":"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"}
@@ -218,10 +218,9 @@ function createFocusVisibleListener(handler, opts) {
218
218
  */
219
219
  function createFocusVisible(props = {}) {
220
220
  if (isServer) return { isFocusVisible: () => false };
221
- const { isTextInput, autoFocus } = props;
222
- const [isVisible, setIsVisible] = createSignal(autoFocus || isFocusVisible());
221
+ const [isVisible, setIsVisible] = createSignal(props.autoFocus || isFocusVisible());
223
222
  createEffect(() => {
224
- onCleanup(createFocusVisibleListener(setIsVisible, { isTextInput }));
223
+ onCleanup(createFocusVisibleListener(setIsVisible, { isTextInput: props.isTextInput }));
225
224
  });
226
225
  return { isFocusVisible: isVisible };
227
226
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createInteractionModality.js","names":[],"sources":["../../src/interactions/createInteractionModality.ts"],"sourcesContent":["/**\n * createInteractionModality + focus-visible tracking for solidaria\n *\n * Port of @react-aria/interactions useFocusVisible/useInteractionModality.\n * Tracks the current interaction modality (keyboard, pointer, or virtual) and\n * provides focus-visible state and listeners.\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink } from \"../utils\";\n\nexport type Modality = \"keyboard\" | \"pointer\" | \"virtual\";\nexport type PointerType = \"mouse\" | \"pen\" | \"touch\" | \"keyboard\" | \"virtual\";\ntype HandlerEvent = PointerEvent | MouseEvent | KeyboardEvent | FocusEvent | null;\ntype Handler = (modality: Modality, e: HandlerEvent) => void;\n\nexport type FocusVisibleHandler = (isFocusVisible: boolean) => void;\n\nexport interface FocusVisibleProps {\n /** Whether the element is a text input. */\n isTextInput?: boolean;\n /** Whether the element will be auto focused. */\n autoFocus?: boolean;\n}\n\nexport interface FocusVisibleResult {\n /** Whether keyboard focus is visible globally. */\n isFocusVisible: Accessor<boolean>;\n}\n\nexport interface InteractionModalityResult {\n /** The current interaction modality. */\n modality: Accessor<Modality | null>;\n}\n\nlet currentModality: Modality | null = null;\nlet currentPointerType: PointerType = \"keyboard\";\nconst changeHandlers = new Set<Handler>();\n\nexport let hasSetupGlobalListeners: Map<\n Window,\n { focus: typeof window.HTMLElement.prototype.focus }\n> = new Map();\nlet hasEventBeforeFocus = false;\nlet hasBlurredWindowRecently = false;\nlet ignoreFocusEvent = false;\n\nconst FOCUS_VISIBLE_INPUT_KEYS: Record<string, boolean> = {\n Tab: true,\n Escape: true,\n};\n\nfunction triggerChangeHandlers(modality: Modality, e: HandlerEvent) {\n for (const handler of changeHandlers) {\n handler(modality, e);\n }\n}\n\nfunction isValidKey(e: KeyboardEvent) {\n return !(\n e.metaKey ||\n (!isMac() && e.altKey) ||\n e.ctrlKey ||\n e.key === \"Control\" ||\n e.key === \"Shift\" ||\n e.key === \"Meta\"\n );\n}\n\nfunction handleKeyboardEvent(e: KeyboardEvent) {\n hasEventBeforeFocus = true;\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isValidKey(e)) {\n currentModality = \"keyboard\";\n currentPointerType = \"keyboard\";\n triggerChangeHandlers(\"keyboard\", e);\n }\n}\n\nfunction handlePointerEvent(e: PointerEvent | MouseEvent) {\n currentModality = \"pointer\";\n currentPointerType = \"pointerType\" in e ? (e.pointerType as PointerType) : \"mouse\";\n if (e.type === \"mousedown\" || e.type === \"pointerdown\") {\n hasEventBeforeFocus = true;\n triggerChangeHandlers(\"pointer\", e);\n }\n}\n\nfunction handleClickEvent(e: MouseEvent) {\n if (!e.isTrusted) {\n return;\n }\n\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isVirtualClick(e)) {\n hasEventBeforeFocus = true;\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n }\n}\n\nfunction handleFocusEvent(e: FocusEvent) {\n if (!e.isTrusted || ignoreFocusEvent) {\n return;\n }\n\n const target = e.target as EventTarget | null;\n const targetElement = target && (target as Element).nodeType ? (target as Element) : null;\n const ownerWindow = targetElement ? getOwnerWindow(targetElement) : window;\n const ownerDocument = targetElement ? getOwnerDocument(targetElement) : document;\n\n if (target === ownerWindow || target === ownerDocument) {\n return;\n }\n\n if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n triggerChangeHandlers(\"virtual\", e);\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = false;\n}\n\nfunction handleWindowBlur() {\n if (ignoreFocusEvent) {\n return;\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = true;\n}\n\nfunction setupGlobalFocusEvents(element?: HTMLElement | null) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n if (hasSetupGlobalListeners.get(windowObject)) {\n return;\n }\n\n const documentObject = getOwnerDocument(element);\n\n // Programmatic focus() calls shouldn't affect the current input modality, so we\n // patch HTMLElement.prototype.focus to record that an event preceded the focus.\n // Use Reflect.defineProperty (not assignment) so this works even when `focus` is\n // currently a getter-only accessor — e.g. when a test library's setup() has\n // instrumented it. Plain assignment throws in that case; Reflect.defineProperty\n // returns false rather than throwing (and succeeds on the configurable prototype).\n const originalFocus = windowObject.HTMLElement.prototype.focus;\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: function () {\n hasEventBeforeFocus = true;\n originalFocus.apply(this, arguments as unknown as [options?: FocusOptions | undefined]);\n },\n });\n\n documentObject.addEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"click\", handleClickEvent, true);\n\n windowObject.addEventListener(\"focus\", handleFocusEvent, true);\n windowObject.addEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.addEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.addEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.addEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.addEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n windowObject.addEventListener(\n \"beforeunload\",\n () => {\n tearDownWindowFocusTracking(element);\n },\n { once: true },\n );\n\n hasSetupGlobalListeners.set(windowObject, { focus: originalFocus });\n}\n\nfunction tearDownWindowFocusTracking(element?: HTMLElement | null, loadListener?: () => void) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n const documentObject = getOwnerDocument(element);\n\n if (loadListener) {\n documentObject.removeEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n if (!hasSetupGlobalListeners.has(windowObject)) {\n return;\n }\n\n const entry = hasSetupGlobalListeners.get(windowObject)!;\n // Mirror the setup path: defineProperty (not assignment) restores the original\n // focus even if it had been replaced with a getter-only accessor.\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: entry.focus,\n });\n\n documentObject.removeEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"click\", handleClickEvent, true);\n\n windowObject.removeEventListener(\"focus\", handleFocusEvent, true);\n windowObject.removeEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.removeEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.removeEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n hasSetupGlobalListeners.delete(windowObject);\n}\n\n/**\n * Adds a window (i.e. iframe) to the list of windows that are being tracked for focus visible.\n */\nexport function addWindowFocusTracking(element?: HTMLElement | null): () => void {\n const documentObject = getOwnerDocument(element);\n let loadListener: (() => void) | undefined;\n\n if (documentObject.readyState !== \"loading\") {\n setupGlobalFocusEvents(element);\n } else {\n loadListener = () => {\n setupGlobalFocusEvents(element);\n };\n documentObject.addEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n return () => tearDownWindowFocusTracking(element, loadListener);\n}\n\nexport function setupGlobalFocusListeners(): void {\n addWindowFocusTracking();\n}\n\nif (typeof document !== \"undefined\") {\n addWindowFocusTracking();\n}\n\n/**\n * If true, keyboard focus is visible.\n */\nexport function isFocusVisible(): boolean {\n return currentModality !== \"pointer\";\n}\n\n/**\n * Gets the current interaction modality.\n */\nexport function getInteractionModality(): Modality | null {\n return currentModality;\n}\n\n/**\n * Sets the current interaction modality.\n */\nexport function setInteractionModality(modality: Modality): void {\n currentModality = modality;\n currentPointerType = modality === \"pointer\" ? \"mouse\" : modality;\n triggerChangeHandlers(modality, null);\n}\n\n/**\n * Gets the current pointer type.\n */\nexport function getPointerType(): PointerType {\n return currentPointerType;\n}\n\nfunction isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent): boolean {\n if (!e) {\n return true;\n }\n\n const target = \"target\" in e ? (e.target as Element | null) : null;\n const ownerDocument = target ? getOwnerDocument(target) : document;\n const ownerWindow = target ? getOwnerWindow(target) : window;\n\n const IHTMLInputElement = ownerWindow.HTMLInputElement;\n const IHTMLTextAreaElement = ownerWindow.HTMLTextAreaElement;\n const IHTMLElement = ownerWindow.HTMLElement;\n const IKeyboardEvent = ownerWindow.KeyboardEvent;\n\n const nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n ]);\n\n isTextInput =\n isTextInput ||\n (ownerDocument.activeElement instanceof IHTMLInputElement &&\n !nonTextInputTypes.has(ownerDocument.activeElement.type)) ||\n ownerDocument.activeElement instanceof IHTMLTextAreaElement ||\n (ownerDocument.activeElement instanceof IHTMLElement &&\n ownerDocument.activeElement.isContentEditable);\n\n return !(\n isTextInput &&\n modality === \"keyboard\" &&\n e instanceof IKeyboardEvent &&\n !FOCUS_VISIBLE_INPUT_KEYS[e.key]\n );\n}\n\n/**\n * Listens for trigger change and reports if focus is visible.\n */\nexport function createFocusVisibleListener(\n handler: FocusVisibleHandler,\n opts?: { isTextInput?: boolean },\n): () => void {\n setupGlobalFocusEvents();\n const listener: Handler = (modality: Modality, e: HandlerEvent) => {\n if (!isKeyboardFocusEvent(!!opts?.isTextInput, modality, e)) {\n return;\n }\n handler(isFocusVisible());\n };\n changeHandlers.add(listener);\n return () => {\n changeHandlers.delete(listener);\n };\n}\n\n/**\n * Manages focus visible state for the page.\n */\nexport function createFocusVisible(props: FocusVisibleProps = {}): FocusVisibleResult {\n if (isServer) {\n return { isFocusVisible: () => false };\n }\n\n const { isTextInput, autoFocus } = props;\n const [isVisible, setIsVisible] = createSignal<boolean>(autoFocus || isFocusVisible());\n\n createEffect(() => {\n const cleanup = createFocusVisibleListener(setIsVisible, { isTextInput });\n onCleanup(cleanup);\n });\n\n return { isFocusVisible: isVisible };\n}\n\n/**\n * Tracks the current interaction modality.\n */\nexport function createInteractionModality(): InteractionModalityResult {\n if (isServer) {\n return {\n modality: () => null,\n };\n }\n\n const [modality, setModality] = createSignal<Modality | null>(currentModality);\n\n createEffect(() => {\n setupGlobalFocusEvents();\n const handler: Handler = (newModality: Modality) => {\n setModality(newModality);\n };\n changeHandlers.add(handler);\n onCleanup(() => {\n changeHandlers.delete(handler);\n });\n });\n\n return {\n modality,\n };\n}\n\n/**\n * Adds a listener for modality changes.\n */\nexport function addModalityListener(handler: (modality: Modality) => void): () => void {\n const wrapped: Handler = (modality) => {\n handler(modality);\n };\n changeHandlers.add(wrapped);\n return () => {\n changeHandlers.delete(wrapped);\n };\n}\n\n/**\n * Hook to track whether the user is currently interacting with the keyboard.\n */\nexport function useIsKeyboardFocused(): Accessor<boolean> {\n if (isServer) {\n return () => false;\n }\n\n const { modality } = createInteractionModality();\n return () => modality() === \"keyboard\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createInteractionModality.js","names":[],"sources":["../../src/interactions/createInteractionModality.ts"],"sourcesContent":["/**\n * createInteractionModality + focus-visible tracking for solidaria\n *\n * Port of @react-aria/interactions useFocusVisible/useInteractionModality.\n * Tracks the current interaction modality (keyboard, pointer, or virtual) and\n * provides focus-visible state and listeners.\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink } from \"../utils\";\n\nexport type Modality = \"keyboard\" | \"pointer\" | \"virtual\";\nexport type PointerType = \"mouse\" | \"pen\" | \"touch\" | \"keyboard\" | \"virtual\";\ntype HandlerEvent = PointerEvent | MouseEvent | KeyboardEvent | FocusEvent | null;\ntype Handler = (modality: Modality, e: HandlerEvent) => void;\n\nexport type FocusVisibleHandler = (isFocusVisible: boolean) => void;\n\nexport interface FocusVisibleProps {\n /** Whether the element is a text input. */\n isTextInput?: boolean;\n /** Whether the element will be auto focused. */\n autoFocus?: boolean;\n}\n\nexport interface FocusVisibleResult {\n /** Whether keyboard focus is visible globally. */\n isFocusVisible: Accessor<boolean>;\n}\n\nexport interface InteractionModalityResult {\n /** The current interaction modality. */\n modality: Accessor<Modality | null>;\n}\n\nlet currentModality: Modality | null = null;\nlet currentPointerType: PointerType = \"keyboard\";\nconst changeHandlers = new Set<Handler>();\n\nexport let hasSetupGlobalListeners: Map<\n Window,\n { focus: typeof window.HTMLElement.prototype.focus }\n> = new Map();\nlet hasEventBeforeFocus = false;\nlet hasBlurredWindowRecently = false;\nlet ignoreFocusEvent = false;\n\nconst FOCUS_VISIBLE_INPUT_KEYS: Record<string, boolean> = {\n Tab: true,\n Escape: true,\n};\n\nfunction triggerChangeHandlers(modality: Modality, e: HandlerEvent) {\n for (const handler of changeHandlers) {\n handler(modality, e);\n }\n}\n\nfunction isValidKey(e: KeyboardEvent) {\n return !(\n e.metaKey ||\n (!isMac() && e.altKey) ||\n e.ctrlKey ||\n e.key === \"Control\" ||\n e.key === \"Shift\" ||\n e.key === \"Meta\"\n );\n}\n\nfunction handleKeyboardEvent(e: KeyboardEvent) {\n hasEventBeforeFocus = true;\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isValidKey(e)) {\n currentModality = \"keyboard\";\n currentPointerType = \"keyboard\";\n triggerChangeHandlers(\"keyboard\", e);\n }\n}\n\nfunction handlePointerEvent(e: PointerEvent | MouseEvent) {\n currentModality = \"pointer\";\n currentPointerType = \"pointerType\" in e ? (e.pointerType as PointerType) : \"mouse\";\n if (e.type === \"mousedown\" || e.type === \"pointerdown\") {\n hasEventBeforeFocus = true;\n triggerChangeHandlers(\"pointer\", e);\n }\n}\n\nfunction handleClickEvent(e: MouseEvent) {\n if (!e.isTrusted) {\n return;\n }\n\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isVirtualClick(e)) {\n hasEventBeforeFocus = true;\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n }\n}\n\nfunction handleFocusEvent(e: FocusEvent) {\n if (!e.isTrusted || ignoreFocusEvent) {\n return;\n }\n\n const target = e.target as EventTarget | null;\n const targetElement = target && (target as Element).nodeType ? (target as Element) : null;\n const ownerWindow = targetElement ? getOwnerWindow(targetElement) : window;\n const ownerDocument = targetElement ? getOwnerDocument(targetElement) : document;\n\n if (target === ownerWindow || target === ownerDocument) {\n return;\n }\n\n if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n triggerChangeHandlers(\"virtual\", e);\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = false;\n}\n\nfunction handleWindowBlur() {\n if (ignoreFocusEvent) {\n return;\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = true;\n}\n\nfunction setupGlobalFocusEvents(element?: HTMLElement | null) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n if (hasSetupGlobalListeners.get(windowObject)) {\n return;\n }\n\n const documentObject = getOwnerDocument(element);\n\n // Programmatic focus() calls shouldn't affect the current input modality, so we\n // patch HTMLElement.prototype.focus to record that an event preceded the focus.\n // Use Reflect.defineProperty (not assignment) so this works even when `focus` is\n // currently a getter-only accessor — e.g. when a test library's setup() has\n // instrumented it. Plain assignment throws in that case; Reflect.defineProperty\n // returns false rather than throwing (and succeeds on the configurable prototype).\n const originalFocus = windowObject.HTMLElement.prototype.focus;\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: function () {\n hasEventBeforeFocus = true;\n originalFocus.apply(this, arguments as unknown as [options?: FocusOptions | undefined]);\n },\n });\n\n documentObject.addEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"click\", handleClickEvent, true);\n\n windowObject.addEventListener(\"focus\", handleFocusEvent, true);\n windowObject.addEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.addEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.addEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.addEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.addEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n windowObject.addEventListener(\n \"beforeunload\",\n () => {\n tearDownWindowFocusTracking(element);\n },\n { once: true },\n );\n\n hasSetupGlobalListeners.set(windowObject, { focus: originalFocus });\n}\n\nfunction tearDownWindowFocusTracking(element?: HTMLElement | null, loadListener?: () => void) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n const documentObject = getOwnerDocument(element);\n\n if (loadListener) {\n documentObject.removeEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n if (!hasSetupGlobalListeners.has(windowObject)) {\n return;\n }\n\n const entry = hasSetupGlobalListeners.get(windowObject)!;\n // Mirror the setup path: defineProperty (not assignment) restores the original\n // focus even if it had been replaced with a getter-only accessor.\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: entry.focus,\n });\n\n documentObject.removeEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"click\", handleClickEvent, true);\n\n windowObject.removeEventListener(\"focus\", handleFocusEvent, true);\n windowObject.removeEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.removeEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.removeEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n hasSetupGlobalListeners.delete(windowObject);\n}\n\n/**\n * Adds a window (i.e. iframe) to the list of windows that are being tracked for focus visible.\n */\nexport function addWindowFocusTracking(element?: HTMLElement | null): () => void {\n const documentObject = getOwnerDocument(element);\n let loadListener: (() => void) | undefined;\n\n if (documentObject.readyState !== \"loading\") {\n setupGlobalFocusEvents(element);\n } else {\n loadListener = () => {\n setupGlobalFocusEvents(element);\n };\n documentObject.addEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n return () => tearDownWindowFocusTracking(element, loadListener);\n}\n\nexport function setupGlobalFocusListeners(): void {\n addWindowFocusTracking();\n}\n\nif (typeof document !== \"undefined\") {\n addWindowFocusTracking();\n}\n\n/**\n * If true, keyboard focus is visible.\n */\nexport function isFocusVisible(): boolean {\n return currentModality !== \"pointer\";\n}\n\n/**\n * Gets the current interaction modality.\n */\nexport function getInteractionModality(): Modality | null {\n return currentModality;\n}\n\n/**\n * Sets the current interaction modality.\n */\nexport function setInteractionModality(modality: Modality): void {\n currentModality = modality;\n currentPointerType = modality === \"pointer\" ? \"mouse\" : modality;\n triggerChangeHandlers(modality, null);\n}\n\n/**\n * Gets the current pointer type.\n */\nexport function getPointerType(): PointerType {\n return currentPointerType;\n}\n\nfunction isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent): boolean {\n if (!e) {\n return true;\n }\n\n const target = \"target\" in e ? (e.target as Element | null) : null;\n const ownerDocument = target ? getOwnerDocument(target) : document;\n const ownerWindow = target ? getOwnerWindow(target) : window;\n\n const IHTMLInputElement = ownerWindow.HTMLInputElement;\n const IHTMLTextAreaElement = ownerWindow.HTMLTextAreaElement;\n const IHTMLElement = ownerWindow.HTMLElement;\n const IKeyboardEvent = ownerWindow.KeyboardEvent;\n\n const nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n ]);\n\n isTextInput =\n isTextInput ||\n (ownerDocument.activeElement instanceof IHTMLInputElement &&\n !nonTextInputTypes.has(ownerDocument.activeElement.type)) ||\n ownerDocument.activeElement instanceof IHTMLTextAreaElement ||\n (ownerDocument.activeElement instanceof IHTMLElement &&\n ownerDocument.activeElement.isContentEditable);\n\n return !(\n isTextInput &&\n modality === \"keyboard\" &&\n e instanceof IKeyboardEvent &&\n !FOCUS_VISIBLE_INPUT_KEYS[e.key]\n );\n}\n\n/**\n * Listens for trigger change and reports if focus is visible.\n */\nexport function createFocusVisibleListener(\n handler: FocusVisibleHandler,\n opts?: { isTextInput?: boolean },\n): () => void {\n setupGlobalFocusEvents();\n const listener: Handler = (modality: Modality, e: HandlerEvent) => {\n if (!isKeyboardFocusEvent(!!opts?.isTextInput, modality, e)) {\n return;\n }\n handler(isFocusVisible());\n };\n changeHandlers.add(listener);\n return () => {\n changeHandlers.delete(listener);\n };\n}\n\n/**\n * Manages focus visible state for the page.\n */\nexport function createFocusVisible(props: FocusVisibleProps = {}): FocusVisibleResult {\n if (isServer) {\n return { isFocusVisible: () => false };\n }\n\n // autoFocus seeds the initial value once; isTextInput is read inside the effect\n // so it re-subscribes reactively (a top-level destructure would freeze it — the\n // body runs once). Mirrors upstream useFocusVisible's [isTextInput] dep.\n const [isVisible, setIsVisible] = createSignal<boolean>(props.autoFocus || isFocusVisible());\n\n createEffect(() => {\n const cleanup = createFocusVisibleListener(setIsVisible, { isTextInput: props.isTextInput });\n onCleanup(cleanup);\n });\n\n return { isFocusVisible: isVisible };\n}\n\n/**\n * Tracks the current interaction modality.\n */\nexport function createInteractionModality(): InteractionModalityResult {\n if (isServer) {\n return {\n modality: () => null,\n };\n }\n\n const [modality, setModality] = createSignal<Modality | null>(currentModality);\n\n createEffect(() => {\n setupGlobalFocusEvents();\n const handler: Handler = (newModality: Modality) => {\n setModality(newModality);\n };\n changeHandlers.add(handler);\n onCleanup(() => {\n changeHandlers.delete(handler);\n });\n });\n\n return {\n modality,\n };\n}\n\n/**\n * Adds a listener for modality changes.\n */\nexport function addModalityListener(handler: (modality: Modality) => void): () => void {\n const wrapped: Handler = (modality) => {\n handler(modality);\n };\n changeHandlers.add(wrapped);\n return () => {\n changeHandlers.delete(wrapped);\n };\n}\n\n/**\n * Hook to track whether the user is currently interacting with the keyboard.\n */\nexport function useIsKeyboardFocused(): Accessor<boolean> {\n if (isServer) {\n return () => false;\n }\n\n const { modality } = createInteractionModality();\n return () => modality() === \"keyboard\";\n}\n"],"mappings":"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"}
@@ -218,10 +218,9 @@ function createFocusVisibleListener(handler, opts) {
218
218
  */
219
219
  function createFocusVisible(props = {}) {
220
220
  if (isServer) return { isFocusVisible: () => false };
221
- const { isTextInput, autoFocus } = props;
222
- const [isVisible, setIsVisible] = createSignal(autoFocus || isFocusVisible());
221
+ const [isVisible, setIsVisible] = createSignal(props.autoFocus || isFocusVisible());
223
222
  createEffect(() => {
224
- onCleanup(createFocusVisibleListener(setIsVisible, { isTextInput }));
223
+ onCleanup(createFocusVisibleListener(setIsVisible, { isTextInput: props.isTextInput }));
225
224
  });
226
225
  return { isFocusVisible: isVisible };
227
226
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createInteractionModality.jsx","names":[],"sources":["../../src/interactions/createInteractionModality.ts"],"sourcesContent":["/**\n * createInteractionModality + focus-visible tracking for solidaria\n *\n * Port of @react-aria/interactions useFocusVisible/useInteractionModality.\n * Tracks the current interaction modality (keyboard, pointer, or virtual) and\n * provides focus-visible state and listeners.\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink } from \"../utils\";\n\nexport type Modality = \"keyboard\" | \"pointer\" | \"virtual\";\nexport type PointerType = \"mouse\" | \"pen\" | \"touch\" | \"keyboard\" | \"virtual\";\ntype HandlerEvent = PointerEvent | MouseEvent | KeyboardEvent | FocusEvent | null;\ntype Handler = (modality: Modality, e: HandlerEvent) => void;\n\nexport type FocusVisibleHandler = (isFocusVisible: boolean) => void;\n\nexport interface FocusVisibleProps {\n /** Whether the element is a text input. */\n isTextInput?: boolean;\n /** Whether the element will be auto focused. */\n autoFocus?: boolean;\n}\n\nexport interface FocusVisibleResult {\n /** Whether keyboard focus is visible globally. */\n isFocusVisible: Accessor<boolean>;\n}\n\nexport interface InteractionModalityResult {\n /** The current interaction modality. */\n modality: Accessor<Modality | null>;\n}\n\nlet currentModality: Modality | null = null;\nlet currentPointerType: PointerType = \"keyboard\";\nconst changeHandlers = new Set<Handler>();\n\nexport let hasSetupGlobalListeners: Map<\n Window,\n { focus: typeof window.HTMLElement.prototype.focus }\n> = new Map();\nlet hasEventBeforeFocus = false;\nlet hasBlurredWindowRecently = false;\nlet ignoreFocusEvent = false;\n\nconst FOCUS_VISIBLE_INPUT_KEYS: Record<string, boolean> = {\n Tab: true,\n Escape: true,\n};\n\nfunction triggerChangeHandlers(modality: Modality, e: HandlerEvent) {\n for (const handler of changeHandlers) {\n handler(modality, e);\n }\n}\n\nfunction isValidKey(e: KeyboardEvent) {\n return !(\n e.metaKey ||\n (!isMac() && e.altKey) ||\n e.ctrlKey ||\n e.key === \"Control\" ||\n e.key === \"Shift\" ||\n e.key === \"Meta\"\n );\n}\n\nfunction handleKeyboardEvent(e: KeyboardEvent) {\n hasEventBeforeFocus = true;\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isValidKey(e)) {\n currentModality = \"keyboard\";\n currentPointerType = \"keyboard\";\n triggerChangeHandlers(\"keyboard\", e);\n }\n}\n\nfunction handlePointerEvent(e: PointerEvent | MouseEvent) {\n currentModality = \"pointer\";\n currentPointerType = \"pointerType\" in e ? (e.pointerType as PointerType) : \"mouse\";\n if (e.type === \"mousedown\" || e.type === \"pointerdown\") {\n hasEventBeforeFocus = true;\n triggerChangeHandlers(\"pointer\", e);\n }\n}\n\nfunction handleClickEvent(e: MouseEvent) {\n if (!e.isTrusted) {\n return;\n }\n\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isVirtualClick(e)) {\n hasEventBeforeFocus = true;\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n }\n}\n\nfunction handleFocusEvent(e: FocusEvent) {\n if (!e.isTrusted || ignoreFocusEvent) {\n return;\n }\n\n const target = e.target as EventTarget | null;\n const targetElement = target && (target as Element).nodeType ? (target as Element) : null;\n const ownerWindow = targetElement ? getOwnerWindow(targetElement) : window;\n const ownerDocument = targetElement ? getOwnerDocument(targetElement) : document;\n\n if (target === ownerWindow || target === ownerDocument) {\n return;\n }\n\n if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n triggerChangeHandlers(\"virtual\", e);\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = false;\n}\n\nfunction handleWindowBlur() {\n if (ignoreFocusEvent) {\n return;\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = true;\n}\n\nfunction setupGlobalFocusEvents(element?: HTMLElement | null) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n if (hasSetupGlobalListeners.get(windowObject)) {\n return;\n }\n\n const documentObject = getOwnerDocument(element);\n\n // Programmatic focus() calls shouldn't affect the current input modality, so we\n // patch HTMLElement.prototype.focus to record that an event preceded the focus.\n // Use Reflect.defineProperty (not assignment) so this works even when `focus` is\n // currently a getter-only accessor — e.g. when a test library's setup() has\n // instrumented it. Plain assignment throws in that case; Reflect.defineProperty\n // returns false rather than throwing (and succeeds on the configurable prototype).\n const originalFocus = windowObject.HTMLElement.prototype.focus;\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: function () {\n hasEventBeforeFocus = true;\n originalFocus.apply(this, arguments as unknown as [options?: FocusOptions | undefined]);\n },\n });\n\n documentObject.addEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"click\", handleClickEvent, true);\n\n windowObject.addEventListener(\"focus\", handleFocusEvent, true);\n windowObject.addEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.addEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.addEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.addEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.addEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n windowObject.addEventListener(\n \"beforeunload\",\n () => {\n tearDownWindowFocusTracking(element);\n },\n { once: true },\n );\n\n hasSetupGlobalListeners.set(windowObject, { focus: originalFocus });\n}\n\nfunction tearDownWindowFocusTracking(element?: HTMLElement | null, loadListener?: () => void) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n const documentObject = getOwnerDocument(element);\n\n if (loadListener) {\n documentObject.removeEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n if (!hasSetupGlobalListeners.has(windowObject)) {\n return;\n }\n\n const entry = hasSetupGlobalListeners.get(windowObject)!;\n // Mirror the setup path: defineProperty (not assignment) restores the original\n // focus even if it had been replaced with a getter-only accessor.\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: entry.focus,\n });\n\n documentObject.removeEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"click\", handleClickEvent, true);\n\n windowObject.removeEventListener(\"focus\", handleFocusEvent, true);\n windowObject.removeEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.removeEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.removeEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n hasSetupGlobalListeners.delete(windowObject);\n}\n\n/**\n * Adds a window (i.e. iframe) to the list of windows that are being tracked for focus visible.\n */\nexport function addWindowFocusTracking(element?: HTMLElement | null): () => void {\n const documentObject = getOwnerDocument(element);\n let loadListener: (() => void) | undefined;\n\n if (documentObject.readyState !== \"loading\") {\n setupGlobalFocusEvents(element);\n } else {\n loadListener = () => {\n setupGlobalFocusEvents(element);\n };\n documentObject.addEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n return () => tearDownWindowFocusTracking(element, loadListener);\n}\n\nexport function setupGlobalFocusListeners(): void {\n addWindowFocusTracking();\n}\n\nif (typeof document !== \"undefined\") {\n addWindowFocusTracking();\n}\n\n/**\n * If true, keyboard focus is visible.\n */\nexport function isFocusVisible(): boolean {\n return currentModality !== \"pointer\";\n}\n\n/**\n * Gets the current interaction modality.\n */\nexport function getInteractionModality(): Modality | null {\n return currentModality;\n}\n\n/**\n * Sets the current interaction modality.\n */\nexport function setInteractionModality(modality: Modality): void {\n currentModality = modality;\n currentPointerType = modality === \"pointer\" ? \"mouse\" : modality;\n triggerChangeHandlers(modality, null);\n}\n\n/**\n * Gets the current pointer type.\n */\nexport function getPointerType(): PointerType {\n return currentPointerType;\n}\n\nfunction isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent): boolean {\n if (!e) {\n return true;\n }\n\n const target = \"target\" in e ? (e.target as Element | null) : null;\n const ownerDocument = target ? getOwnerDocument(target) : document;\n const ownerWindow = target ? getOwnerWindow(target) : window;\n\n const IHTMLInputElement = ownerWindow.HTMLInputElement;\n const IHTMLTextAreaElement = ownerWindow.HTMLTextAreaElement;\n const IHTMLElement = ownerWindow.HTMLElement;\n const IKeyboardEvent = ownerWindow.KeyboardEvent;\n\n const nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n ]);\n\n isTextInput =\n isTextInput ||\n (ownerDocument.activeElement instanceof IHTMLInputElement &&\n !nonTextInputTypes.has(ownerDocument.activeElement.type)) ||\n ownerDocument.activeElement instanceof IHTMLTextAreaElement ||\n (ownerDocument.activeElement instanceof IHTMLElement &&\n ownerDocument.activeElement.isContentEditable);\n\n return !(\n isTextInput &&\n modality === \"keyboard\" &&\n e instanceof IKeyboardEvent &&\n !FOCUS_VISIBLE_INPUT_KEYS[e.key]\n );\n}\n\n/**\n * Listens for trigger change and reports if focus is visible.\n */\nexport function createFocusVisibleListener(\n handler: FocusVisibleHandler,\n opts?: { isTextInput?: boolean },\n): () => void {\n setupGlobalFocusEvents();\n const listener: Handler = (modality: Modality, e: HandlerEvent) => {\n if (!isKeyboardFocusEvent(!!opts?.isTextInput, modality, e)) {\n return;\n }\n handler(isFocusVisible());\n };\n changeHandlers.add(listener);\n return () => {\n changeHandlers.delete(listener);\n };\n}\n\n/**\n * Manages focus visible state for the page.\n */\nexport function createFocusVisible(props: FocusVisibleProps = {}): FocusVisibleResult {\n if (isServer) {\n return { isFocusVisible: () => false };\n }\n\n const { isTextInput, autoFocus } = props;\n const [isVisible, setIsVisible] = createSignal<boolean>(autoFocus || isFocusVisible());\n\n createEffect(() => {\n const cleanup = createFocusVisibleListener(setIsVisible, { isTextInput });\n onCleanup(cleanup);\n });\n\n return { isFocusVisible: isVisible };\n}\n\n/**\n * Tracks the current interaction modality.\n */\nexport function createInteractionModality(): InteractionModalityResult {\n if (isServer) {\n return {\n modality: () => null,\n };\n }\n\n const [modality, setModality] = createSignal<Modality | null>(currentModality);\n\n createEffect(() => {\n setupGlobalFocusEvents();\n const handler: Handler = (newModality: Modality) => {\n setModality(newModality);\n };\n changeHandlers.add(handler);\n onCleanup(() => {\n changeHandlers.delete(handler);\n });\n });\n\n return {\n modality,\n };\n}\n\n/**\n * Adds a listener for modality changes.\n */\nexport function addModalityListener(handler: (modality: Modality) => void): () => void {\n const wrapped: Handler = (modality) => {\n handler(modality);\n };\n changeHandlers.add(wrapped);\n return () => {\n changeHandlers.delete(wrapped);\n };\n}\n\n/**\n * Hook to track whether the user is currently interacting with the keyboard.\n */\nexport function useIsKeyboardFocused(): Accessor<boolean> {\n if (isServer) {\n return () => false;\n }\n\n const { modality } = createInteractionModality();\n return () => modality() === \"keyboard\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createInteractionModality.jsx","names":[],"sources":["../../src/interactions/createInteractionModality.ts"],"sourcesContent":["/**\n * createInteractionModality + focus-visible tracking for solidaria\n *\n * Port of @react-aria/interactions useFocusVisible/useInteractionModality.\n * Tracks the current interaction modality (keyboard, pointer, or virtual) and\n * provides focus-visible state and listeners.\n */\n\nimport { type Accessor, createSignal, createEffect, onCleanup } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { getOwnerDocument, getOwnerWindow, isMac, isVirtualClick, openLink } from \"../utils\";\n\nexport type Modality = \"keyboard\" | \"pointer\" | \"virtual\";\nexport type PointerType = \"mouse\" | \"pen\" | \"touch\" | \"keyboard\" | \"virtual\";\ntype HandlerEvent = PointerEvent | MouseEvent | KeyboardEvent | FocusEvent | null;\ntype Handler = (modality: Modality, e: HandlerEvent) => void;\n\nexport type FocusVisibleHandler = (isFocusVisible: boolean) => void;\n\nexport interface FocusVisibleProps {\n /** Whether the element is a text input. */\n isTextInput?: boolean;\n /** Whether the element will be auto focused. */\n autoFocus?: boolean;\n}\n\nexport interface FocusVisibleResult {\n /** Whether keyboard focus is visible globally. */\n isFocusVisible: Accessor<boolean>;\n}\n\nexport interface InteractionModalityResult {\n /** The current interaction modality. */\n modality: Accessor<Modality | null>;\n}\n\nlet currentModality: Modality | null = null;\nlet currentPointerType: PointerType = \"keyboard\";\nconst changeHandlers = new Set<Handler>();\n\nexport let hasSetupGlobalListeners: Map<\n Window,\n { focus: typeof window.HTMLElement.prototype.focus }\n> = new Map();\nlet hasEventBeforeFocus = false;\nlet hasBlurredWindowRecently = false;\nlet ignoreFocusEvent = false;\n\nconst FOCUS_VISIBLE_INPUT_KEYS: Record<string, boolean> = {\n Tab: true,\n Escape: true,\n};\n\nfunction triggerChangeHandlers(modality: Modality, e: HandlerEvent) {\n for (const handler of changeHandlers) {\n handler(modality, e);\n }\n}\n\nfunction isValidKey(e: KeyboardEvent) {\n return !(\n e.metaKey ||\n (!isMac() && e.altKey) ||\n e.ctrlKey ||\n e.key === \"Control\" ||\n e.key === \"Shift\" ||\n e.key === \"Meta\"\n );\n}\n\nfunction handleKeyboardEvent(e: KeyboardEvent) {\n hasEventBeforeFocus = true;\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isValidKey(e)) {\n currentModality = \"keyboard\";\n currentPointerType = \"keyboard\";\n triggerChangeHandlers(\"keyboard\", e);\n }\n}\n\nfunction handlePointerEvent(e: PointerEvent | MouseEvent) {\n currentModality = \"pointer\";\n currentPointerType = \"pointerType\" in e ? (e.pointerType as PointerType) : \"mouse\";\n if (e.type === \"mousedown\" || e.type === \"pointerdown\") {\n hasEventBeforeFocus = true;\n triggerChangeHandlers(\"pointer\", e);\n }\n}\n\nfunction handleClickEvent(e: MouseEvent) {\n if (!e.isTrusted) {\n return;\n }\n\n const isOpening = (openLink as { isOpening?: boolean }).isOpening;\n if (!isOpening && isVirtualClick(e)) {\n hasEventBeforeFocus = true;\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n }\n}\n\nfunction handleFocusEvent(e: FocusEvent) {\n if (!e.isTrusted || ignoreFocusEvent) {\n return;\n }\n\n const target = e.target as EventTarget | null;\n const targetElement = target && (target as Element).nodeType ? (target as Element) : null;\n const ownerWindow = targetElement ? getOwnerWindow(targetElement) : window;\n const ownerDocument = targetElement ? getOwnerDocument(targetElement) : document;\n\n if (target === ownerWindow || target === ownerDocument) {\n return;\n }\n\n if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {\n currentModality = \"virtual\";\n currentPointerType = \"virtual\";\n triggerChangeHandlers(\"virtual\", e);\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = false;\n}\n\nfunction handleWindowBlur() {\n if (ignoreFocusEvent) {\n return;\n }\n\n hasEventBeforeFocus = false;\n hasBlurredWindowRecently = true;\n}\n\nfunction setupGlobalFocusEvents(element?: HTMLElement | null) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n if (hasSetupGlobalListeners.get(windowObject)) {\n return;\n }\n\n const documentObject = getOwnerDocument(element);\n\n // Programmatic focus() calls shouldn't affect the current input modality, so we\n // patch HTMLElement.prototype.focus to record that an event preceded the focus.\n // Use Reflect.defineProperty (not assignment) so this works even when `focus` is\n // currently a getter-only accessor — e.g. when a test library's setup() has\n // instrumented it. Plain assignment throws in that case; Reflect.defineProperty\n // returns false rather than throwing (and succeeds on the configurable prototype).\n const originalFocus = windowObject.HTMLElement.prototype.focus;\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: function () {\n hasEventBeforeFocus = true;\n originalFocus.apply(this, arguments as unknown as [options?: FocusOptions | undefined]);\n },\n });\n\n documentObject.addEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.addEventListener(\"click\", handleClickEvent, true);\n\n windowObject.addEventListener(\"focus\", handleFocusEvent, true);\n windowObject.addEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.addEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.addEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.addEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.addEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.addEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n windowObject.addEventListener(\n \"beforeunload\",\n () => {\n tearDownWindowFocusTracking(element);\n },\n { once: true },\n );\n\n hasSetupGlobalListeners.set(windowObject, { focus: originalFocus });\n}\n\nfunction tearDownWindowFocusTracking(element?: HTMLElement | null, loadListener?: () => void) {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n return;\n }\n\n const windowObject = getOwnerWindow(element);\n const documentObject = getOwnerDocument(element);\n\n if (loadListener) {\n documentObject.removeEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n if (!hasSetupGlobalListeners.has(windowObject)) {\n return;\n }\n\n const entry = hasSetupGlobalListeners.get(windowObject)!;\n // Mirror the setup path: defineProperty (not assignment) restores the original\n // focus even if it had been replaced with a getter-only accessor.\n Reflect.defineProperty(windowObject.HTMLElement.prototype, \"focus\", {\n configurable: true,\n writable: true,\n value: entry.focus,\n });\n\n documentObject.removeEventListener(\"keydown\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"keyup\", handleKeyboardEvent, true);\n documentObject.removeEventListener(\"click\", handleClickEvent, true);\n\n windowObject.removeEventListener(\"focus\", handleFocusEvent, true);\n windowObject.removeEventListener(\"blur\", handleWindowBlur, false);\n\n if (typeof windowObject.PointerEvent !== \"undefined\") {\n documentObject.removeEventListener(\"pointerdown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointermove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"pointerup\", handlePointerEvent, true);\n } else {\n documentObject.removeEventListener(\"mousedown\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mousemove\", handlePointerEvent, true);\n documentObject.removeEventListener(\"mouseup\", handlePointerEvent, true);\n }\n\n hasSetupGlobalListeners.delete(windowObject);\n}\n\n/**\n * Adds a window (i.e. iframe) to the list of windows that are being tracked for focus visible.\n */\nexport function addWindowFocusTracking(element?: HTMLElement | null): () => void {\n const documentObject = getOwnerDocument(element);\n let loadListener: (() => void) | undefined;\n\n if (documentObject.readyState !== \"loading\") {\n setupGlobalFocusEvents(element);\n } else {\n loadListener = () => {\n setupGlobalFocusEvents(element);\n };\n documentObject.addEventListener(\"DOMContentLoaded\", loadListener);\n }\n\n return () => tearDownWindowFocusTracking(element, loadListener);\n}\n\nexport function setupGlobalFocusListeners(): void {\n addWindowFocusTracking();\n}\n\nif (typeof document !== \"undefined\") {\n addWindowFocusTracking();\n}\n\n/**\n * If true, keyboard focus is visible.\n */\nexport function isFocusVisible(): boolean {\n return currentModality !== \"pointer\";\n}\n\n/**\n * Gets the current interaction modality.\n */\nexport function getInteractionModality(): Modality | null {\n return currentModality;\n}\n\n/**\n * Sets the current interaction modality.\n */\nexport function setInteractionModality(modality: Modality): void {\n currentModality = modality;\n currentPointerType = modality === \"pointer\" ? \"mouse\" : modality;\n triggerChangeHandlers(modality, null);\n}\n\n/**\n * Gets the current pointer type.\n */\nexport function getPointerType(): PointerType {\n return currentPointerType;\n}\n\nfunction isKeyboardFocusEvent(isTextInput: boolean, modality: Modality, e: HandlerEvent): boolean {\n if (!e) {\n return true;\n }\n\n const target = \"target\" in e ? (e.target as Element | null) : null;\n const ownerDocument = target ? getOwnerDocument(target) : document;\n const ownerWindow = target ? getOwnerWindow(target) : window;\n\n const IHTMLInputElement = ownerWindow.HTMLInputElement;\n const IHTMLTextAreaElement = ownerWindow.HTMLTextAreaElement;\n const IHTMLElement = ownerWindow.HTMLElement;\n const IKeyboardEvent = ownerWindow.KeyboardEvent;\n\n const nonTextInputTypes = new Set([\n \"checkbox\",\n \"radio\",\n \"range\",\n \"color\",\n \"file\",\n \"image\",\n \"button\",\n \"submit\",\n \"reset\",\n ]);\n\n isTextInput =\n isTextInput ||\n (ownerDocument.activeElement instanceof IHTMLInputElement &&\n !nonTextInputTypes.has(ownerDocument.activeElement.type)) ||\n ownerDocument.activeElement instanceof IHTMLTextAreaElement ||\n (ownerDocument.activeElement instanceof IHTMLElement &&\n ownerDocument.activeElement.isContentEditable);\n\n return !(\n isTextInput &&\n modality === \"keyboard\" &&\n e instanceof IKeyboardEvent &&\n !FOCUS_VISIBLE_INPUT_KEYS[e.key]\n );\n}\n\n/**\n * Listens for trigger change and reports if focus is visible.\n */\nexport function createFocusVisibleListener(\n handler: FocusVisibleHandler,\n opts?: { isTextInput?: boolean },\n): () => void {\n setupGlobalFocusEvents();\n const listener: Handler = (modality: Modality, e: HandlerEvent) => {\n if (!isKeyboardFocusEvent(!!opts?.isTextInput, modality, e)) {\n return;\n }\n handler(isFocusVisible());\n };\n changeHandlers.add(listener);\n return () => {\n changeHandlers.delete(listener);\n };\n}\n\n/**\n * Manages focus visible state for the page.\n */\nexport function createFocusVisible(props: FocusVisibleProps = {}): FocusVisibleResult {\n if (isServer) {\n return { isFocusVisible: () => false };\n }\n\n // autoFocus seeds the initial value once; isTextInput is read inside the effect\n // so it re-subscribes reactively (a top-level destructure would freeze it — the\n // body runs once). Mirrors upstream useFocusVisible's [isTextInput] dep.\n const [isVisible, setIsVisible] = createSignal<boolean>(props.autoFocus || isFocusVisible());\n\n createEffect(() => {\n const cleanup = createFocusVisibleListener(setIsVisible, { isTextInput: props.isTextInput });\n onCleanup(cleanup);\n });\n\n return { isFocusVisible: isVisible };\n}\n\n/**\n * Tracks the current interaction modality.\n */\nexport function createInteractionModality(): InteractionModalityResult {\n if (isServer) {\n return {\n modality: () => null,\n };\n }\n\n const [modality, setModality] = createSignal<Modality | null>(currentModality);\n\n createEffect(() => {\n setupGlobalFocusEvents();\n const handler: Handler = (newModality: Modality) => {\n setModality(newModality);\n };\n changeHandlers.add(handler);\n onCleanup(() => {\n changeHandlers.delete(handler);\n });\n });\n\n return {\n modality,\n };\n}\n\n/**\n * Adds a listener for modality changes.\n */\nexport function addModalityListener(handler: (modality: Modality) => void): () => void {\n const wrapped: Handler = (modality) => {\n handler(modality);\n };\n changeHandlers.add(wrapped);\n return () => {\n changeHandlers.delete(wrapped);\n };\n}\n\n/**\n * Hook to track whether the user is currently interacting with the keyboard.\n */\nexport function useIsKeyboardFocused(): Accessor<boolean> {\n if (isServer) {\n return () => false;\n }\n\n const { modality } = createInteractionModality();\n return () => modality() === \"keyboard\";\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { i as access, t as isDevEnv } from "./env.js";
1
+ import { t as isDevEnv } from "./env.js";
2
+ import { t as access } from "./reactivity.js";
2
3
  import { createId } from "../ssr/index.js";
3
4
  import { t as createLabels } from "./createLabels.js";
4
5
  //#region src/label/createLabel.ts