@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,149 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tabs/useTabListState.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; upstream's intentionally dep-less useEffect becomes an explicit `null`
4
+ // (run after every render).
5
+ import type {
6
+ Collection,
7
+ CollectionBase,
8
+ CollectionStateBase,
9
+ Key,
10
+ Node,
11
+ SingleSelection,
12
+ } from '@react-types/shared';
13
+ import { useEffect, useRef } from 'octane';
14
+
15
+ import { S, splitSlot, subSlot } from '../../internal';
16
+ import {
17
+ type SingleSelectListState,
18
+ useSingleSelectListState,
19
+ } from '../list/useSingleSelectListState';
20
+
21
+ export interface TabListProps<T>
22
+ extends
23
+ CollectionBase<T>,
24
+ Omit<
25
+ SingleSelection,
26
+ 'disallowEmptySelection' | 'selectedKey' | 'defaultSelectedKey' | 'onSelectionChange'
27
+ > {
28
+ /**
29
+ * Whether the TabList is disabled.
30
+ * Shows that a selection exists, but is not available in that circumstance.
31
+ */
32
+ isDisabled?: boolean;
33
+ /** The currently selected key in the collection (controlled). */
34
+ selectedKey?: Key;
35
+ /** The initial selected keys in the collection (uncontrolled). */
36
+ defaultSelectedKey?: Key;
37
+ /** Handler that is called when the selection changes. */
38
+ onSelectionChange?: (key: Key) => void;
39
+ }
40
+
41
+ export interface TabListStateOptions<T>
42
+ extends Omit<TabListProps<T>, 'children'>, CollectionStateBase<T> {}
43
+
44
+ export interface TabListState<T> extends SingleSelectListState<T> {
45
+ /** Whether the tab list is disabled. */
46
+ isDisabled: boolean;
47
+ }
48
+
49
+ /**
50
+ * Provides state management for a Tabs component. Tabs include a TabList which tracks
51
+ * which tab is currently selected and displays the content associated with that Tab in a TabPanel.
52
+ */
53
+ export function useTabListState<T extends object>(props: TabListStateOptions<T>): TabListState<T>;
54
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
55
+ export function useTabListState<T extends object>(
56
+ props: TabListStateOptions<T>,
57
+ slot: symbol | undefined,
58
+ ): TabListState<T>;
59
+ export function useTabListState(...args: any[]): TabListState<any> {
60
+ const [user, slotArg] = splitSlot(args);
61
+ const slot = slotArg ?? S('useTabListState');
62
+ const props = user[0] as TabListStateOptions<any>;
63
+
64
+ let state = useSingleSelectListState<any>(
65
+ {
66
+ ...props,
67
+ onSelectionChange: props.onSelectionChange
68
+ ? (key: Key | null) => {
69
+ if (key != null) {
70
+ props.onSelectionChange?.(key);
71
+ }
72
+ }
73
+ : undefined,
74
+ suppressTextValueWarning: true,
75
+ defaultSelectedKey:
76
+ props.defaultSelectedKey ??
77
+ findDefaultSelectedKey(
78
+ props.collection,
79
+ props.disabledKeys ? new Set(props.disabledKeys) : new Set(),
80
+ ) ??
81
+ undefined,
82
+ },
83
+ subSlot(slot, 'list'),
84
+ );
85
+
86
+ let { selectionManager, collection, selectedKey: currentSelectedKey } = state;
87
+
88
+ let lastSelectedKey = useRef(currentSelectedKey, subSlot(slot, 'lastSelected'));
89
+ useEffect(
90
+ () => {
91
+ // Ensure a tab is always selected (in case no selected key was specified or if selected item was deleted from collection)
92
+ let selectedKey = currentSelectedKey;
93
+ if (
94
+ props.selectedKey == null &&
95
+ (selectionManager.isEmpty || selectedKey == null || !collection.getItem(selectedKey))
96
+ ) {
97
+ selectedKey = findDefaultSelectedKey(collection, state.disabledKeys);
98
+ if (selectedKey != null) {
99
+ // directly set selection because replace/toggle selection won't consider disabled keys
100
+ selectionManager.setSelectedKeys([selectedKey]);
101
+ }
102
+ }
103
+
104
+ // If the tablist doesn't have focus and the selected key changes or if there isn't a focused key yet, change focused key to the selected key if it exists.
105
+ if (
106
+ (selectedKey != null && selectionManager.focusedKey == null) ||
107
+ (!selectionManager.isFocused && selectedKey !== lastSelectedKey.current)
108
+ ) {
109
+ selectionManager.setFocusedKey(selectedKey);
110
+ }
111
+ lastSelectedKey.current = selectedKey;
112
+ },
113
+ null,
114
+ subSlot(slot, 'ensureSelected'),
115
+ );
116
+
117
+ return {
118
+ ...state,
119
+ isDisabled: props.isDisabled || false,
120
+ };
121
+ }
122
+
123
+ function findDefaultSelectedKey<T>(
124
+ collection: Collection<Node<T>> | undefined,
125
+ disabledKeys: Set<Key>,
126
+ ) {
127
+ let selectedKey: Key | null = null;
128
+ if (collection) {
129
+ selectedKey = collection.getFirstKey();
130
+ // loop over tabs until we find one that isn't disabled and select that
131
+ while (
132
+ selectedKey != null &&
133
+ (disabledKeys.has(selectedKey) || collection.getItem(selectedKey)?.props?.isDisabled) &&
134
+ selectedKey !== collection.getLastKey()
135
+ ) {
136
+ selectedKey = collection.getKeyAfter(selectedKey);
137
+ }
138
+ // if this check is true, then every item is disabled, it makes more sense to default to the first key than the last
139
+ if (
140
+ selectedKey != null &&
141
+ (disabledKeys.has(selectedKey) || collection.getItem(selectedKey)?.props?.isDisabled) &&
142
+ selectedKey === collection.getLastKey()
143
+ ) {
144
+ selectedKey = collection.getFirstKey();
145
+ }
146
+ }
147
+
148
+ return selectedKey;
149
+ }
@@ -0,0 +1,109 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/toggle/useToggleGroupState.ts).
2
+ // Its import closure is confined to `useControlledState` + `@react-types/shared` (no
3
+ // list/selection modules), so it lands in Phase 1. octane adaptations: public-hook slot
4
+ // threading (splitSlot/subSlot) per the binding convention; explicit `Set<Key>` element
5
+ // types on the default-set constructions (strict inference); explicit useMemo dep arrays
6
+ // preserved exactly.
7
+ import type { Key } from '@react-types/shared';
8
+ import { useMemo } from 'octane';
9
+
10
+ import { S, splitSlot, subSlot } from '../../internal';
11
+ import { useControlledState } from '../utils/useControlledState';
12
+
13
+ export interface ToggleGroupProps {
14
+ /**
15
+ * Whether single or multiple selection is enabled.
16
+ *
17
+ * @default 'single'
18
+ */
19
+ selectionMode?: 'single' | 'multiple';
20
+ /** Whether the collection allows empty selection. */
21
+ disallowEmptySelection?: boolean;
22
+ /** The currently selected keys in the collection (controlled). */
23
+ selectedKeys?: Iterable<Key>;
24
+ /** The initial selected keys in the collection (uncontrolled). */
25
+ defaultSelectedKeys?: Iterable<Key>;
26
+ /** Handler that is called when the selection changes. */
27
+ onSelectionChange?: (keys: Set<Key>) => void;
28
+ /** Whether all items are disabled. */
29
+ isDisabled?: boolean;
30
+ }
31
+
32
+ export interface ToggleGroupState {
33
+ /** Whether single or multiple selection is enabled. */
34
+ readonly selectionMode: 'single' | 'multiple';
35
+
36
+ /** Whether all items are disabled. */
37
+ readonly isDisabled: boolean;
38
+
39
+ /** A set of keys for items that are selected. */
40
+ readonly selectedKeys: Set<Key>;
41
+
42
+ /** Toggles the selected state for an item by its key. */
43
+ toggleKey(key: Key): void;
44
+
45
+ /** Sets whether the given key is selected. */
46
+ setSelected(key: Key, isSelected: boolean): void;
47
+
48
+ /** Replaces the set of selected keys. */
49
+ setSelectedKeys(keys: Set<Key>): void;
50
+ }
51
+
52
+ /**
53
+ * Manages state for a group of toggles.
54
+ * It supports both single and multiple selected items.
55
+ */
56
+ export function useToggleGroupState(props: ToggleGroupProps): ToggleGroupState;
57
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
58
+ export function useToggleGroupState(
59
+ props: ToggleGroupProps,
60
+ slot: symbol | undefined,
61
+ ): ToggleGroupState;
62
+ export function useToggleGroupState(...args: any[]): ToggleGroupState {
63
+ const [user, slotArg] = splitSlot(args);
64
+ const slot = slotArg ?? S('useToggleGroupState');
65
+ const props = user[0] as ToggleGroupProps;
66
+
67
+ let { selectionMode = 'single', disallowEmptySelection, isDisabled = false } = props;
68
+ let [selectedKeys, setSelectedKeys] = useControlledState(
69
+ useMemo(
70
+ () => (props.selectedKeys ? new Set(props.selectedKeys) : undefined),
71
+ [props.selectedKeys],
72
+ subSlot(slot, 'controlled'),
73
+ ),
74
+ useMemo(
75
+ () => (props.defaultSelectedKeys ? new Set(props.defaultSelectedKeys) : new Set<Key>()),
76
+ [props.defaultSelectedKeys],
77
+ subSlot(slot, 'default'),
78
+ ),
79
+ props.onSelectionChange,
80
+ subSlot(slot, 'keys'),
81
+ );
82
+
83
+ return {
84
+ selectionMode,
85
+ isDisabled,
86
+ selectedKeys,
87
+ setSelectedKeys,
88
+ toggleKey(key) {
89
+ let keys: Set<Key>;
90
+ if (selectionMode === 'multiple') {
91
+ keys = new Set(selectedKeys);
92
+ if (keys.has(key) && (!disallowEmptySelection || keys.size > 1)) {
93
+ keys.delete(key);
94
+ } else {
95
+ keys.add(key);
96
+ }
97
+ } else {
98
+ keys = new Set(selectedKeys.has(key) && !disallowEmptySelection ? [] : [key]);
99
+ }
100
+
101
+ setSelectedKeys(keys);
102
+ },
103
+ setSelected(key, isSelected) {
104
+ if (isSelected !== selectedKeys.has(key)) {
105
+ this.toggleKey(key);
106
+ }
107
+ },
108
+ };
109
+ }
@@ -0,0 +1,100 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/toggle/useToggleState.ts).
2
+ // octane adaptations: React's `ReactNode` children type → `any` (octane descriptors);
3
+ // `FocusableProps` comes from the ported interactions area (type-only — upstream's
4
+ // @react-types/shared version is typed over React synthetic events); public-hook slot
5
+ // threading (splitSlot/subSlot) per the binding convention. The public value-level
6
+ // `onChange` callback is unchanged (the onInput rule applies only to DOM wiring).
7
+ import type { InputBase, Validation } from '@react-types/shared';
8
+ import { useState } from 'octane';
9
+
10
+ import type { FocusableProps } from '../../interactions/useFocusable';
11
+
12
+ import { S, splitSlot, subSlot } from '../../internal';
13
+ import { useControlledState } from '../utils/useControlledState';
14
+
15
+ export interface ToggleStateOptions extends InputBase {
16
+ /**
17
+ * Whether the element should be selected (uncontrolled).
18
+ */
19
+ defaultSelected?: boolean;
20
+ /**
21
+ * Whether the element should be selected (controlled).
22
+ */
23
+ isSelected?: boolean;
24
+ /**
25
+ * Handler that is called when the element's selection state changes.
26
+ */
27
+ onChange?: (isSelected: boolean) => void;
28
+ }
29
+
30
+ export interface ToggleProps extends ToggleStateOptions, Validation<boolean>, FocusableProps {
31
+ /**
32
+ * The label for the element.
33
+ */
34
+ children?: any;
35
+ /**
36
+ * The value of the input element, used when submitting an HTML form. See
37
+ * [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefvalue).
38
+ */
39
+ value?: string;
40
+ }
41
+
42
+ export interface ToggleState {
43
+ /** Whether the toggle is selected. */
44
+ readonly isSelected: boolean;
45
+
46
+ /** Whether the toggle is selected by default. */
47
+ readonly defaultSelected: boolean;
48
+
49
+ /** Updates selection state. */
50
+ setSelected(isSelected: boolean): void;
51
+
52
+ /** Toggle the selection state. */
53
+ toggle(): void;
54
+ }
55
+
56
+ /**
57
+ * Provides state management for toggle components like checkboxes and switches.
58
+ */
59
+ export function useToggleState(props?: ToggleStateOptions): ToggleState;
60
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
61
+ export function useToggleState(
62
+ props: ToggleStateOptions | undefined,
63
+ slot: symbol | undefined,
64
+ ): ToggleState;
65
+ export function useToggleState(...args: any[]): ToggleState {
66
+ const [user, slotArg] = splitSlot(args);
67
+ const slot = slotArg ?? S('useToggleState');
68
+ const props = (user[0] as ToggleStateOptions | undefined) ?? {};
69
+
70
+ let { isReadOnly } = props;
71
+
72
+ // have to provide an empty function so useControlledState doesn't throw a fit
73
+ // can't use useControlledState's prop calling because we need the event object from the change
74
+ let [isSelected, setSelected] = useControlledState(
75
+ props.isSelected,
76
+ props.defaultSelected || false,
77
+ props.onChange,
78
+ subSlot(slot, 'selected'),
79
+ );
80
+ let [initialValue] = useState(isSelected, subSlot(slot, 'initial'));
81
+
82
+ function updateSelected(value: boolean) {
83
+ if (!isReadOnly) {
84
+ setSelected(value);
85
+ }
86
+ }
87
+
88
+ function toggleState() {
89
+ if (!isReadOnly) {
90
+ setSelected(!isSelected);
91
+ }
92
+ }
93
+
94
+ return {
95
+ isSelected,
96
+ defaultSelected: props.defaultSelected ?? initialValue,
97
+ setSelected: updateSelected,
98
+ toggle: toggleState,
99
+ };
100
+ }
@@ -0,0 +1,218 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tooltip/useTooltipTriggerState.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; the module-level warmup/cooldown timers and global tooltip registry are
4
+ // ported verbatim; upstream's explicit useEffect dep arrays are kept verbatim with a
5
+ // trailing subSlot.
6
+ import { useEffect, useMemo, useRef } from 'octane';
7
+
8
+ import { S, splitSlot, subSlot } from '../../internal';
9
+ import {
10
+ type OverlayTriggerProps,
11
+ useOverlayTriggerState,
12
+ } from '../overlays/useOverlayTriggerState';
13
+
14
+ export interface TooltipTriggerProps extends OverlayTriggerProps {
15
+ /**
16
+ * Whether the tooltip should be disabled, independent from the trigger.
17
+ */
18
+ isDisabled?: boolean;
19
+
20
+ /**
21
+ * The delay time for the tooltip to show up. [See
22
+ * guidelines](https://spectrum.adobe.com/page/tooltip/#Immediate-or-delayed-appearance).
23
+ *
24
+ * @default 1500
25
+ */
26
+ delay?: number;
27
+
28
+ /**
29
+ * The delay time for the tooltip to close. [See
30
+ * guidelines](https://spectrum.adobe.com/page/tooltip/#Warmup-and-cooldown).
31
+ *
32
+ * @default 500
33
+ */
34
+ closeDelay?: number;
35
+
36
+ /**
37
+ * By default, opens for both focus and hover. Can be made to open only for focus.
38
+ *
39
+ * @default 'hover'
40
+ */
41
+ trigger?: 'hover' | 'focus';
42
+
43
+ /**
44
+ * Whether the tooltip should close when the trigger is pressed.
45
+ *
46
+ * @default true
47
+ */
48
+ shouldCloseOnPress?: boolean;
49
+ }
50
+
51
+ const TOOLTIP_DELAY = 1500; // this seems to be a 1.5 second delay, check with design
52
+ const TOOLTIP_COOLDOWN = 500;
53
+
54
+ export interface TooltipTriggerState {
55
+ /** Whether the tooltip is currently showing. */
56
+ isOpen: boolean;
57
+ /**
58
+ * Shows the tooltip. By default, the tooltip becomes visible after a delay
59
+ * depending on a global warmup timer. The `immediate` option shows the
60
+ * tooltip immediately instead.
61
+ */
62
+ open(immediate?: boolean): void;
63
+ /** Hides the tooltip. */
64
+ close(immediate?: boolean): void;
65
+ }
66
+
67
+ // octane adaptation: loose index type (upstream's `{}`) so the cleanup's truthiness
68
+ // check on a registry entry isn't flagged as an always-defined function.
69
+ let tooltips: Record<string, any> = {};
70
+ let tooltipId = 0;
71
+ let globalWarmedUp = false;
72
+ let globalWarmUpTimeout: ReturnType<typeof setTimeout> | null = null;
73
+ let globalCooldownTimeout: ReturnType<typeof setTimeout> | null = null;
74
+
75
+ /**
76
+ * Manages state for a tooltip trigger. Tracks whether the tooltip is open, and provides
77
+ * methods to toggle this state. Ensures only one tooltip is open at a time and controls
78
+ * the delay for showing a tooltip.
79
+ */
80
+ export function useTooltipTriggerState(props?: TooltipTriggerProps): TooltipTriggerState;
81
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
82
+ export function useTooltipTriggerState(
83
+ props: TooltipTriggerProps | undefined,
84
+ slot: symbol | undefined,
85
+ ): TooltipTriggerState;
86
+ export function useTooltipTriggerState(...args: any[]): TooltipTriggerState {
87
+ const [user, slotArg] = splitSlot(args);
88
+ const slot = slotArg ?? S('useTooltipTriggerState');
89
+ const props = (user[0] as TooltipTriggerProps) ?? {};
90
+
91
+ let { delay = TOOLTIP_DELAY, closeDelay = TOOLTIP_COOLDOWN } = props;
92
+ let { isOpen, open, close } = useOverlayTriggerState(props, subSlot(slot, 'overlay'));
93
+ let id = useMemo(() => `${++tooltipId}`, [], subSlot(slot, 'id'));
94
+ let closeTimeout = useRef<ReturnType<typeof setTimeout> | null>(
95
+ null,
96
+ subSlot(slot, 'closeTimeout'),
97
+ );
98
+ let closeCallback = useRef<() => void>(close, subSlot(slot, 'closeCallback'));
99
+
100
+ let ensureTooltipEntry = () => {
101
+ tooltips[id] = hideTooltip;
102
+ };
103
+
104
+ let closeOpenTooltips = () => {
105
+ for (let hideTooltipId in tooltips) {
106
+ if (hideTooltipId !== id) {
107
+ tooltips[hideTooltipId](true);
108
+ delete tooltips[hideTooltipId];
109
+ }
110
+ }
111
+ };
112
+
113
+ let showTooltip = () => {
114
+ if (closeTimeout.current) {
115
+ clearTimeout(closeTimeout.current);
116
+ }
117
+ closeTimeout.current = null;
118
+ closeOpenTooltips();
119
+ ensureTooltipEntry();
120
+ globalWarmedUp = true;
121
+ open();
122
+ if (globalWarmUpTimeout) {
123
+ clearTimeout(globalWarmUpTimeout);
124
+ globalWarmUpTimeout = null;
125
+ }
126
+ if (globalCooldownTimeout) {
127
+ clearTimeout(globalCooldownTimeout);
128
+ globalCooldownTimeout = null;
129
+ }
130
+ };
131
+
132
+ let hideTooltip = (immediate?: boolean) => {
133
+ if (immediate || closeDelay <= 0) {
134
+ if (closeTimeout.current) {
135
+ clearTimeout(closeTimeout.current);
136
+ }
137
+ closeTimeout.current = null;
138
+ closeCallback.current();
139
+ } else if (!closeTimeout.current) {
140
+ closeTimeout.current = setTimeout(() => {
141
+ closeTimeout.current = null;
142
+ closeCallback.current();
143
+ }, closeDelay);
144
+ }
145
+
146
+ if (globalWarmUpTimeout) {
147
+ clearTimeout(globalWarmUpTimeout);
148
+ globalWarmUpTimeout = null;
149
+ }
150
+ if (globalWarmedUp) {
151
+ if (globalCooldownTimeout) {
152
+ clearTimeout(globalCooldownTimeout);
153
+ }
154
+ globalCooldownTimeout = setTimeout(
155
+ () => {
156
+ delete tooltips[id];
157
+ globalCooldownTimeout = null;
158
+ globalWarmedUp = false;
159
+ },
160
+ Math.max(TOOLTIP_COOLDOWN, closeDelay),
161
+ );
162
+ }
163
+ };
164
+
165
+ let warmupTooltip = () => {
166
+ closeOpenTooltips();
167
+ ensureTooltipEntry();
168
+ if (!isOpen && !globalWarmedUp) {
169
+ if (globalWarmUpTimeout) {
170
+ clearTimeout(globalWarmUpTimeout);
171
+ }
172
+
173
+ globalWarmUpTimeout = setTimeout(() => {
174
+ globalWarmUpTimeout = null;
175
+ globalWarmedUp = true;
176
+ showTooltip();
177
+ }, delay);
178
+ } else if (!isOpen) {
179
+ showTooltip();
180
+ }
181
+ };
182
+
183
+ useEffect(
184
+ () => {
185
+ closeCallback.current = close;
186
+ },
187
+ [close],
188
+ subSlot(slot, 'closeCallback'),
189
+ );
190
+
191
+ useEffect(
192
+ () => {
193
+ return () => {
194
+ if (closeTimeout.current) {
195
+ clearTimeout(closeTimeout.current);
196
+ }
197
+ let tooltip = tooltips[id];
198
+ if (tooltip) {
199
+ delete tooltips[id];
200
+ }
201
+ };
202
+ },
203
+ [id],
204
+ subSlot(slot, 'cleanup'),
205
+ );
206
+
207
+ return {
208
+ isOpen,
209
+ open: (immediate) => {
210
+ if (!immediate && delay > 0 && !closeTimeout.current) {
211
+ warmupTooltip();
212
+ } else {
213
+ showTooltip();
214
+ }
215
+ },
216
+ close: hideTooltip,
217
+ };
218
+ }
@@ -0,0 +1,92 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/tree/TreeCollection.ts).
2
+ // Verbatim (no React surface).
3
+ import type { Collection, Key, Node } from '@react-types/shared';
4
+
5
+ export class TreeCollection<T> implements Collection<Node<T>> {
6
+ private keyMap: Map<Key, Node<T>> = new Map();
7
+ private iterable: Iterable<Node<T>>;
8
+ private firstKey: Key | null = null;
9
+ private lastKey: Key | null = null;
10
+
11
+ constructor(nodes: Iterable<Node<T>>, { expandedKeys }: { expandedKeys?: Set<Key> } = {}) {
12
+ this.iterable = nodes;
13
+ expandedKeys = expandedKeys || new Set();
14
+
15
+ let visit = (node: Node<T>) => {
16
+ this.keyMap.set(node.key, node);
17
+
18
+ if (node.childNodes && (node.type === 'section' || expandedKeys.has(node.key))) {
19
+ for (let child of node.childNodes) {
20
+ visit(child);
21
+ }
22
+ }
23
+ };
24
+
25
+ for (let node of nodes) {
26
+ visit(node);
27
+ }
28
+
29
+ let last: Node<T> | null = null;
30
+ let index = 0;
31
+ for (let [key, node] of this.keyMap) {
32
+ if (last) {
33
+ last.nextKey = key;
34
+ node.prevKey = last.key;
35
+ } else {
36
+ this.firstKey = key;
37
+ node.prevKey = undefined;
38
+ }
39
+
40
+ if (node.type === 'item') {
41
+ node.index = index++;
42
+ }
43
+
44
+ last = node;
45
+
46
+ // Set nextKey as undefined since this might be the last node
47
+ // If it isn't the last node, last.nextKey will properly set at start of new loop
48
+ last.nextKey = undefined;
49
+ }
50
+
51
+ this.lastKey = last?.key ?? null;
52
+ }
53
+
54
+ *[Symbol.iterator](): IterableIterator<Node<T>> {
55
+ yield* this.iterable;
56
+ }
57
+
58
+ get size(): number {
59
+ return this.keyMap.size;
60
+ }
61
+
62
+ getKeys(): IterableIterator<Key> {
63
+ return this.keyMap.keys();
64
+ }
65
+
66
+ getKeyBefore(key: Key): Key | null {
67
+ let node = this.keyMap.get(key);
68
+ return node ? (node.prevKey ?? null) : null;
69
+ }
70
+
71
+ getKeyAfter(key: Key): Key | null {
72
+ let node = this.keyMap.get(key);
73
+ return node ? (node.nextKey ?? null) : null;
74
+ }
75
+
76
+ getFirstKey(): Key | null {
77
+ return this.firstKey;
78
+ }
79
+
80
+ getLastKey(): Key | null {
81
+ return this.lastKey;
82
+ }
83
+
84
+ getItem(key: Key): Node<T> | null {
85
+ return this.keyMap.get(key) ?? null;
86
+ }
87
+
88
+ at(idx: number): Node<T> | null {
89
+ const keys = [...this.getKeys()];
90
+ return this.getItem(keys[idx]);
91
+ }
92
+ }