@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,332 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/CollectionBuilder.ts).
2
+ // octane adaptations:
3
+ // - React.isValidElement/Fragment/Children → octane's parity helpers over element
4
+ // DESCRIPTORS (value-position JSX). Descriptors carry .type/.props/.key like React
5
+ // elements, so the walk itself is verbatim.
6
+ // - OCTANE DIVERGENCE: literal static JSX children are a compiled children BLOCK (a
7
+ // render function), which cannot be statically walked — the hooks-tier builder
8
+ // supports dynamic collections (`items` + render function) and descriptor arrays,
9
+ // and rejects children blocks with a descriptive error. The RAC tier does not have
10
+ // this limitation. Same divergence class as radix `Slot`.
11
+ import type { CollectionBase, Key, Node } from '@react-types/shared';
12
+ import { Children, Fragment, isChildrenBlock, isValidElement } from 'octane';
13
+ import type { PartialNode } from './types';
14
+
15
+ type CollectionElement<T> = any;
16
+
17
+ interface CollectionBuilderState {
18
+ renderer?: (value: any) => any;
19
+ }
20
+
21
+ export class CollectionBuilder<T extends object> {
22
+ private context?: unknown;
23
+ private cache: WeakMap<T, Node<T>> = new WeakMap();
24
+
25
+ build(props: Partial<CollectionBase<T>>, context?: unknown): Iterable<Node<T>> {
26
+ this.context = context;
27
+ return iterable(() => this.iterateCollection(props as any));
28
+ }
29
+
30
+ private *iterateCollection(props: { children?: any; items?: Iterable<T> }): Generator<Node<T>> {
31
+ let { children, items } = props;
32
+
33
+ if (isChildrenBlock(children)) {
34
+ throw new Error(
35
+ 'Static JSX children are not supported by hooks-tier octane collections: octane ' +
36
+ 'compiles children-position JSX into a render block that cannot be statically ' +
37
+ 'walked. Pass `items` with a render function returning <Item> descriptors, or an ' +
38
+ 'array of <Item> descriptors.',
39
+ );
40
+ }
41
+
42
+ if (isValidElement(children) && (children as any).type === Fragment) {
43
+ yield* this.iterateCollection({
44
+ children: (children as any).props.children,
45
+ items,
46
+ });
47
+ } else if (typeof children === 'function') {
48
+ if (!items) {
49
+ throw new Error('props.children was a function but props.items is missing');
50
+ }
51
+
52
+ let index = 0;
53
+ for (let item of items) {
54
+ yield* this.getFullNode(
55
+ {
56
+ value: item,
57
+ index,
58
+ },
59
+ { renderer: children },
60
+ );
61
+ index++;
62
+ }
63
+ } else {
64
+ let items: CollectionElement<T>[] = [];
65
+ Children.forEach(children, (child: any) => {
66
+ if (child) {
67
+ items.push(child);
68
+ }
69
+ });
70
+
71
+ let index = 0;
72
+ for (let item of items) {
73
+ let nodes = this.getFullNode(
74
+ {
75
+ element: item,
76
+ index: index,
77
+ },
78
+ {},
79
+ );
80
+
81
+ for (let node of nodes) {
82
+ index++;
83
+ yield node;
84
+ }
85
+ }
86
+ }
87
+ }
88
+
89
+ private getKey(
90
+ item: NonNullable<CollectionElement<T>>,
91
+ partialNode: PartialNode<T>,
92
+ state: CollectionBuilderState,
93
+ parentKey?: Key | null,
94
+ ): Key {
95
+ if (item.key != null) {
96
+ return item.key;
97
+ }
98
+
99
+ if (partialNode.type === 'cell' && partialNode.key != null) {
100
+ return `${parentKey}${partialNode.key}`;
101
+ }
102
+
103
+ let v = partialNode.value as any;
104
+ if (v != null) {
105
+ let key = v.key ?? v.id;
106
+ if (key == null) {
107
+ throw new Error('No key found for item');
108
+ }
109
+
110
+ return key;
111
+ }
112
+
113
+ return parentKey ? `${parentKey}.${partialNode.index}` : `$.${partialNode.index}`;
114
+ }
115
+
116
+ private getChildState(state: CollectionBuilderState, partialNode: PartialNode<T>) {
117
+ return {
118
+ renderer: partialNode.renderer || state.renderer,
119
+ };
120
+ }
121
+
122
+ private *getFullNode(
123
+ partialNode: PartialNode<T> & { index: number },
124
+ state: CollectionBuilderState,
125
+ parentKey?: Key | null,
126
+ parentNode?: Node<T>,
127
+ ): Generator<Node<T>> {
128
+ if (isValidElement(partialNode.element) && (partialNode.element as any).type === Fragment) {
129
+ let children: CollectionElement<T>[] = [];
130
+
131
+ Children.forEach((partialNode.element as any).props.children, (child: any) => {
132
+ children.push(child);
133
+ });
134
+
135
+ let index = partialNode.index ?? 0;
136
+
137
+ for (const child of children) {
138
+ yield* this.getFullNode(
139
+ {
140
+ element: child,
141
+ index: index++,
142
+ },
143
+ state,
144
+ parentKey,
145
+ parentNode,
146
+ );
147
+ }
148
+
149
+ return;
150
+ }
151
+
152
+ // If there's a value instead of an element on the node, and a parent renderer function is available,
153
+ // use it to render an element for the value.
154
+ let element = partialNode.element;
155
+ if (!element && partialNode.value && state && state.renderer) {
156
+ let cached = this.cache.get(partialNode.value);
157
+ if (cached && (!cached.shouldInvalidate || !cached.shouldInvalidate(this.context))) {
158
+ cached.index = partialNode.index;
159
+ cached.parentKey = parentNode ? parentNode.key : null;
160
+ yield cached;
161
+ return;
162
+ }
163
+
164
+ element = state.renderer(partialNode.value);
165
+ }
166
+
167
+ // If there's an element with a getCollectionNode function on its type, then it's a supported component.
168
+ // Call this function to get a partial node, and recursively build a full node from there.
169
+ if (isValidElement(element)) {
170
+ let type = (element as any).type as any;
171
+ if (typeof type !== 'function' && typeof type?.getCollectionNode !== 'function') {
172
+ let name = (element as any).type;
173
+ throw new Error(`Unknown element <${name}> in collection.`);
174
+ }
175
+
176
+ let childNodes = type.getCollectionNode((element as any).props, this.context) as Generator<
177
+ PartialNode<T>,
178
+ void,
179
+ Node<T>[]
180
+ >;
181
+ let index = partialNode.index ?? 0;
182
+ let result = childNodes.next();
183
+ while (!result.done && result.value) {
184
+ let childNode = result.value;
185
+
186
+ partialNode.index = index;
187
+
188
+ let nodeKey = childNode.key ?? null;
189
+ if (nodeKey == null) {
190
+ nodeKey = childNode.element
191
+ ? null
192
+ : this.getKey(
193
+ element as NonNullable<CollectionElement<T>>,
194
+ partialNode,
195
+ state,
196
+ parentKey,
197
+ );
198
+ }
199
+
200
+ let nodes = this.getFullNode(
201
+ {
202
+ ...childNode,
203
+ key: nodeKey,
204
+ index,
205
+ wrapper: compose(partialNode.wrapper, childNode.wrapper),
206
+ },
207
+ this.getChildState(state, childNode),
208
+ parentKey ? `${parentKey}${(element as any).key}` : (element as any).key,
209
+ parentNode,
210
+ );
211
+
212
+ let children = [...nodes];
213
+ for (let node of children) {
214
+ // Cache the node based on its value
215
+ node.value = childNode.value ?? partialNode.value ?? null;
216
+ if (node.value) {
217
+ this.cache.set(node.value, node);
218
+ }
219
+
220
+ // The partial node may have specified a type for the child in order to specify a constraint.
221
+ // Verify that the full node that was built recursively matches this type.
222
+ if (partialNode.type && node.type !== partialNode.type) {
223
+ throw new Error(
224
+ `Unsupported type <${capitalize(node.type)}> in <${capitalize(parentNode?.type ?? 'unknown parent type')}>. Only <${capitalize(partialNode.type)}> is supported.`,
225
+ );
226
+ }
227
+
228
+ index++;
229
+ yield node;
230
+ }
231
+
232
+ result = childNodes.next(children);
233
+ }
234
+
235
+ return;
236
+ }
237
+
238
+ // Ignore invalid elements
239
+ if (partialNode.key == null || partialNode.type == null) {
240
+ return;
241
+ }
242
+
243
+ // Create full node
244
+ let builder = this;
245
+ let node: Node<T> = {
246
+ type: partialNode.type,
247
+ props: partialNode.props,
248
+ key: partialNode.key,
249
+ parentKey: parentNode ? parentNode.key : null,
250
+ value: partialNode.value ?? null,
251
+ level: (parentNode?.level ?? 0) + (parentNode?.type === 'item' ? 1 : 0),
252
+ index: partialNode.index,
253
+ rendered: partialNode.rendered,
254
+ textValue: partialNode.textValue ?? '',
255
+ 'aria-label': partialNode['aria-label'],
256
+ wrapper: partialNode.wrapper,
257
+ shouldInvalidate: partialNode.shouldInvalidate,
258
+ hasChildNodes: partialNode.hasChildNodes || false,
259
+ childNodes: iterable(function* () {
260
+ if (!partialNode.hasChildNodes || !partialNode.childNodes) {
261
+ return;
262
+ }
263
+
264
+ let index = 0;
265
+ for (let child of partialNode.childNodes()) {
266
+ // Ensure child keys are globally unique by prepending the parent node's key
267
+ if (child.key != null) {
268
+ // TODO: Remove this line entirely and enforce that users always provide unique keys.
269
+ // Currently this line will have issues when a parent has a key `a` and a child with key `bc`
270
+ // but another parent has key `ab` and its child has a key `c`. The combined keys would result in both
271
+ // children having a key of `abc`.
272
+ child.key = `${node.key}${child.key}`;
273
+ }
274
+
275
+ let nodes = builder.getFullNode(
276
+ { ...child, index },
277
+ builder.getChildState(state, child),
278
+ node.key,
279
+ node,
280
+ );
281
+ for (let node of nodes) {
282
+ index++;
283
+ yield node;
284
+ }
285
+ }
286
+ }),
287
+ };
288
+
289
+ yield node;
290
+ }
291
+ }
292
+
293
+ // Wraps an iterator function as an iterable object, and caches the results.
294
+ function iterable<T>(iterator: () => IterableIterator<Node<T>>): Iterable<Node<T>> {
295
+ let cache: Array<Node<T>> = [];
296
+ let iterable: null | IterableIterator<Node<T>> = null;
297
+ return {
298
+ *[Symbol.iterator]() {
299
+ for (let item of cache) {
300
+ yield item;
301
+ }
302
+
303
+ if (!iterable) {
304
+ iterable = iterator();
305
+ }
306
+
307
+ for (let item of iterable) {
308
+ cache.push(item);
309
+ yield item;
310
+ }
311
+ },
312
+ };
313
+ }
314
+
315
+ type Wrapper = (element: any) => any;
316
+ function compose(outer: Wrapper | void, inner: Wrapper | void): Wrapper | undefined {
317
+ if (outer && inner) {
318
+ return (element) => outer(inner(element));
319
+ }
320
+
321
+ if (outer) {
322
+ return outer;
323
+ }
324
+
325
+ if (inner) {
326
+ return inner;
327
+ }
328
+ }
329
+
330
+ function capitalize(str: string) {
331
+ return str[0].toUpperCase() + str.slice(1);
332
+ }
@@ -0,0 +1,78 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/Item.ts).
2
+ // octane adaptations: React.Children → octane Children (descriptor arrays); element
3
+ // types → `any` descriptors. `<Item>` is a collection DESCRIPTOR component — it renders
4
+ // nothing; CollectionBuilder walks it via the static `getCollectionNode` generator.
5
+ import type { ItemProps } from '@react-types/shared';
6
+ import { Children } from 'octane';
7
+ import type { PartialNode } from './types';
8
+
9
+ function Item<T>(props: ItemProps<T>): any {
10
+ return null;
11
+ }
12
+
13
+ Item.getCollectionNode = function* getCollectionNode<T>(
14
+ props: ItemProps<T>,
15
+ context: any,
16
+ ): Generator<PartialNode<T>> {
17
+ let { childItems, title, children } = props;
18
+
19
+ let rendered = props.title || props.children;
20
+ let textValue =
21
+ props.textValue || (typeof rendered === 'string' ? rendered : '') || props['aria-label'] || '';
22
+
23
+ // suppressTextValueWarning is used in components like Tabs, which don't have type to select support.
24
+ if (!textValue && !context?.suppressTextValueWarning && process.env.NODE_ENV !== 'production') {
25
+ console.warn(
26
+ '<Item> with non-plain text contents is unsupported by type to select for accessibility. Please add a `textValue` prop.',
27
+ );
28
+ }
29
+
30
+ yield {
31
+ type: 'item',
32
+ props: props,
33
+ rendered,
34
+ textValue,
35
+ 'aria-label': props['aria-label'],
36
+ hasChildNodes: hasChildItems(props),
37
+ *childNodes() {
38
+ if (childItems) {
39
+ for (let child of childItems) {
40
+ yield {
41
+ type: 'item',
42
+ value: child,
43
+ };
44
+ }
45
+ } else if (title) {
46
+ let items: PartialNode<T>[] = [];
47
+ Children.forEach(children as any, (child: any) => {
48
+ items.push({
49
+ type: 'item',
50
+ element: child,
51
+ });
52
+ });
53
+
54
+ yield* items;
55
+ }
56
+ },
57
+ };
58
+ };
59
+
60
+ function hasChildItems<T>(props: ItemProps<T>) {
61
+ if (props.hasChildItems != null) {
62
+ return props.hasChildItems;
63
+ }
64
+
65
+ if (props.childItems) {
66
+ return true;
67
+ }
68
+
69
+ if (props.title && Children.count(props.children as any) > 0) {
70
+ return true;
71
+ }
72
+
73
+ return false;
74
+ }
75
+
76
+ // We don't want getCollectionNode to show up in the type definition
77
+ let _Item = Item as unknown as <T>(props: ItemProps<T>) => any;
78
+ export { _Item as Item };
@@ -0,0 +1,52 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/Section.ts).
2
+ // octane adaptations: React.Children → octane Children (descriptor arrays); element
3
+ // types → `any` descriptors. Renders nothing; walked via static `getCollectionNode`.
4
+ import type { SectionProps } from '@react-types/shared';
5
+ import { Children } from 'octane';
6
+ import type { PartialNode } from './types';
7
+
8
+ function Section<T>(props: SectionProps<T>): any {
9
+ return null;
10
+ }
11
+
12
+ Section.getCollectionNode = function* getCollectionNode<T>(
13
+ props: SectionProps<T>,
14
+ ): Generator<PartialNode<T>> {
15
+ let { children, title, items } = props;
16
+ yield {
17
+ type: 'section',
18
+ props: props,
19
+ hasChildNodes: true,
20
+ rendered: title,
21
+ 'aria-label': props['aria-label'],
22
+ *childNodes() {
23
+ if (typeof children === 'function') {
24
+ if (!items) {
25
+ throw new Error('props.children was a function but props.items is missing');
26
+ }
27
+
28
+ for (let item of items) {
29
+ yield {
30
+ type: 'item',
31
+ value: item,
32
+ renderer: children,
33
+ };
34
+ }
35
+ } else {
36
+ let items: PartialNode<T>[] = [];
37
+ Children.forEach(children as any, (child: any) => {
38
+ items.push({
39
+ type: 'item',
40
+ element: child,
41
+ });
42
+ });
43
+
44
+ yield* items;
45
+ }
46
+ },
47
+ };
48
+ };
49
+
50
+ // We don't want getCollectionNode to show up in the type definition
51
+ let _Section = Section as unknown as <T>(props: SectionProps<T>) => any;
52
+ export { _Section as Section };
@@ -0,0 +1,94 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/getChildNodes.ts).
2
+ // Verbatim (no React surface).
3
+ import type { Collection, Node } from '@react-types/shared';
4
+
5
+ export function getChildNodes<T>(
6
+ node: Node<T>,
7
+ collection: Collection<Node<T>>,
8
+ ): Iterable<Node<T>> {
9
+ // New API: call collection.getChildren with the node key.
10
+ if (typeof collection.getChildren === 'function') {
11
+ return collection.getChildren(node.key);
12
+ }
13
+
14
+ // Old API: access childNodes directly.
15
+ return node.childNodes;
16
+ }
17
+
18
+ export function getFirstItem<T>(iterable: Iterable<T>): T | undefined {
19
+ return getNthItem(iterable, 0);
20
+ }
21
+
22
+ export function getNthItem<T>(iterable: Iterable<T>, index: number): T | undefined {
23
+ if (index < 0) {
24
+ return undefined;
25
+ }
26
+
27
+ let i = 0;
28
+ for (let item of iterable) {
29
+ if (i === index) {
30
+ return item;
31
+ }
32
+
33
+ i++;
34
+ }
35
+ }
36
+
37
+ export function getLastItem<T>(iterable: Iterable<T>): T | undefined {
38
+ let lastItem: T | undefined = undefined;
39
+ for (let value of iterable) {
40
+ lastItem = value;
41
+ }
42
+
43
+ return lastItem;
44
+ }
45
+
46
+ export function compareNodeOrder<T>(
47
+ collection: Collection<Node<T>>,
48
+ a: Node<T>,
49
+ b: Node<T>,
50
+ ): number {
51
+ // If the two nodes have the same parent, compare their indices.
52
+ if (a.parentKey === b.parentKey) {
53
+ return a.index - b.index;
54
+ }
55
+
56
+ // Otherwise, collect all of the ancestors from each node, and find the first one that doesn't match starting from the root.
57
+ // Include the base nodes in case we are comparing nodes of different levels so that we can compare the higher node to the lower level node's
58
+ // ancestor of the same level
59
+ let aAncestors = [...getAncestors(collection, a), a];
60
+ let bAncestors = [...getAncestors(collection, b), b];
61
+ let firstNonMatchingAncestor = aAncestors
62
+ .slice(0, bAncestors.length)
63
+ .findIndex((a, i) => a !== bAncestors[i]);
64
+ if (firstNonMatchingAncestor !== -1) {
65
+ // Compare the indices of two children within the common ancestor.
66
+ a = aAncestors[firstNonMatchingAncestor];
67
+ b = bAncestors[firstNonMatchingAncestor];
68
+ return a.index - b.index;
69
+ }
70
+
71
+ // If there isn't a non matching ancestor, we might be in a case where one of the nodes is the ancestor of the other.
72
+ if (aAncestors.findIndex((node) => node === b) >= 0) {
73
+ return 1;
74
+ } else if (bAncestors.findIndex((node) => node === a) >= 0) {
75
+ return -1;
76
+ }
77
+
78
+ // 🤷
79
+ return -1;
80
+ }
81
+
82
+ function getAncestors<T>(collection: Collection<Node<T>>, node: Node<T>): Node<T>[] {
83
+ let parents: Node<T>[] = [];
84
+
85
+ let currNode: Node<T> | null = node;
86
+ while (currNode?.parentKey != null) {
87
+ currNode = collection.getItem(currNode.parentKey);
88
+ if (currNode) {
89
+ parents.unshift(currNode);
90
+ }
91
+ }
92
+
93
+ return parents;
94
+ }
@@ -0,0 +1,29 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/getItemCount.ts).
2
+ // Verbatim (no React surface).
3
+ import type { Collection, Node } from '@react-types/shared';
4
+ import { getChildNodes } from './getChildNodes';
5
+
6
+ const cache = new WeakMap<Iterable<unknown>, number>();
7
+
8
+ export function getItemCount<T>(collection: Collection<Node<T>>): number {
9
+ let count = cache.get(collection);
10
+ if (count != null) {
11
+ return count;
12
+ }
13
+
14
+ // TS isn't smart enough to know we've ensured count is a number, so use a new variable
15
+ let counter = 0;
16
+ let countItems = (items: Iterable<Node<T>>) => {
17
+ for (let item of items) {
18
+ if (item.type === 'section') {
19
+ countItems(getChildNodes(item, collection));
20
+ } else if (item.type === 'item') {
21
+ counter++;
22
+ }
23
+ }
24
+ };
25
+
26
+ countItems(collection);
27
+ cache.set(collection, counter);
28
+ return counter;
29
+ }
@@ -0,0 +1,20 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/types.ts).
2
+ // octane adaptations: React element types → `any` (octane element descriptors).
3
+ import type { Key } from '@react-types/shared';
4
+
5
+ export interface PartialNode<T> {
6
+ type?: string;
7
+ key?: Key | null;
8
+ value?: T;
9
+ element?: any;
10
+ wrapper?: (element: any) => any;
11
+ rendered?: any;
12
+ textValue?: string;
13
+ 'aria-label'?: string;
14
+ index?: number;
15
+ renderer?: (item: T) => any;
16
+ hasChildNodes?: boolean;
17
+ childNodes?: () => IterableIterator<PartialNode<T>>;
18
+ props?: any;
19
+ shouldInvalidate?: (context: any) => boolean;
20
+ }
@@ -0,0 +1,54 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/collections/useCollection.ts).
2
+ // octane adaptations: React element types → `any` descriptors; public-hook slot
3
+ // threading; explicit dependency arrays kept verbatim.
4
+ import type { Collection, CollectionStateBase, Node } from '@react-types/shared';
5
+ import { useMemo } from 'octane';
6
+
7
+ import { S, splitSlot, subSlot } from '../../internal';
8
+ import { CollectionBuilder } from './CollectionBuilder';
9
+
10
+ interface CollectionOptions<T, C extends Collection<Node<T>>> extends Omit<
11
+ CollectionStateBase<T, C>,
12
+ 'children'
13
+ > {
14
+ children?: any;
15
+ }
16
+
17
+ type CollectionFactory<T, C extends Collection<Node<T>>> = (node: Iterable<Node<T>>) => C;
18
+
19
+ export function useCollection<
20
+ T extends object,
21
+ C extends Collection<Node<T>> = Collection<Node<T>>,
22
+ >(props: CollectionOptions<T, C>, factory: CollectionFactory<T, C>, context?: unknown): C;
23
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
24
+ export function useCollection<
25
+ T extends object,
26
+ C extends Collection<Node<T>> = Collection<Node<T>>,
27
+ >(
28
+ props: CollectionOptions<T, C>,
29
+ factory: CollectionFactory<T, C>,
30
+ context: unknown,
31
+ slot: symbol | undefined,
32
+ ): C;
33
+ export function useCollection(...args: any[]): any {
34
+ const [user, slotArg] = splitSlot(args);
35
+ const slot = slotArg ?? S('useCollection');
36
+ const props = user[0] as CollectionOptions<any, any>;
37
+ const factory = user[1] as CollectionFactory<any, any>;
38
+ const context = user[2];
39
+
40
+ let builder = useMemo(() => new CollectionBuilder<any>(), [], subSlot(slot, 'builder'));
41
+ let { children, items, collection } = props as any;
42
+ let result = useMemo(
43
+ () => {
44
+ if (collection) {
45
+ return collection;
46
+ }
47
+ let nodes = builder.build({ children, items }, context);
48
+ return factory(nodes);
49
+ },
50
+ [builder, children, items, collection, context, factory],
51
+ subSlot(slot, 'collection'),
52
+ );
53
+ return result;
54
+ }