@octanejs/aria 0.0.1 → 0.0.3

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 (500) hide show
  1. package/package.json +6 -3
  2. package/src/breadcrumbs/useBreadcrumbItem.ts +95 -0
  3. package/src/breadcrumbs/useBreadcrumbs.ts +51 -0
  4. package/src/button/useButton.ts +273 -0
  5. package/src/button/useToggleButton.ts +131 -0
  6. package/src/button/useToggleButtonGroup.ts +131 -0
  7. package/src/checkbox/useCheckbox.ts +114 -0
  8. package/src/checkbox/useCheckboxGroup.ts +107 -0
  9. package/src/checkbox/useCheckboxGroupItem.ts +132 -0
  10. package/src/checkbox/utils.ts +15 -0
  11. package/src/combobox/useComboBox.ts +602 -0
  12. package/src/dialog/useDialog.ts +147 -0
  13. package/src/disclosure/useDisclosure.ts +180 -0
  14. package/src/focus/FocusRing.ts +69 -0
  15. package/src/focus/FocusScope.ts +1205 -0
  16. package/src/focus/useFocusRing.ts +125 -0
  17. package/src/focus/useHasTabbableChild.ts +82 -0
  18. package/src/focus/virtualFocus.ts +38 -0
  19. package/src/form/useFormValidation.ts +205 -0
  20. package/src/grid/useGridSelectionAnnouncement.ts +177 -0
  21. package/src/grid/useGridSelectionCheckbox.ts +86 -0
  22. package/src/grid/useHighlightSelectionDescription.ts +81 -0
  23. package/src/gridlist/useGridList.ts +236 -0
  24. package/src/gridlist/useGridListItem.ts +512 -0
  25. package/src/gridlist/useGridListSection.ts +78 -0
  26. package/src/gridlist/useGridListSelectionCheckbox.ts +47 -0
  27. package/src/gridlist/utils.ts +36 -0
  28. package/src/i18n/I18nProvider.ts +97 -0
  29. package/src/i18n/server.ts +115 -0
  30. package/src/i18n/useCollator.ts +42 -0
  31. package/src/i18n/useDateFormatter.ts +64 -0
  32. package/src/i18n/useDefaultLocale.ts +93 -0
  33. package/src/i18n/useFilter.ts +107 -0
  34. package/src/i18n/useListFormatter.ts +33 -0
  35. package/src/i18n/useLocalizedStringFormatter.ts +90 -0
  36. package/src/i18n/useNumberFormatter.ts +33 -0
  37. package/src/i18n/utils.ts +67 -0
  38. package/src/index.ts +268 -0
  39. package/src/intl/breadcrumbs/ar-AE.json +3 -0
  40. package/src/intl/breadcrumbs/bg-BG.json +3 -0
  41. package/src/intl/breadcrumbs/cs-CZ.json +3 -0
  42. package/src/intl/breadcrumbs/da-DK.json +3 -0
  43. package/src/intl/breadcrumbs/de-DE.json +3 -0
  44. package/src/intl/breadcrumbs/el-GR.json +3 -0
  45. package/src/intl/breadcrumbs/en-US.json +3 -0
  46. package/src/intl/breadcrumbs/es-ES.json +3 -0
  47. package/src/intl/breadcrumbs/et-EE.json +3 -0
  48. package/src/intl/breadcrumbs/fi-FI.json +3 -0
  49. package/src/intl/breadcrumbs/fr-FR.json +3 -0
  50. package/src/intl/breadcrumbs/he-IL.json +3 -0
  51. package/src/intl/breadcrumbs/hr-HR.json +3 -0
  52. package/src/intl/breadcrumbs/hu-HU.json +3 -0
  53. package/src/intl/breadcrumbs/index.ts +75 -0
  54. package/src/intl/breadcrumbs/it-IT.json +3 -0
  55. package/src/intl/breadcrumbs/ja-JP.json +3 -0
  56. package/src/intl/breadcrumbs/ko-KR.json +3 -0
  57. package/src/intl/breadcrumbs/lt-LT.json +3 -0
  58. package/src/intl/breadcrumbs/lv-LV.json +3 -0
  59. package/src/intl/breadcrumbs/nb-NO.json +3 -0
  60. package/src/intl/breadcrumbs/nl-NL.json +3 -0
  61. package/src/intl/breadcrumbs/pl-PL.json +3 -0
  62. package/src/intl/breadcrumbs/pt-BR.json +3 -0
  63. package/src/intl/breadcrumbs/pt-PT.json +3 -0
  64. package/src/intl/breadcrumbs/ro-RO.json +3 -0
  65. package/src/intl/breadcrumbs/ru-RU.json +3 -0
  66. package/src/intl/breadcrumbs/sk-SK.json +3 -0
  67. package/src/intl/breadcrumbs/sl-SI.json +3 -0
  68. package/src/intl/breadcrumbs/sr-SP.json +3 -0
  69. package/src/intl/breadcrumbs/sv-SE.json +3 -0
  70. package/src/intl/breadcrumbs/tr-TR.json +3 -0
  71. package/src/intl/breadcrumbs/uk-UA.json +3 -0
  72. package/src/intl/breadcrumbs/zh-CN.json +3 -0
  73. package/src/intl/breadcrumbs/zh-TW.json +3 -0
  74. package/src/intl/combobox/ar-AE.json +7 -0
  75. package/src/intl/combobox/bg-BG.json +7 -0
  76. package/src/intl/combobox/cs-CZ.json +7 -0
  77. package/src/intl/combobox/da-DK.json +7 -0
  78. package/src/intl/combobox/de-DE.json +7 -0
  79. package/src/intl/combobox/el-GR.json +7 -0
  80. package/src/intl/combobox/en-US.json +7 -0
  81. package/src/intl/combobox/es-ES.json +7 -0
  82. package/src/intl/combobox/et-EE.json +7 -0
  83. package/src/intl/combobox/fi-FI.json +7 -0
  84. package/src/intl/combobox/fr-FR.json +7 -0
  85. package/src/intl/combobox/he-IL.json +7 -0
  86. package/src/intl/combobox/hr-HR.json +7 -0
  87. package/src/intl/combobox/hu-HU.json +7 -0
  88. package/src/intl/combobox/index.ts +75 -0
  89. package/src/intl/combobox/it-IT.json +7 -0
  90. package/src/intl/combobox/ja-JP.json +7 -0
  91. package/src/intl/combobox/ko-KR.json +7 -0
  92. package/src/intl/combobox/lt-LT.json +7 -0
  93. package/src/intl/combobox/lv-LV.json +7 -0
  94. package/src/intl/combobox/nb-NO.json +7 -0
  95. package/src/intl/combobox/nl-NL.json +7 -0
  96. package/src/intl/combobox/pl-PL.json +7 -0
  97. package/src/intl/combobox/pt-BR.json +7 -0
  98. package/src/intl/combobox/pt-PT.json +7 -0
  99. package/src/intl/combobox/ro-RO.json +7 -0
  100. package/src/intl/combobox/ru-RU.json +7 -0
  101. package/src/intl/combobox/sk-SK.json +7 -0
  102. package/src/intl/combobox/sl-SI.json +7 -0
  103. package/src/intl/combobox/sr-SP.json +7 -0
  104. package/src/intl/combobox/sv-SE.json +7 -0
  105. package/src/intl/combobox/tr-TR.json +7 -0
  106. package/src/intl/combobox/uk-UA.json +7 -0
  107. package/src/intl/combobox/zh-CN.json +7 -0
  108. package/src/intl/combobox/zh-TW.json +7 -0
  109. package/src/intl/grid/ar-AE.json +8 -0
  110. package/src/intl/grid/bg-BG.json +8 -0
  111. package/src/intl/grid/cs-CZ.json +8 -0
  112. package/src/intl/grid/da-DK.json +8 -0
  113. package/src/intl/grid/de-DE.json +8 -0
  114. package/src/intl/grid/el-GR.json +8 -0
  115. package/src/intl/grid/en-US.json +8 -0
  116. package/src/intl/grid/es-ES.json +8 -0
  117. package/src/intl/grid/et-EE.json +8 -0
  118. package/src/intl/grid/fi-FI.json +8 -0
  119. package/src/intl/grid/fr-FR.json +8 -0
  120. package/src/intl/grid/he-IL.json +8 -0
  121. package/src/intl/grid/hr-HR.json +8 -0
  122. package/src/intl/grid/hu-HU.json +8 -0
  123. package/src/intl/grid/index.ts +75 -0
  124. package/src/intl/grid/it-IT.json +8 -0
  125. package/src/intl/grid/ja-JP.json +8 -0
  126. package/src/intl/grid/ko-KR.json +8 -0
  127. package/src/intl/grid/lt-LT.json +8 -0
  128. package/src/intl/grid/lv-LV.json +8 -0
  129. package/src/intl/grid/nb-NO.json +8 -0
  130. package/src/intl/grid/nl-NL.json +8 -0
  131. package/src/intl/grid/pl-PL.json +8 -0
  132. package/src/intl/grid/pt-BR.json +8 -0
  133. package/src/intl/grid/pt-PT.json +8 -0
  134. package/src/intl/grid/ro-RO.json +8 -0
  135. package/src/intl/grid/ru-RU.json +8 -0
  136. package/src/intl/grid/sk-SK.json +8 -0
  137. package/src/intl/grid/sl-SI.json +8 -0
  138. package/src/intl/grid/sr-SP.json +8 -0
  139. package/src/intl/grid/sv-SE.json +8 -0
  140. package/src/intl/grid/tr-TR.json +8 -0
  141. package/src/intl/grid/uk-UA.json +8 -0
  142. package/src/intl/grid/zh-CN.json +8 -0
  143. package/src/intl/grid/zh-TW.json +8 -0
  144. package/src/intl/gridlist/ar-AE.json +4 -0
  145. package/src/intl/gridlist/bg-BG.json +4 -0
  146. package/src/intl/gridlist/cs-CZ.json +4 -0
  147. package/src/intl/gridlist/da-DK.json +4 -0
  148. package/src/intl/gridlist/de-DE.json +4 -0
  149. package/src/intl/gridlist/el-GR.json +4 -0
  150. package/src/intl/gridlist/en-US.json +4 -0
  151. package/src/intl/gridlist/es-ES.json +4 -0
  152. package/src/intl/gridlist/et-EE.json +4 -0
  153. package/src/intl/gridlist/fi-FI.json +4 -0
  154. package/src/intl/gridlist/fr-FR.json +4 -0
  155. package/src/intl/gridlist/he-IL.json +4 -0
  156. package/src/intl/gridlist/hr-HR.json +4 -0
  157. package/src/intl/gridlist/hu-HU.json +4 -0
  158. package/src/intl/gridlist/index.ts +75 -0
  159. package/src/intl/gridlist/it-IT.json +4 -0
  160. package/src/intl/gridlist/ja-JP.json +4 -0
  161. package/src/intl/gridlist/ko-KR.json +4 -0
  162. package/src/intl/gridlist/lt-LT.json +4 -0
  163. package/src/intl/gridlist/lv-LV.json +4 -0
  164. package/src/intl/gridlist/nb-NO.json +4 -0
  165. package/src/intl/gridlist/nl-NL.json +4 -0
  166. package/src/intl/gridlist/pl-PL.json +4 -0
  167. package/src/intl/gridlist/pt-BR.json +4 -0
  168. package/src/intl/gridlist/pt-PT.json +4 -0
  169. package/src/intl/gridlist/ro-RO.json +4 -0
  170. package/src/intl/gridlist/ru-RU.json +4 -0
  171. package/src/intl/gridlist/sk-SK.json +4 -0
  172. package/src/intl/gridlist/sl-SI.json +4 -0
  173. package/src/intl/gridlist/sr-SP.json +4 -0
  174. package/src/intl/gridlist/sv-SE.json +4 -0
  175. package/src/intl/gridlist/tr-TR.json +4 -0
  176. package/src/intl/gridlist/uk-UA.json +4 -0
  177. package/src/intl/gridlist/zh-CN.json +4 -0
  178. package/src/intl/gridlist/zh-TW.json +4 -0
  179. package/src/intl/menu/ar-AE.json +3 -0
  180. package/src/intl/menu/bg-BG.json +3 -0
  181. package/src/intl/menu/cs-CZ.json +3 -0
  182. package/src/intl/menu/da-DK.json +3 -0
  183. package/src/intl/menu/de-DE.json +3 -0
  184. package/src/intl/menu/el-GR.json +3 -0
  185. package/src/intl/menu/en-US.json +3 -0
  186. package/src/intl/menu/es-ES.json +3 -0
  187. package/src/intl/menu/et-EE.json +3 -0
  188. package/src/intl/menu/fi-FI.json +3 -0
  189. package/src/intl/menu/fr-FR.json +3 -0
  190. package/src/intl/menu/he-IL.json +3 -0
  191. package/src/intl/menu/hr-HR.json +3 -0
  192. package/src/intl/menu/hu-HU.json +3 -0
  193. package/src/intl/menu/index.ts +75 -0
  194. package/src/intl/menu/it-IT.json +3 -0
  195. package/src/intl/menu/ja-JP.json +3 -0
  196. package/src/intl/menu/ko-KR.json +3 -0
  197. package/src/intl/menu/lt-LT.json +3 -0
  198. package/src/intl/menu/lv-LV.json +3 -0
  199. package/src/intl/menu/nb-NO.json +3 -0
  200. package/src/intl/menu/nl-NL.json +3 -0
  201. package/src/intl/menu/pl-PL.json +3 -0
  202. package/src/intl/menu/pt-BR.json +3 -0
  203. package/src/intl/menu/pt-PT.json +3 -0
  204. package/src/intl/menu/ro-RO.json +3 -0
  205. package/src/intl/menu/ru-RU.json +3 -0
  206. package/src/intl/menu/sk-SK.json +3 -0
  207. package/src/intl/menu/sl-SI.json +3 -0
  208. package/src/intl/menu/sr-SP.json +3 -0
  209. package/src/intl/menu/sv-SE.json +3 -0
  210. package/src/intl/menu/tr-TR.json +3 -0
  211. package/src/intl/menu/uk-UA.json +3 -0
  212. package/src/intl/menu/zh-CN.json +3 -0
  213. package/src/intl/menu/zh-TW.json +3 -0
  214. package/src/intl/numberfield/ar-AE.json +5 -0
  215. package/src/intl/numberfield/bg-BG.json +5 -0
  216. package/src/intl/numberfield/cs-CZ.json +5 -0
  217. package/src/intl/numberfield/da-DK.json +5 -0
  218. package/src/intl/numberfield/de-DE.json +5 -0
  219. package/src/intl/numberfield/el-GR.json +5 -0
  220. package/src/intl/numberfield/en-US.json +5 -0
  221. package/src/intl/numberfield/es-ES.json +5 -0
  222. package/src/intl/numberfield/et-EE.json +5 -0
  223. package/src/intl/numberfield/fi-FI.json +5 -0
  224. package/src/intl/numberfield/fr-FR.json +5 -0
  225. package/src/intl/numberfield/he-IL.json +5 -0
  226. package/src/intl/numberfield/hr-HR.json +5 -0
  227. package/src/intl/numberfield/hu-HU.json +5 -0
  228. package/src/intl/numberfield/index.ts +75 -0
  229. package/src/intl/numberfield/it-IT.json +5 -0
  230. package/src/intl/numberfield/ja-JP.json +5 -0
  231. package/src/intl/numberfield/ko-KR.json +5 -0
  232. package/src/intl/numberfield/lt-LT.json +5 -0
  233. package/src/intl/numberfield/lv-LV.json +5 -0
  234. package/src/intl/numberfield/nb-NO.json +5 -0
  235. package/src/intl/numberfield/nl-NL.json +5 -0
  236. package/src/intl/numberfield/pl-PL.json +5 -0
  237. package/src/intl/numberfield/pt-BR.json +5 -0
  238. package/src/intl/numberfield/pt-PT.json +5 -0
  239. package/src/intl/numberfield/ro-RO.json +5 -0
  240. package/src/intl/numberfield/ru-RU.json +5 -0
  241. package/src/intl/numberfield/sk-SK.json +5 -0
  242. package/src/intl/numberfield/sl-SI.json +5 -0
  243. package/src/intl/numberfield/sr-SP.json +5 -0
  244. package/src/intl/numberfield/sv-SE.json +5 -0
  245. package/src/intl/numberfield/tr-TR.json +5 -0
  246. package/src/intl/numberfield/uk-UA.json +5 -0
  247. package/src/intl/numberfield/zh-CN.json +5 -0
  248. package/src/intl/numberfield/zh-TW.json +5 -0
  249. package/src/intl/overlays/ar-AE.json +3 -0
  250. package/src/intl/overlays/bg-BG.json +3 -0
  251. package/src/intl/overlays/cs-CZ.json +3 -0
  252. package/src/intl/overlays/da-DK.json +3 -0
  253. package/src/intl/overlays/de-DE.json +3 -0
  254. package/src/intl/overlays/el-GR.json +3 -0
  255. package/src/intl/overlays/en-US.json +3 -0
  256. package/src/intl/overlays/es-ES.json +3 -0
  257. package/src/intl/overlays/et-EE.json +3 -0
  258. package/src/intl/overlays/fi-FI.json +3 -0
  259. package/src/intl/overlays/fr-FR.json +3 -0
  260. package/src/intl/overlays/he-IL.json +3 -0
  261. package/src/intl/overlays/hr-HR.json +3 -0
  262. package/src/intl/overlays/hu-HU.json +3 -0
  263. package/src/intl/overlays/index.ts +75 -0
  264. package/src/intl/overlays/it-IT.json +3 -0
  265. package/src/intl/overlays/ja-JP.json +3 -0
  266. package/src/intl/overlays/ko-KR.json +3 -0
  267. package/src/intl/overlays/lt-LT.json +3 -0
  268. package/src/intl/overlays/lv-LV.json +3 -0
  269. package/src/intl/overlays/nb-NO.json +3 -0
  270. package/src/intl/overlays/nl-NL.json +3 -0
  271. package/src/intl/overlays/pl-PL.json +3 -0
  272. package/src/intl/overlays/pt-BR.json +3 -0
  273. package/src/intl/overlays/pt-PT.json +3 -0
  274. package/src/intl/overlays/ro-RO.json +3 -0
  275. package/src/intl/overlays/ru-RU.json +3 -0
  276. package/src/intl/overlays/sk-SK.json +3 -0
  277. package/src/intl/overlays/sl-SI.json +3 -0
  278. package/src/intl/overlays/sr-SP.json +3 -0
  279. package/src/intl/overlays/sv-SE.json +3 -0
  280. package/src/intl/overlays/tr-TR.json +3 -0
  281. package/src/intl/overlays/uk-UA.json +3 -0
  282. package/src/intl/overlays/zh-CN.json +3 -0
  283. package/src/intl/overlays/zh-TW.json +3 -0
  284. package/src/intl/searchfield/ar-AE.json +3 -0
  285. package/src/intl/searchfield/bg-BG.json +3 -0
  286. package/src/intl/searchfield/cs-CZ.json +3 -0
  287. package/src/intl/searchfield/da-DK.json +3 -0
  288. package/src/intl/searchfield/de-DE.json +3 -0
  289. package/src/intl/searchfield/el-GR.json +3 -0
  290. package/src/intl/searchfield/en-US.json +3 -0
  291. package/src/intl/searchfield/es-ES.json +3 -0
  292. package/src/intl/searchfield/et-EE.json +3 -0
  293. package/src/intl/searchfield/fi-FI.json +3 -0
  294. package/src/intl/searchfield/fr-FR.json +3 -0
  295. package/src/intl/searchfield/he-IL.json +3 -0
  296. package/src/intl/searchfield/hr-HR.json +3 -0
  297. package/src/intl/searchfield/hu-HU.json +3 -0
  298. package/src/intl/searchfield/index.ts +75 -0
  299. package/src/intl/searchfield/it-IT.json +3 -0
  300. package/src/intl/searchfield/ja-JP.json +3 -0
  301. package/src/intl/searchfield/ko-KR.json +3 -0
  302. package/src/intl/searchfield/lt-LT.json +3 -0
  303. package/src/intl/searchfield/lv-LV.json +3 -0
  304. package/src/intl/searchfield/nb-NO.json +3 -0
  305. package/src/intl/searchfield/nl-NL.json +3 -0
  306. package/src/intl/searchfield/pl-PL.json +3 -0
  307. package/src/intl/searchfield/pt-BR.json +3 -0
  308. package/src/intl/searchfield/pt-PT.json +3 -0
  309. package/src/intl/searchfield/ro-RO.json +3 -0
  310. package/src/intl/searchfield/ru-RU.json +3 -0
  311. package/src/intl/searchfield/sk-SK.json +3 -0
  312. package/src/intl/searchfield/sl-SI.json +3 -0
  313. package/src/intl/searchfield/sr-SP.json +3 -0
  314. package/src/intl/searchfield/sv-SE.json +3 -0
  315. package/src/intl/searchfield/tr-TR.json +3 -0
  316. package/src/intl/searchfield/uk-UA.json +3 -0
  317. package/src/intl/searchfield/zh-CN.json +3 -0
  318. package/src/intl/searchfield/zh-TW.json +3 -0
  319. package/src/intl/spinbutton/ar-AE.json +3 -0
  320. package/src/intl/spinbutton/bg-BG.json +3 -0
  321. package/src/intl/spinbutton/cs-CZ.json +3 -0
  322. package/src/intl/spinbutton/da-DK.json +3 -0
  323. package/src/intl/spinbutton/de-DE.json +3 -0
  324. package/src/intl/spinbutton/el-GR.json +3 -0
  325. package/src/intl/spinbutton/en-US.json +3 -0
  326. package/src/intl/spinbutton/es-ES.json +3 -0
  327. package/src/intl/spinbutton/et-EE.json +3 -0
  328. package/src/intl/spinbutton/fi-FI.json +3 -0
  329. package/src/intl/spinbutton/fr-FR.json +3 -0
  330. package/src/intl/spinbutton/he-IL.json +3 -0
  331. package/src/intl/spinbutton/hr-HR.json +3 -0
  332. package/src/intl/spinbutton/hu-HU.json +3 -0
  333. package/src/intl/spinbutton/index.ts +75 -0
  334. package/src/intl/spinbutton/it-IT.json +3 -0
  335. package/src/intl/spinbutton/ja-JP.json +3 -0
  336. package/src/intl/spinbutton/ko-KR.json +3 -0
  337. package/src/intl/spinbutton/lt-LT.json +3 -0
  338. package/src/intl/spinbutton/lv-LV.json +3 -0
  339. package/src/intl/spinbutton/nb-NO.json +3 -0
  340. package/src/intl/spinbutton/nl-NL.json +3 -0
  341. package/src/intl/spinbutton/pl-PL.json +3 -0
  342. package/src/intl/spinbutton/pt-BR.json +3 -0
  343. package/src/intl/spinbutton/pt-PT.json +3 -0
  344. package/src/intl/spinbutton/ro-RO.json +3 -0
  345. package/src/intl/spinbutton/ru-RU.json +3 -0
  346. package/src/intl/spinbutton/sk-SK.json +3 -0
  347. package/src/intl/spinbutton/sl-SI.json +3 -0
  348. package/src/intl/spinbutton/sr-SP.json +3 -0
  349. package/src/intl/spinbutton/sv-SE.json +3 -0
  350. package/src/intl/spinbutton/tr-TR.json +3 -0
  351. package/src/intl/spinbutton/uk-UA.json +3 -0
  352. package/src/intl/spinbutton/zh-CN.json +3 -0
  353. package/src/intl/spinbutton/zh-TW.json +3 -0
  354. package/src/intl/tag/ar-AE.json +4 -0
  355. package/src/intl/tag/bg-BG.json +4 -0
  356. package/src/intl/tag/cs-CZ.json +4 -0
  357. package/src/intl/tag/da-DK.json +4 -0
  358. package/src/intl/tag/de-DE.json +4 -0
  359. package/src/intl/tag/el-GR.json +4 -0
  360. package/src/intl/tag/en-US.json +4 -0
  361. package/src/intl/tag/es-ES.json +4 -0
  362. package/src/intl/tag/et-EE.json +4 -0
  363. package/src/intl/tag/fi-FI.json +4 -0
  364. package/src/intl/tag/fr-FR.json +4 -0
  365. package/src/intl/tag/he-IL.json +4 -0
  366. package/src/intl/tag/hr-HR.json +4 -0
  367. package/src/intl/tag/hu-HU.json +4 -0
  368. package/src/intl/tag/index.ts +75 -0
  369. package/src/intl/tag/it-IT.json +4 -0
  370. package/src/intl/tag/ja-JP.json +4 -0
  371. package/src/intl/tag/ko-KR.json +4 -0
  372. package/src/intl/tag/lt-LT.json +4 -0
  373. package/src/intl/tag/lv-LV.json +4 -0
  374. package/src/intl/tag/nb-NO.json +4 -0
  375. package/src/intl/tag/nl-NL.json +4 -0
  376. package/src/intl/tag/pl-PL.json +4 -0
  377. package/src/intl/tag/pt-BR.json +4 -0
  378. package/src/intl/tag/pt-PT.json +4 -0
  379. package/src/intl/tag/ro-RO.json +4 -0
  380. package/src/intl/tag/ru-RU.json +4 -0
  381. package/src/intl/tag/sk-SK.json +4 -0
  382. package/src/intl/tag/sl-SI.json +4 -0
  383. package/src/intl/tag/sr-SP.json +4 -0
  384. package/src/intl/tag/sv-SE.json +4 -0
  385. package/src/intl/tag/tr-TR.json +4 -0
  386. package/src/intl/tag/uk-UA.json +4 -0
  387. package/src/intl/tag/zh-CN.json +4 -0
  388. package/src/intl/tag/zh-TW.json +4 -0
  389. package/src/label/useField.ts +67 -0
  390. package/src/label/useLabel.ts +78 -0
  391. package/src/link/useLink.ts +108 -0
  392. package/src/listbox/useListBox.ts +224 -0
  393. package/src/listbox/useListBoxSection.ts +74 -0
  394. package/src/listbox/useOption.ts +212 -0
  395. package/src/listbox/utils.ts +38 -0
  396. package/src/live-announcer/LiveAnnouncer.ts +172 -0
  397. package/src/menu/useMenu.ts +139 -0
  398. package/src/menu/useMenuItem.ts +453 -0
  399. package/src/menu/useMenuSection.ts +70 -0
  400. package/src/menu/useMenuTrigger.ts +189 -0
  401. package/src/menu/useSafelyMouseToSubmenu.ts +236 -0
  402. package/src/menu/useSubmenuTrigger.ts +357 -0
  403. package/src/menu/utils.ts +16 -0
  404. package/src/meter/useMeter.ts +43 -0
  405. package/src/numberfield/useNumberField.ts +572 -0
  406. package/src/overlays/DismissButton.ts +50 -0
  407. package/src/overlays/Overlay.ts +106 -0
  408. package/src/overlays/PortalProvider.ts +37 -0
  409. package/src/overlays/ariaHideOutside.ts +299 -0
  410. package/src/overlays/calculatePosition.ts +856 -0
  411. package/src/overlays/useCloseOnScroll.ts +75 -0
  412. package/src/overlays/useModal.ts +224 -0
  413. package/src/overlays/useModalOverlay.ts +103 -0
  414. package/src/overlays/useOverlay.ts +199 -0
  415. package/src/overlays/useOverlayPosition.ts +462 -0
  416. package/src/overlays/useOverlayTrigger.ts +94 -0
  417. package/src/overlays/usePopover.ts +170 -0
  418. package/src/overlays/usePreventScroll.ts +316 -0
  419. package/src/progress/useProgressBar.ts +115 -0
  420. package/src/radio/useRadio.ts +219 -0
  421. package/src/radio/useRadioGroup.ts +184 -0
  422. package/src/radio/utils.ts +15 -0
  423. package/src/searchfield/useSearchField.ts +156 -0
  424. package/src/select/HiddenSelect.ts +261 -0
  425. package/src/select/useSelect.ts +332 -0
  426. package/src/selection/DOMLayoutDelegate.ts +51 -0
  427. package/src/selection/ListKeyboardDelegate.ts +392 -0
  428. package/src/selection/useSelectableCollection.ts +750 -0
  429. package/src/selection/useSelectableItem.ts +499 -0
  430. package/src/selection/useSelectableList.ts +132 -0
  431. package/src/selection/useTypeSelect.ts +192 -0
  432. package/src/selection/utils.ts +50 -0
  433. package/src/separator/useSeparator.ts +41 -0
  434. package/src/slider/useSlider.ts +277 -0
  435. package/src/slider/useSliderThumb.ts +375 -0
  436. package/src/slider/utils.ts +20 -0
  437. package/src/spinbutton/useSpinButton.ts +380 -0
  438. package/src/stately/checkbox/useCheckboxGroupState.ts +177 -0
  439. package/src/stately/collections/CollectionBuilder.ts +332 -0
  440. package/src/stately/collections/Item.ts +78 -0
  441. package/src/stately/collections/Section.ts +52 -0
  442. package/src/stately/collections/getChildNodes.ts +94 -0
  443. package/src/stately/collections/getItemCount.ts +29 -0
  444. package/src/stately/collections/types.ts +20 -0
  445. package/src/stately/collections/useCollection.ts +54 -0
  446. package/src/stately/combobox/useComboBoxState.ts +763 -0
  447. package/src/stately/disclosure/useDisclosureGroupState.ts +108 -0
  448. package/src/stately/disclosure/useDisclosureState.ts +84 -0
  449. package/src/stately/form/useFormValidationState.ts +331 -0
  450. package/src/stately/index.ts +111 -0
  451. package/src/stately/list/ListCollection.ts +104 -0
  452. package/src/stately/list/useListState.ts +178 -0
  453. package/src/stately/list/useSingleSelectListState.ts +101 -0
  454. package/src/stately/menu/useMenuTriggerState.ts +120 -0
  455. package/src/stately/menu/useSubmenuTriggerState.ts +116 -0
  456. package/src/stately/numberfield/useNumberFieldState.ts +430 -0
  457. package/src/stately/overlays/useOverlayTriggerState.ts +85 -0
  458. package/src/stately/radio/useRadioGroupState.ts +150 -0
  459. package/src/stately/searchfield/useSearchFieldState.ts +79 -0
  460. package/src/stately/select/useSelectState.ts +322 -0
  461. package/src/stately/selection/Selection.ts +23 -0
  462. package/src/stately/selection/SelectionManager.ts +541 -0
  463. package/src/stately/selection/types.ts +117 -0
  464. package/src/stately/selection/useMultipleSelectionState.ts +178 -0
  465. package/src/stately/slider/useSliderState.ts +458 -0
  466. package/src/stately/tabs/useTabListState.ts +149 -0
  467. package/src/stately/toggle/useToggleGroupState.ts +109 -0
  468. package/src/stately/toggle/useToggleState.ts +100 -0
  469. package/src/stately/tooltip/useTooltipTriggerState.ts +218 -0
  470. package/src/stately/tree/TreeCollection.ts +92 -0
  471. package/src/stately/tree/useTreeState.ts +121 -0
  472. package/src/stately/utils/useControlledState.ts +7 -0
  473. package/src/switch/useSwitch.ts +77 -0
  474. package/src/tabs/TabsKeyboardDelegate.ts +99 -0
  475. package/src/tabs/useTab.ts +117 -0
  476. package/src/tabs/useTabList.ts +105 -0
  477. package/src/tabs/useTabPanel.ts +75 -0
  478. package/src/tabs/utils.ts +32 -0
  479. package/src/tag/useTag.ts +162 -0
  480. package/src/tag/useTagGroup.ts +192 -0
  481. package/src/textfield/useFormattedTextField.ts +203 -0
  482. package/src/textfield/useTextField.ts +248 -0
  483. package/src/toggle/useToggle.ts +265 -0
  484. package/src/toolbar/useToolbar.ts +147 -0
  485. package/src/tooltip/useTooltip.ts +64 -0
  486. package/src/tooltip/useTooltipTrigger.ts +187 -0
  487. package/src/utils/filterDOMProps.ts +121 -0
  488. package/src/utils/getScrollParent.ts +16 -0
  489. package/src/utils/getScrollParents.ts +20 -0
  490. package/src/utils/keyboard.ts +38 -0
  491. package/src/utils/scrollIntoView.ts +178 -0
  492. package/src/utils/useDeepMemo.ts +30 -0
  493. package/src/utils/useFormReset.ts +54 -0
  494. package/src/utils/useId.ts +5 -0
  495. package/src/utils/useLabels.ts +53 -0
  496. package/src/utils/useResizeObserver.ts +70 -0
  497. package/src/utils/useSlot.ts +78 -0
  498. package/src/utils/useUpdateEffect.ts +54 -0
  499. package/src/utils/useUpdateLayoutEffect.ts +58 -0
  500. package/src/visually-hidden/VisuallyHidden.ts +100 -0
@@ -0,0 +1,64 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/tooltip/useTooltip.ts).
2
+ // octane adaptations:
3
+ // - `DOMAttributes` is a local structural prop-bag alias (upstream's is typed over React's
4
+ // synthetic handlers).
5
+ // - The `TooltipTriggerState` type is imported from the ported stately hook, not a bare
6
+ // `react-stately/...` specifier.
7
+ // - Public-hook slot threading (splitSlot/subSlot) per the binding convention.
8
+ import type { AriaLabelingProps, DOMProps } from '@react-types/shared';
9
+ import { filterDOMProps } from '../utils/filterDOMProps';
10
+ import { mergeProps } from '../utils/mergeProps';
11
+ import type { TooltipTriggerState } from '../stately/tooltip/useTooltipTriggerState';
12
+ import { useHover } from '../interactions/useHover';
13
+
14
+ import { S, splitSlot, subSlot } from '../internal';
15
+
16
+ // octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
17
+ // handler types along).
18
+ type DOMAttributes = Record<string, any>;
19
+
20
+ export interface TooltipProps {
21
+ isOpen?: boolean;
22
+ }
23
+
24
+ export interface AriaTooltipProps extends TooltipProps, DOMProps, AriaLabelingProps {}
25
+
26
+ export interface TooltipAria {
27
+ /**
28
+ * Props for the tooltip element.
29
+ */
30
+ tooltipProps: DOMAttributes;
31
+ }
32
+
33
+ /**
34
+ * Provides the accessibility implementation for a Tooltip component.
35
+ */
36
+ export function useTooltip(props: AriaTooltipProps, state?: TooltipTriggerState): TooltipAria;
37
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
38
+ export function useTooltip(
39
+ props: AriaTooltipProps,
40
+ state: TooltipTriggerState | undefined,
41
+ slot: symbol | undefined,
42
+ ): TooltipAria;
43
+ export function useTooltip(...args: any[]): TooltipAria {
44
+ const [user, slotArg] = splitSlot(args);
45
+ const slot = slotArg ?? S('useTooltip');
46
+ const props = user[0] as AriaTooltipProps;
47
+ const state = user[1] as TooltipTriggerState | undefined;
48
+
49
+ let domProps = filterDOMProps(props, { labelable: true });
50
+
51
+ let { hoverProps } = useHover(
52
+ {
53
+ onHoverStart: () => state?.open(true),
54
+ onHoverEnd: () => state?.close(),
55
+ },
56
+ subSlot(slot, 'hover'),
57
+ );
58
+
59
+ return {
60
+ tooltipProps: mergeProps(domProps, hoverProps, {
61
+ role: 'tooltip',
62
+ }),
63
+ };
64
+ }
@@ -0,0 +1,187 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/tooltip/useTooltipTrigger.ts).
2
+ // octane adaptations:
3
+ // - `DOMAttributes` is a local structural prop-bag alias (upstream's is typed over React's
4
+ // synthetic handlers); the global keydown listener receives a native KeyboardEvent.
5
+ // - `TooltipTriggerProps`/`TooltipTriggerState` are imported from the ported stately hook,
6
+ // not a bare `react-stately/...` specifier.
7
+ // - Public-hook slot threading (splitSlot/subSlot) per the binding convention; the explicit
8
+ // useEffect dep array is kept verbatim with a trailing subSlot.
9
+ import type { FocusableElement, RefObject } from '@react-types/shared';
10
+ import { getInteractionModality, isFocusVisible } from '../interactions/useFocusVisible';
11
+ import { mergeProps } from '../utils/mergeProps';
12
+ import type {
13
+ TooltipTriggerProps,
14
+ TooltipTriggerState,
15
+ } from '../stately/tooltip/useTooltipTriggerState';
16
+ import { useEffect, useRef } from 'octane';
17
+ import { useFocusable } from '../interactions/useFocusable';
18
+ import { useHover } from '../interactions/useHover';
19
+ import { useId } from '../utils/useId';
20
+
21
+ import { S, splitSlot, subSlot } from '../internal';
22
+
23
+ // octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
24
+ // handler types along).
25
+ type DOMAttributes = Record<string, any>;
26
+
27
+ export interface TooltipTriggerAria {
28
+ /**
29
+ * Props for the trigger element.
30
+ */
31
+ triggerProps: DOMAttributes;
32
+
33
+ /**
34
+ * Props for the overlay container element.
35
+ */
36
+ tooltipProps: DOMAttributes;
37
+ }
38
+
39
+ /**
40
+ * Provides the behavior and accessibility implementation for a tooltip trigger, e.g. a button
41
+ * that shows a description when focused or hovered.
42
+ */
43
+ export function useTooltipTrigger(
44
+ props: TooltipTriggerProps,
45
+ state: TooltipTriggerState,
46
+ ref: RefObject<FocusableElement | null>,
47
+ ): TooltipTriggerAria;
48
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
49
+ export function useTooltipTrigger(
50
+ props: TooltipTriggerProps,
51
+ state: TooltipTriggerState,
52
+ ref: RefObject<FocusableElement | null>,
53
+ slot: symbol | undefined,
54
+ ): TooltipTriggerAria;
55
+ export function useTooltipTrigger(...args: any[]): TooltipTriggerAria {
56
+ const [user, slotArg] = splitSlot(args);
57
+ const slot = slotArg ?? S('useTooltipTrigger');
58
+ const props = user[0] as TooltipTriggerProps;
59
+ const state = user[1] as TooltipTriggerState;
60
+ const ref = user[2] as RefObject<FocusableElement | null>;
61
+
62
+ let { isDisabled, trigger, shouldCloseOnPress = true } = props;
63
+
64
+ let tooltipId = useId(subSlot(slot, 'id'));
65
+
66
+ let isHovered = useRef(false, subSlot(slot, 'isHovered'));
67
+ let isFocused = useRef(false, subSlot(slot, 'isFocused'));
68
+
69
+ let handleShow = () => {
70
+ if (isHovered.current || isFocused.current) {
71
+ state.open(isFocused.current);
72
+ }
73
+ };
74
+
75
+ let handleHide = (immediate?: boolean) => {
76
+ if (!isHovered.current && !isFocused.current) {
77
+ state.close(immediate);
78
+ }
79
+ };
80
+
81
+ useEffect(
82
+ () => {
83
+ let onKeyDown = (e: KeyboardEvent) => {
84
+ if (ref && ref.current) {
85
+ // Escape after clicking something can give it keyboard focus
86
+ // dismiss tooltip on esc key press
87
+ if (e.key === 'Escape') {
88
+ e.stopPropagation();
89
+ state.close(true);
90
+ }
91
+ }
92
+ };
93
+ if (state.isOpen) {
94
+ document.addEventListener('keydown', onKeyDown, true);
95
+ return () => {
96
+ document.removeEventListener('keydown', onKeyDown, true);
97
+ };
98
+ }
99
+ },
100
+ [ref, state],
101
+ subSlot(slot, 'keydown'),
102
+ );
103
+
104
+ let onHoverStart = () => {
105
+ if (trigger === 'focus') {
106
+ return;
107
+ }
108
+ // In chrome, if you hover a trigger, then another element obscures it, due to keyboard
109
+ // interactions for example, hover will end. When hover is restored after that element disappears,
110
+ // focus moves on for example, then the tooltip will reopen. We check the modality to know if the hover
111
+ // is the result of moving the mouse.
112
+ if (getInteractionModality() === 'pointer') {
113
+ isHovered.current = true;
114
+ } else {
115
+ isHovered.current = false;
116
+ }
117
+ handleShow();
118
+ };
119
+
120
+ let onHoverEnd = () => {
121
+ if (trigger === 'focus') {
122
+ return;
123
+ }
124
+ // no matter how the trigger is left, we should close the tooltip
125
+ isFocused.current = false;
126
+ isHovered.current = false;
127
+ handleHide();
128
+ };
129
+
130
+ let onPressStart = () => {
131
+ // if shouldCloseOnPress is false, we should not close the tooltip
132
+ if (!shouldCloseOnPress) {
133
+ return;
134
+ }
135
+ // no matter how the trigger is pressed, we should close the tooltip
136
+ isFocused.current = false;
137
+ isHovered.current = false;
138
+ handleHide(true);
139
+ };
140
+
141
+ let onFocus = () => {
142
+ let isVisible = isFocusVisible();
143
+ if (isVisible) {
144
+ isFocused.current = true;
145
+ handleShow();
146
+ }
147
+ };
148
+
149
+ let onBlur = () => {
150
+ isFocused.current = false;
151
+ isHovered.current = false;
152
+ handleHide(true);
153
+ };
154
+
155
+ let { hoverProps } = useHover(
156
+ {
157
+ isDisabled,
158
+ onHoverStart,
159
+ onHoverEnd,
160
+ },
161
+ subSlot(slot, 'hover'),
162
+ );
163
+
164
+ let { focusableProps } = useFocusable(
165
+ {
166
+ isDisabled,
167
+ onFocus,
168
+ onBlur,
169
+ },
170
+ ref,
171
+ subSlot(slot, 'focusable'),
172
+ );
173
+
174
+ return {
175
+ triggerProps: {
176
+ 'aria-describedby': state.isOpen ? tooltipId : undefined,
177
+ ...mergeProps(focusableProps, hoverProps, {
178
+ onPointerDown: onPressStart,
179
+ onKeyDown: onPressStart,
180
+ }),
181
+ tabIndex: undefined,
182
+ },
183
+ tooltipProps: {
184
+ id: tooltipId,
185
+ },
186
+ };
187
+ }
@@ -0,0 +1,121 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/filterDOMProps.ts).
2
+ // Plain function (no hooks, no slot threading). The prop-name tables port verbatim: the
3
+ // `on*` names in `globalEvents` are octane's NATIVE delegated event props, which use the
4
+ // same casing as upstream's React names for these events.
5
+ import type { AriaLabelingProps, DOMProps, LinkDOMProps } from '@react-types/shared';
6
+
7
+ // octane adaptation: upstream's `GlobalDOMAttributes` from '@react-types/shared' is typed
8
+ // over React synthetic-event handlers; octane props carry native handlers, so it becomes a
9
+ // structural bag.
10
+ type GlobalDOMAttributes = Record<string, any>;
11
+
12
+ const DOMPropNames = new Set(['id']);
13
+
14
+ const labelablePropNames = new Set([
15
+ 'aria-label',
16
+ 'aria-labelledby',
17
+ 'aria-describedby',
18
+ 'aria-details',
19
+ ]);
20
+
21
+ // See LinkDOMProps in dom.d.ts.
22
+ const linkPropNames = new Set([
23
+ 'href',
24
+ 'hrefLang',
25
+ 'target',
26
+ 'rel',
27
+ 'download',
28
+ 'ping',
29
+ 'referrerPolicy',
30
+ ]);
31
+
32
+ const globalAttrs = new Set(['dir', 'lang', 'hidden', 'inert', 'translate']);
33
+
34
+ const globalEvents = new Set([
35
+ 'onClick',
36
+ 'onAuxClick',
37
+ 'onContextMenu',
38
+ 'onDoubleClick',
39
+ 'onMouseDown',
40
+ 'onMouseEnter',
41
+ 'onMouseLeave',
42
+ 'onMouseMove',
43
+ 'onMouseOut',
44
+ 'onMouseOver',
45
+ 'onMouseUp',
46
+ 'onTouchCancel',
47
+ 'onTouchEnd',
48
+ 'onTouchMove',
49
+ 'onTouchStart',
50
+ 'onPointerDown',
51
+ 'onPointerMove',
52
+ 'onPointerUp',
53
+ 'onPointerCancel',
54
+ 'onPointerEnter',
55
+ 'onPointerLeave',
56
+ 'onPointerOver',
57
+ 'onPointerOut',
58
+ 'onGotPointerCapture',
59
+ 'onLostPointerCapture',
60
+ 'onScroll',
61
+ 'onWheel',
62
+ 'onAnimationStart',
63
+ 'onAnimationEnd',
64
+ 'onAnimationIteration',
65
+ 'onTransitionCancel',
66
+ 'onTransitionEnd',
67
+ 'onTransitionRun',
68
+ 'onTransitionStart',
69
+ ]);
70
+
71
+ interface Options {
72
+ /**
73
+ * If labelling associated aria properties should be included in the filter.
74
+ */
75
+ labelable?: boolean;
76
+ /** Whether the element is a link and should include DOM props for <a> elements. */
77
+ isLink?: boolean;
78
+ /** Whether to include global DOM attributes. */
79
+ global?: boolean;
80
+ /** Whether to include DOM events. */
81
+ events?: boolean;
82
+ /**
83
+ * A Set of other property names that should be included in the filter.
84
+ */
85
+ propNames?: Set<string>;
86
+ }
87
+
88
+ const propRe = /^(data-.*)$/;
89
+
90
+ /**
91
+ * Filters out all props that aren't valid DOM props or defined via override prop obj.
92
+ *
93
+ * @param props - The component props to be filtered.
94
+ * @param opts - Props to override.
95
+ */
96
+ export function filterDOMProps(
97
+ props: DOMProps & AriaLabelingProps & LinkDOMProps & GlobalDOMAttributes,
98
+ opts: Options = {},
99
+ ): DOMProps & AriaLabelingProps & GlobalDOMAttributes {
100
+ let { labelable, isLink, global, events = global, propNames } = opts;
101
+ let filteredProps: Record<string, any> = {};
102
+
103
+ for (const prop in props) {
104
+ if (
105
+ Object.prototype.hasOwnProperty.call(props, prop) &&
106
+ (DOMPropNames.has(prop) ||
107
+ (labelable && labelablePropNames.has(prop)) ||
108
+ (isLink && linkPropNames.has(prop)) ||
109
+ (global && globalAttrs.has(prop)) ||
110
+ (events &&
111
+ (globalEvents.has(prop) ||
112
+ (prop.endsWith('Capture') && globalEvents.has(prop.slice(0, -7))))) ||
113
+ propNames?.has(prop) ||
114
+ propRe.test(prop))
115
+ ) {
116
+ filteredProps[prop] = (props as Record<string, any>)[prop];
117
+ }
118
+ }
119
+
120
+ return filteredProps;
121
+ }
@@ -0,0 +1,16 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/getScrollParent.ts).
2
+ // octane adaptations: none (pure DOM walk); ports verbatim.
3
+ import { isScrollable } from './isScrollable';
4
+
5
+ export function getScrollParent(node: Element, checkForOverflow?: boolean): Element {
6
+ let scrollableNode: Element | null = node;
7
+ if (isScrollable(scrollableNode, checkForOverflow)) {
8
+ scrollableNode = scrollableNode.parentElement;
9
+ }
10
+
11
+ while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {
12
+ scrollableNode = scrollableNode.parentElement;
13
+ }
14
+
15
+ return scrollableNode || document.scrollingElement || document.documentElement;
16
+ }
@@ -0,0 +1,20 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/getScrollParents.ts).
2
+ // Verbatim (no React surface).
3
+ import { isScrollable } from './isScrollable';
4
+
5
+ export function getScrollParents(node: Element, checkForOverflow?: boolean): Element[] {
6
+ let parentElements: Element[] = [];
7
+ let root = document.scrollingElement || document.documentElement;
8
+
9
+ while (node) {
10
+ if (isScrollable(node, checkForOverflow)) {
11
+ parentElements.push(node);
12
+ }
13
+ if (node === root) {
14
+ break;
15
+ }
16
+ node = node.parentElement as Element;
17
+ }
18
+
19
+ return parentElements;
20
+ }
@@ -0,0 +1,38 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/keyboard.tsx).
2
+ // Verbatim (no React surface); the upstream file carries a .tsx extension but contains no JSX.
3
+ import { isMac } from './platform';
4
+
5
+ interface Event {
6
+ altKey: boolean;
7
+ ctrlKey: boolean;
8
+ metaKey: boolean;
9
+ }
10
+
11
+ export function isCtrlKeyPressed(e: Event): boolean {
12
+ if (isMac()) {
13
+ return e.metaKey;
14
+ }
15
+
16
+ return e.ctrlKey;
17
+ }
18
+
19
+ // HTML input types that do not cause the software keyboard to appear.
20
+ const nonTextInputTypes = new Set([
21
+ 'checkbox',
22
+ 'radio',
23
+ 'range',
24
+ 'color',
25
+ 'file',
26
+ 'image',
27
+ 'button',
28
+ 'submit',
29
+ 'reset',
30
+ ]);
31
+
32
+ export function willOpenKeyboard(target: Element): boolean {
33
+ return (
34
+ (target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type)) ||
35
+ target instanceof HTMLTextAreaElement ||
36
+ (target instanceof HTMLElement && target.isContentEditable)
37
+ );
38
+ }
@@ -0,0 +1,178 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/scrollIntoView.ts).
2
+ // Verbatim (no React surface), including the NODE_ENV === 'test' direct-assignment branch
3
+ // (jsdom has no scrollTo implementation).
4
+ import { getScrollParents } from './getScrollParents';
5
+ import { isIOS } from './platform';
6
+
7
+ interface ScrollIntoViewOpts {
8
+ /** The position to align items along the block axis in. */
9
+ block?: ScrollLogicalPosition;
10
+ /** The position to align items along the inline axis in. */
11
+ inline?: ScrollLogicalPosition;
12
+ }
13
+
14
+ interface ScrollIntoViewportOpts {
15
+ /** The optional containing element of the target to be centered in the viewport. */
16
+ containingElement?: Element | null;
17
+ }
18
+
19
+ /**
20
+ * Scrolls `scrollView` so that `element` is visible.
21
+ * Similar to `element.scrollIntoView({block: 'nearest'})` (not supported in Edge),
22
+ * but doesn't affect parents above `scrollView`.
23
+ */
24
+ export function scrollIntoView(
25
+ scrollView: HTMLElement,
26
+ element: HTMLElement,
27
+ opts: ScrollIntoViewOpts = {},
28
+ ): void {
29
+ let { block = 'nearest', inline = 'nearest' } = opts;
30
+
31
+ if (scrollView === element) {
32
+ return;
33
+ }
34
+
35
+ let y = scrollView.scrollTop;
36
+ let x = scrollView.scrollLeft;
37
+
38
+ let target = element.getBoundingClientRect();
39
+ let view = scrollView.getBoundingClientRect();
40
+ let itemStyle = window.getComputedStyle(element);
41
+ let viewStyle = window.getComputedStyle(scrollView);
42
+ let root = document.scrollingElement || document.documentElement;
43
+ let isRoot = scrollView === root;
44
+
45
+ let viewTop = scrollView === root ? 0 : view.top;
46
+ let viewBottom = scrollView === root ? scrollView.clientHeight : view.bottom;
47
+ let viewLeft = scrollView === root ? 0 : view.left;
48
+ let viewRight = scrollView === root ? scrollView.clientWidth : view.right;
49
+
50
+ let scrollMarginTop = parseFloat(itemStyle.scrollMarginTop) || 0;
51
+ let scrollMarginBottom = parseFloat(itemStyle.scrollMarginBottom) || 0;
52
+ let scrollMarginLeft = parseFloat(itemStyle.scrollMarginLeft) || 0;
53
+ let scrollMarginRight = parseFloat(itemStyle.scrollMarginRight) || 0;
54
+
55
+ let scrollPaddingTop = parseFloat(viewStyle.scrollPaddingTop) || 0;
56
+ let scrollPaddingBottom = parseFloat(viewStyle.scrollPaddingBottom) || 0;
57
+ let scrollPaddingLeft = parseFloat(viewStyle.scrollPaddingLeft) || 0;
58
+ let scrollPaddingRight = parseFloat(viewStyle.scrollPaddingRight) || 0;
59
+
60
+ let borderTopWidth = parseFloat(viewStyle.borderTopWidth) || 0;
61
+ let borderBottomWidth = parseFloat(viewStyle.borderBottomWidth) || 0;
62
+ let borderLeftWidth = parseFloat(viewStyle.borderLeftWidth) || 0;
63
+ let borderRightWidth = parseFloat(viewStyle.borderRightWidth) || 0;
64
+
65
+ let scrollAreaTop = target.top - scrollMarginTop;
66
+ let scrollAreaBottom = target.bottom + scrollMarginBottom;
67
+ let scrollAreaLeft = target.left - scrollMarginLeft;
68
+ let scrollAreaRight = target.right + scrollMarginRight;
69
+
70
+ let scrollBarOffsetX = scrollView === root ? 0 : borderLeftWidth + borderRightWidth;
71
+ let scrollBarOffsetY = scrollView === root ? 0 : borderTopWidth + borderBottomWidth;
72
+ let scrollBarWidth =
73
+ scrollView === root ? 0 : scrollView.offsetWidth - scrollView.clientWidth - scrollBarOffsetX;
74
+ let scrollBarHeight =
75
+ scrollView === root ? 0 : scrollView.offsetHeight - scrollView.clientHeight - scrollBarOffsetY;
76
+
77
+ let scrollPortTop = viewTop + (isRoot ? 0 : borderTopWidth) + scrollPaddingTop;
78
+ let scrollPortBottom =
79
+ viewBottom - (isRoot ? 0 : borderBottomWidth) - scrollPaddingBottom - scrollBarHeight;
80
+ let scrollPortLeft = viewLeft + (isRoot ? 0 : borderLeftWidth) + scrollPaddingLeft;
81
+ let scrollPortRight = viewRight - (isRoot ? 0 : borderRightWidth) - scrollPaddingRight;
82
+
83
+ // IOS always positions the scrollbar on the right ¯\_(ツ)_/¯
84
+ if (viewStyle.direction === 'rtl' && !isIOS()) {
85
+ scrollPortLeft += scrollBarWidth;
86
+ } else {
87
+ scrollPortRight -= scrollBarWidth;
88
+ }
89
+
90
+ let shouldScrollBlock = scrollAreaTop < scrollPortTop || scrollAreaBottom > scrollPortBottom;
91
+ let shouldScrollInline = scrollAreaLeft < scrollPortLeft || scrollAreaRight > scrollPortRight;
92
+
93
+ if (shouldScrollBlock && block === 'start') {
94
+ y += scrollAreaTop - scrollPortTop;
95
+ } else if (shouldScrollBlock && block === 'center') {
96
+ y += (scrollAreaTop + scrollAreaBottom) / 2 - (scrollPortTop + scrollPortBottom) / 2;
97
+ } else if (shouldScrollBlock && block === 'end') {
98
+ y += scrollAreaBottom - scrollPortBottom;
99
+ } else if (shouldScrollBlock && block === 'nearest') {
100
+ let start = scrollAreaTop - scrollPortTop;
101
+ let end = scrollAreaBottom - scrollPortBottom;
102
+ y += Math.abs(start) <= Math.abs(end) ? start : end;
103
+ }
104
+
105
+ if (shouldScrollInline && inline === 'start') {
106
+ x += scrollAreaLeft - scrollPortLeft;
107
+ } else if (shouldScrollInline && inline === 'center') {
108
+ x += (scrollAreaLeft + scrollAreaRight) / 2 - (scrollPortLeft + scrollPortRight) / 2;
109
+ } else if (shouldScrollInline && inline === 'end') {
110
+ x += scrollAreaRight - scrollPortRight;
111
+ } else if (shouldScrollInline && inline === 'nearest') {
112
+ let start = scrollAreaLeft - scrollPortLeft;
113
+ let end = scrollAreaRight - scrollPortRight;
114
+ x += Math.abs(start) <= Math.abs(end) ? start : end;
115
+ }
116
+
117
+ if (process.env.NODE_ENV === 'test') {
118
+ scrollView.scrollLeft = x;
119
+ scrollView.scrollTop = y;
120
+ return;
121
+ }
122
+
123
+ scrollView.scrollTo({ left: x, top: y });
124
+ }
125
+
126
+ /**
127
+ * Scrolls the `targetElement` so it is visible in the viewport. Accepts an optional
128
+ * `opts.containingElement` that will be centered in the viewport prior to scrolling the
129
+ * targetElement into view. If scrolling is prevented on the body (e.g. targetElement is in a
130
+ * popover), this will only scroll the scroll parents of the targetElement up to but not including
131
+ * the body itself.
132
+ */
133
+ export function scrollIntoViewport(
134
+ targetElement: Element | null,
135
+ opts: ScrollIntoViewportOpts = {},
136
+ ): void {
137
+ let { containingElement } = opts;
138
+ if (targetElement && targetElement.isConnected) {
139
+ let root = document.scrollingElement || document.documentElement;
140
+ let isScrollPrevented = window.getComputedStyle(root).overflow === 'hidden';
141
+ if (!isScrollPrevented) {
142
+ let { left: originalLeft, top: originalTop } = targetElement.getBoundingClientRect();
143
+
144
+ // use scrollIntoView({block: 'nearest'}) instead of .focus to check if the element is fully in view or not since .focus()
145
+ // won't cause a scroll if the element is already focused and doesn't behave consistently when an element is partially out of view horizontally vs vertically
146
+ targetElement?.scrollIntoView?.({ block: 'nearest' });
147
+ let { left: newLeft, top: newTop } = targetElement.getBoundingClientRect();
148
+ // Account for sub pixel differences from rounding
149
+ if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
150
+ containingElement?.scrollIntoView?.({ block: 'center', inline: 'center' });
151
+ targetElement.scrollIntoView?.({ block: 'nearest' });
152
+ }
153
+ } else {
154
+ let { left: originalLeft, top: originalTop } = targetElement.getBoundingClientRect();
155
+
156
+ // If scrolling is prevented, we don't want to scroll the body since it might move the overlay partially offscreen and the user can't scroll it back into view.
157
+ let scrollParents = getScrollParents(targetElement, true);
158
+ for (let scrollParent of scrollParents) {
159
+ scrollIntoView(scrollParent as HTMLElement, targetElement as HTMLElement);
160
+ }
161
+ let { left: newLeft, top: newTop } = targetElement.getBoundingClientRect();
162
+ // Account for sub pixel differences from rounding
163
+ if (Math.abs(originalLeft - newLeft) > 1 || Math.abs(originalTop - newTop) > 1) {
164
+ scrollParents = containingElement ? getScrollParents(containingElement, true) : [];
165
+ // scroll containing element into view first, then rescroll target element into view like the non chrome flow above
166
+ for (let scrollParent of scrollParents) {
167
+ scrollIntoView(scrollParent as HTMLElement, containingElement as HTMLElement, {
168
+ block: 'center',
169
+ inline: 'center',
170
+ });
171
+ }
172
+ for (let scrollParent of getScrollParents(targetElement, true)) {
173
+ scrollIntoView(scrollParent as HTMLElement, targetElement as HTMLElement);
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
@@ -0,0 +1,30 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/utils/useDeepMemo.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; otherwise verbatim.
4
+ import { useRef } from 'octane';
5
+
6
+ import { S, splitSlot, subSlot } from '../internal';
7
+
8
+ export function useDeepMemo<T>(value: T, isEqual: (a: T, b: T) => boolean): T;
9
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
10
+ export function useDeepMemo<T>(
11
+ value: T,
12
+ isEqual: (a: T, b: T) => boolean,
13
+ slot: symbol | undefined,
14
+ ): T;
15
+ export function useDeepMemo(...args: any[]): any {
16
+ const [user, slotArg] = splitSlot(args);
17
+ const slot = slotArg ?? S('useDeepMemo');
18
+ let value = user[0];
19
+ const isEqual = user[1] as (a: any, b: any) => boolean;
20
+
21
+ // Using a ref during render is ok here because it's only an optimization – both values are equivalent.
22
+ // If a render is thrown away, it'll still work the same no matter if the next render is the same or not.
23
+ let lastValue = useRef<any>(null, subSlot(slot, 'last'));
24
+ if (value && lastValue.current && isEqual(value, lastValue.current)) {
25
+ value = lastValue.current;
26
+ }
27
+
28
+ lastValue.current = value;
29
+ return value;
30
+ }