@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,192 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/selection/useTypeSelect.ts).
2
+ // octane adaptations:
3
+ // - Handlers receive NATIVE KeyboardEvents (there is no synthetic layer). The
4
+ // `'continuePropagation' in e` probes port verbatim: they distinguish events wrapped by
5
+ // the ported useKeyboard machinery (whose BaseEvent shim carries continuePropagation/
6
+ // isPropagationStopped) from plain delegated events.
7
+ // - `e.currentTarget` casts to Element (octane's delegated dispatch guarantees the
8
+ // per-handler currentTarget; native types say EventTarget | null).
9
+ // - Public-hook slot threading (splitSlot/subSlot) per the binding convention.
10
+ // - MultipleSelectionManager type from the ported stately selection types.
11
+ import type { Key, KeyboardDelegate } from '@react-types/shared';
12
+ import { getEventTarget, nodeContains } from '../utils/shadowdom/DOMFunctions';
13
+ import { useEffect, useRef } from 'octane';
14
+ import type { MultipleSelectionManager } from '../stately/selection/types';
15
+
16
+ import { S, splitSlot, subSlot } from '../internal';
17
+
18
+ // octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
19
+ // handler types along).
20
+ type DOMAttributes = Record<string, any>;
21
+
22
+ /**
23
+ * Controls how long to wait before clearing the typeahead buffer.
24
+ */
25
+ const TYPEAHEAD_DEBOUNCE_WAIT_MS = 1000; // 1 second
26
+
27
+ export interface AriaTypeSelectOptions {
28
+ /**
29
+ * A delegate that returns collection item keys with respect to visual layout.
30
+ */
31
+ keyboardDelegate: KeyboardDelegate;
32
+ /**
33
+ * An interface for reading and updating multiple selection state.
34
+ */
35
+ selectionManager: MultipleSelectionManager;
36
+ /**
37
+ * Called when an item is focused by typing.
38
+ */
39
+ onTypeSelect?: (key: Key) => void;
40
+ }
41
+
42
+ export interface TypeSelectAria {
43
+ /**
44
+ * Props to be spread on the owner of the options.
45
+ */
46
+ typeSelectProps: DOMAttributes;
47
+ }
48
+
49
+ /**
50
+ * Handles typeahead interactions with collections.
51
+ */
52
+ export function useTypeSelect(options: AriaTypeSelectOptions): TypeSelectAria;
53
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
54
+ export function useTypeSelect(
55
+ options: AriaTypeSelectOptions,
56
+ slot: symbol | undefined,
57
+ ): TypeSelectAria;
58
+ export function useTypeSelect(...args: any[]): TypeSelectAria {
59
+ const [user, slotArg] = splitSlot(args);
60
+ const slot = slotArg ?? S('useTypeSelect');
61
+ const options = user[0] as AriaTypeSelectOptions;
62
+
63
+ let { keyboardDelegate, selectionManager, onTypeSelect } = options;
64
+ let state = useRef<{ search: string; timeout: ReturnType<typeof setTimeout> | undefined }>(
65
+ {
66
+ search: '',
67
+ timeout: undefined,
68
+ },
69
+ subSlot(slot, 'state'),
70
+ );
71
+
72
+ let onKeyDownCapture = (e: KeyboardEvent) => {
73
+ // if we're in the middle of a search, then a spacebar should be treated as a search and we should not propagate the event
74
+ // since we handle this one in a capture phase, we should ignore it in the bubble phase
75
+ if (state.current.search.length > 0 && e.key === ' ') {
76
+ e.preventDefault();
77
+ if (
78
+ !('continuePropagation' in e) ||
79
+ ('continuePropagation' in e && !(e as any).isPropagationStopped())
80
+ ) {
81
+ e.stopPropagation();
82
+ }
83
+ state.current.search += ' ';
84
+
85
+ if (keyboardDelegate.getKeyForSearch != null) {
86
+ // Use the delegate to find a key to focus.
87
+ // Prioritize items after the currently focused item, falling back to searching the whole list.
88
+ let key = keyboardDelegate.getKeyForSearch(
89
+ state.current.search,
90
+ selectionManager.focusedKey,
91
+ );
92
+
93
+ // If no key found, search from the top.
94
+ if (key == null) {
95
+ key = keyboardDelegate.getKeyForSearch(state.current.search);
96
+ }
97
+
98
+ if (key != null) {
99
+ selectionManager.setFocusedKey(key);
100
+ if (onTypeSelect) {
101
+ onTypeSelect(key);
102
+ }
103
+ }
104
+ }
105
+
106
+ clearTimeout(state.current.timeout);
107
+ state.current.timeout = setTimeout(() => {
108
+ state.current.search = '';
109
+ }, TYPEAHEAD_DEBOUNCE_WAIT_MS);
110
+ }
111
+ };
112
+
113
+ let onKeyDown = (e: KeyboardEvent) => {
114
+ let character = getStringForKey(e.key);
115
+ if (
116
+ !character ||
117
+ e.ctrlKey ||
118
+ e.metaKey ||
119
+ e.altKey ||
120
+ !nodeContains(e.currentTarget as Element, getEventTarget(e) as HTMLElement) ||
121
+ (state.current.search.length === 0 && character === ' ')
122
+ ) {
123
+ return;
124
+ }
125
+
126
+ state.current.search += character;
127
+
128
+ if (keyboardDelegate.getKeyForSearch != null) {
129
+ // Use the delegate to find a key to focus.
130
+ // Prioritize items after the currently focused item, falling back to searching the whole list.
131
+ let key = keyboardDelegate.getKeyForSearch(state.current.search, selectionManager.focusedKey);
132
+
133
+ if (key == null) {
134
+ key = keyboardDelegate.getKeyForSearch(state.current.search);
135
+ }
136
+
137
+ if (key != null) {
138
+ selectionManager.setFocusedKey(key);
139
+ if (onTypeSelect) {
140
+ onTypeSelect(key);
141
+ }
142
+ e.preventDefault();
143
+ if (!('continuePropagation' in e)) {
144
+ e.stopPropagation();
145
+ }
146
+ } else {
147
+ // if still nothing then the type to select is done and everything is reset
148
+ state.current.search = '';
149
+ clearTimeout(state.current.timeout);
150
+ state.current.timeout = undefined;
151
+ return;
152
+ }
153
+ }
154
+
155
+ clearTimeout(state.current.timeout);
156
+ state.current.timeout = setTimeout(() => {
157
+ state.current.search = '';
158
+ }, TYPEAHEAD_DEBOUNCE_WAIT_MS);
159
+ };
160
+
161
+ useEffect(
162
+ () => {
163
+ let timeout = state.current.timeout;
164
+ return () => {
165
+ clearTimeout(timeout);
166
+ };
167
+ },
168
+ [state],
169
+ subSlot(slot, 'teardown'),
170
+ );
171
+
172
+ return {
173
+ typeSelectProps: {
174
+ // Using a capturing listener to catch the keydown event before
175
+ // other hooks in order to handle the Spacebar event.
176
+ onKeyDownCapture: keyboardDelegate.getKeyForSearch ? onKeyDownCapture : undefined,
177
+ onKeyDown: keyboardDelegate.getKeyForSearch ? onKeyDown : undefined,
178
+ },
179
+ };
180
+ }
181
+
182
+ function getStringForKey(key: string) {
183
+ // If the key is of length 1, it is an ASCII value.
184
+ // Otherwise, if there are no ASCII characters in the key name,
185
+ // it is a Unicode character.
186
+ // See https://www.w3.org/TR/uievents-key/
187
+ if (key.length === 1 || !/^[A-Z]/i.test(key)) {
188
+ return key;
189
+ }
190
+
191
+ return '';
192
+ }
@@ -0,0 +1,50 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/selection/utils.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) for useCollectionId per
3
+ // the binding convention; RefObject type from @react-types/shared (upstream: React's RefObject).
4
+ import type { Collection, Key, RefObject } from '@react-types/shared';
5
+ import { isAppleDevice } from '../utils/platform';
6
+
7
+ import { S, splitSlot, subSlot } from '../internal';
8
+ import { useId } from '../utils/useId';
9
+
10
+ interface Event {
11
+ altKey: boolean;
12
+ ctrlKey: boolean;
13
+ metaKey: boolean;
14
+ }
15
+
16
+ export function isNonContiguousSelectionModifier(e: Event): boolean {
17
+ // Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.
18
+ // On Windows and Ubuntu, Alt + Space has a system wide meaning.
19
+ return isAppleDevice() ? e.altKey : e.ctrlKey;
20
+ }
21
+
22
+ export function getItemElement(
23
+ collectionRef: RefObject<HTMLElement | null>,
24
+ key: Key,
25
+ ): Element | null | undefined {
26
+ let selector = `[data-key="${CSS.escape(String(key))}"]`;
27
+ let collection = collectionRef.current?.dataset.collection;
28
+ if (collection) {
29
+ selector = `[data-collection="${CSS.escape(collection)}"]${selector}`;
30
+ }
31
+ return collectionRef.current?.querySelector(selector);
32
+ }
33
+
34
+ const collectionMap = new WeakMap<Collection<any>, string>();
35
+ export function useCollectionId(collection: Collection<any>): string;
36
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
37
+ export function useCollectionId(collection: Collection<any>, slot: symbol | undefined): string;
38
+ export function useCollectionId(...args: any[]): string {
39
+ const [user, slotArg] = splitSlot(args);
40
+ const slot = slotArg ?? S('useCollectionId');
41
+ const collection = user[0] as Collection<any>;
42
+
43
+ let id = useId(undefined, subSlot(slot, 'id'));
44
+ collectionMap.set(collection, id);
45
+ return id;
46
+ }
47
+
48
+ export function getCollectionId(collection: Collection<any>): string {
49
+ return collectionMap.get(collection)!;
50
+ }
@@ -0,0 +1,41 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/separator/useSeparator.ts).
2
+ import type { AriaLabelingProps, DOMAttributes, DOMProps, Orientation } from '@react-types/shared';
3
+
4
+ import { filterDOMProps } from '../utils/filterDOMProps';
5
+
6
+ export interface SeparatorProps extends DOMProps, AriaLabelingProps {
7
+ /**
8
+ * The orientation of the separator.
9
+ *
10
+ * @default 'horizontal'
11
+ */
12
+ orientation?: Orientation;
13
+ /** The HTML element type that will be used to render the separator. */
14
+ elementType?: string;
15
+ }
16
+
17
+ export interface SeparatorAria {
18
+ /** Props for the separator element. */
19
+ separatorProps: DOMAttributes;
20
+ }
21
+
22
+ export function useSeparator(props: SeparatorProps): SeparatorAria {
23
+ let domProps = filterDOMProps(props, { labelable: true });
24
+ let ariaOrientation: 'vertical' | undefined;
25
+ // if orientation is horizontal, aria-orientation default is horizontal, so we leave it undefined
26
+ // if it's vertical, we need to specify it
27
+ if (props.orientation === 'vertical') {
28
+ ariaOrientation = 'vertical';
29
+ }
30
+ // hr elements implicitly have role = separator and a horizontal orientation
31
+ if (props.elementType !== 'hr') {
32
+ return {
33
+ separatorProps: {
34
+ ...domProps,
35
+ role: 'separator',
36
+ 'aria-orientation': ariaOrientation,
37
+ },
38
+ };
39
+ }
40
+ return { separatorProps: domProps };
41
+ }
@@ -0,0 +1,277 @@
1
+ // Ported from react-aria (source: .react-spectrum/packages/react-aria/src/slider/useSlider.ts).
2
+ // octane adaptations:
3
+ // - Handlers receive NATIVE events (there is no synthetic layer): the track's
4
+ // onMouseDown/onPointerDown/onTouchStart props take native MouseEvent/PointerEvent/
5
+ // TouchEvent, and `onDownTrack`'s event parameter is the native event union.
6
+ // - React's LabelHTMLAttributes/OutputHTMLAttributes element types collapse to the local
7
+ // structural `DOMAttributes` prop bag.
8
+ // - `clamp` comes from the ported stately number utils; `SliderProps`/`SliderState` from
9
+ // the ported stately slider hook.
10
+ // - Public-hook slot threading (splitSlot/subSlot).
11
+ import type { AriaLabelingProps, DOMProps, RefObject } from '@react-types/shared';
12
+ import { clamp } from '../stately/utils/number';
13
+ import { getSliderThumbId, sliderData } from './utils';
14
+ import { mergeProps } from '../utils/mergeProps';
15
+ import { useRef } from 'octane';
16
+ import { setInteractionModality } from '../interactions/useFocusVisible';
17
+ import type { SliderProps, SliderState } from '../stately/slider/useSliderState';
18
+ import { useGlobalListeners } from '../utils/useGlobalListeners';
19
+ import { useLabel } from '../label/useLabel';
20
+ import { useLocale } from '../i18n/I18nProvider';
21
+ import { useMove } from '../interactions/useMove';
22
+
23
+ import { S, splitSlot, subSlot } from '../internal';
24
+
25
+ // octane adaptation: minimal structural DOMAttributes (upstream's drags React's synthetic
26
+ // handler types along).
27
+ type DOMAttributes = Record<string, any>;
28
+
29
+ export interface AriaSliderProps<T = number | number[]>
30
+ extends SliderProps<T>, DOMProps, AriaLabelingProps {}
31
+
32
+ export interface SliderAria {
33
+ /** Props for the label element. */
34
+ labelProps: DOMAttributes;
35
+
36
+ /** Props for the root element of the slider component; groups slider inputs. */
37
+ groupProps: DOMAttributes;
38
+
39
+ /** Props for the track element. */
40
+ trackProps: DOMAttributes;
41
+
42
+ /** Props for the output element, displaying the value of the slider thumbs. */
43
+ outputProps: DOMAttributes;
44
+ }
45
+
46
+ /**
47
+ * Provides the behavior and accessibility implementation for a slider component representing one or
48
+ * more values.
49
+ *
50
+ * @param props Props for the slider.
51
+ * @param state State for the slider, as returned by `useSliderState`.
52
+ * @param trackRef Ref for the "track" element. The width of this element provides the "length"
53
+ * of the track -- the span of one dimensional space that the slider thumb can be. It also
54
+ * accepts click and drag motions, so that the closest thumb will follow clicks and drags on
55
+ * the track.
56
+ */
57
+ export function useSlider<T extends number | number[]>(
58
+ props: AriaSliderProps<T>,
59
+ state: SliderState,
60
+ trackRef: RefObject<Element | null>,
61
+ ): SliderAria;
62
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
63
+ export function useSlider<T extends number | number[]>(
64
+ props: AriaSliderProps<T>,
65
+ state: SliderState,
66
+ trackRef: RefObject<Element | null>,
67
+ slot: symbol | undefined,
68
+ ): SliderAria;
69
+ export function useSlider(...args: any[]): SliderAria {
70
+ const [user, slotArg] = splitSlot(args);
71
+ const slot = slotArg ?? S('useSlider');
72
+ const props = user[0] as AriaSliderProps<any>;
73
+ const state = user[1] as SliderState;
74
+ const trackRef = user[2] as RefObject<Element | null>;
75
+
76
+ let { labelProps, fieldProps } = useLabel(props, subSlot(slot, 'label'));
77
+
78
+ let isVertical = props.orientation === 'vertical';
79
+
80
+ // Attach id of the label to the state so it can be accessed by useSliderThumb.
81
+ sliderData.set(state, {
82
+ id: (labelProps.id ?? fieldProps.id)!,
83
+ 'aria-describedby': props['aria-describedby'],
84
+ 'aria-details': props['aria-details'],
85
+ });
86
+
87
+ let { direction } = useLocale(subSlot(slot, 'locale'));
88
+
89
+ let { addGlobalListener, removeGlobalListener } = useGlobalListeners(
90
+ subSlot(slot, 'globalListeners'),
91
+ );
92
+
93
+ // When the user clicks or drags the track, we want the motion to set and drag the
94
+ // closest thumb. Hence we also need to install useMove() on the track element.
95
+ // Here, we keep track of which index is the "closest" to the drag start point.
96
+ // It is set onMouseDown/onTouchDown; see trackProps below.
97
+ const realTimeTrackDraggingIndex = useRef<number | null>(null, subSlot(slot, 'dragIndex'));
98
+
99
+ const reverseX = direction === 'rtl';
100
+ const currentPosition = useRef<number | null>(null, subSlot(slot, 'position'));
101
+ const { moveProps } = useMove(
102
+ {
103
+ onMoveStart() {
104
+ currentPosition.current = null;
105
+ },
106
+ onMove({ deltaX, deltaY }) {
107
+ if (!trackRef.current) {
108
+ return;
109
+ }
110
+ let { height, width } = trackRef.current.getBoundingClientRect();
111
+ let size = isVertical ? height : width;
112
+
113
+ if (currentPosition.current == null && realTimeTrackDraggingIndex.current != null) {
114
+ currentPosition.current =
115
+ state.getThumbPercent(realTimeTrackDraggingIndex.current) * size;
116
+ }
117
+
118
+ let delta = isVertical ? deltaY : deltaX;
119
+ if (isVertical || reverseX) {
120
+ delta = -delta;
121
+ }
122
+
123
+ currentPosition.current! += delta;
124
+
125
+ if (realTimeTrackDraggingIndex.current != null && trackRef.current) {
126
+ const percent = clamp(currentPosition.current! / size, 0, 1);
127
+ state.setThumbPercent(realTimeTrackDraggingIndex.current, percent);
128
+ }
129
+ },
130
+ onMoveEnd() {
131
+ if (realTimeTrackDraggingIndex.current != null) {
132
+ state.setThumbDragging(realTimeTrackDraggingIndex.current, false);
133
+ realTimeTrackDraggingIndex.current = null;
134
+ }
135
+ },
136
+ },
137
+ subSlot(slot, 'move'),
138
+ );
139
+
140
+ let currentPointer = useRef<number | null | undefined>(undefined, subSlot(slot, 'pointer'));
141
+ let onDownTrack = (
142
+ e: MouseEvent | PointerEvent | TouchEvent,
143
+ id: number | undefined,
144
+ clientX: number,
145
+ clientY: number,
146
+ ) => {
147
+ // We only trigger track-dragging if the user clicks on the track itself and nothing is currently being dragged.
148
+ if (
149
+ trackRef.current &&
150
+ !props.isDisabled &&
151
+ state.values.every((_, i) => !state.isThumbDragging(i))
152
+ ) {
153
+ let { height, width, top, left } = trackRef.current.getBoundingClientRect();
154
+ let size = isVertical ? height : width;
155
+ // Find the closest thumb
156
+ const trackPosition = isVertical ? top : left;
157
+ const clickPosition = isVertical ? clientY : clientX;
158
+ const offset = clickPosition - trackPosition;
159
+ let percent = offset / size;
160
+ if (direction === 'rtl' || isVertical) {
161
+ percent = 1 - percent;
162
+ }
163
+ let value = state.getPercentValue(percent);
164
+
165
+ // to find the closet thumb we split the array based on the first thumb position to the "right/end" of the click.
166
+ let closestThumb;
167
+ let split = state.values.findIndex((v) => value - v < 0);
168
+ if (split === 0) {
169
+ // If the index is zero then the closetThumb is the first one
170
+ closestThumb = split;
171
+ } else if (split === -1) {
172
+ // If no index is found they've clicked past all the thumbs
173
+ closestThumb = state.values.length - 1;
174
+ } else {
175
+ let lastLeft = state.values[split - 1];
176
+ let firstRight = state.values[split];
177
+ // Pick the last left/start thumb, unless they are stacked on top of each other, then pick the right/end one
178
+ if (Math.abs(lastLeft - value) < Math.abs(firstRight - value)) {
179
+ closestThumb = split - 1;
180
+ } else {
181
+ closestThumb = split;
182
+ }
183
+ }
184
+
185
+ // Confirm that the found closest thumb is editable, not disabled, and move it
186
+ if (closestThumb >= 0 && state.isThumbEditable(closestThumb)) {
187
+ // Don't unfocus anything
188
+ e.preventDefault();
189
+
190
+ realTimeTrackDraggingIndex.current = closestThumb;
191
+ state.setFocusedThumb(closestThumb);
192
+ currentPointer.current = id;
193
+
194
+ state.setThumbDragging(realTimeTrackDraggingIndex.current!, true);
195
+ state.setThumbValue(closestThumb, value);
196
+
197
+ addGlobalListener(window, 'mouseup', onUpTrack, false);
198
+ addGlobalListener(window, 'touchend', onUpTrack, false);
199
+ addGlobalListener(window, 'pointerup', onUpTrack, false);
200
+ } else {
201
+ realTimeTrackDraggingIndex.current = null;
202
+ }
203
+ }
204
+ };
205
+
206
+ let onUpTrack = (e: any) => {
207
+ let id = e.pointerId ?? e.changedTouches?.[0].identifier;
208
+ if (id === currentPointer.current) {
209
+ if (realTimeTrackDraggingIndex.current != null) {
210
+ state.setThumbDragging(realTimeTrackDraggingIndex.current, false);
211
+ realTimeTrackDraggingIndex.current = null;
212
+ }
213
+
214
+ removeGlobalListener(window, 'mouseup', onUpTrack, false);
215
+ removeGlobalListener(window, 'touchend', onUpTrack, false);
216
+ removeGlobalListener(window, 'pointerup', onUpTrack, false);
217
+ }
218
+ };
219
+
220
+ if ('htmlFor' in labelProps && labelProps.htmlFor) {
221
+ // Ideally the `for` attribute should point to the first thumb, but VoiceOver on iOS
222
+ // causes this to override the `aria-labelledby` on the thumb. This causes the first
223
+ // thumb to only be announced as the slider label rather than its individual name as well.
224
+ // See https://bugs.webkit.org/show_bug.cgi?id=172464.
225
+ delete labelProps.htmlFor;
226
+ labelProps.onClick = () => {
227
+ // Safari does not focus <input type="range"> elements when clicking on an associated <label>,
228
+ // so do it manually. In addition, make sure we show the focus ring.
229
+ document.getElementById(getSliderThumbId(state, 0))?.focus();
230
+ setInteractionModality('keyboard');
231
+ };
232
+ }
233
+
234
+ return {
235
+ labelProps,
236
+ // The root element of the Slider will have role="group" to group together
237
+ // all the thumb inputs in the Slider. The label of the Slider will
238
+ // be used to label the group.
239
+ groupProps: {
240
+ role: 'group',
241
+ ...fieldProps,
242
+ },
243
+ trackProps: mergeProps(
244
+ {
245
+ onMouseDown(e: MouseEvent) {
246
+ if (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey) {
247
+ return;
248
+ }
249
+ onDownTrack(e, undefined, e.clientX, e.clientY);
250
+ },
251
+ onPointerDown(e: PointerEvent) {
252
+ if (e.pointerType === 'mouse' && (e.button !== 0 || e.altKey || e.ctrlKey || e.metaKey)) {
253
+ return;
254
+ }
255
+ onDownTrack(e, e.pointerId, e.clientX, e.clientY);
256
+ },
257
+ onTouchStart(e: TouchEvent) {
258
+ onDownTrack(
259
+ e,
260
+ e.changedTouches[0].identifier,
261
+ e.changedTouches[0].clientX,
262
+ e.changedTouches[0].clientY,
263
+ );
264
+ },
265
+ style: {
266
+ position: 'relative',
267
+ touchAction: 'none',
268
+ },
269
+ },
270
+ moveProps,
271
+ ),
272
+ outputProps: {
273
+ htmlFor: state.values.map((_, index) => getSliderThumbId(state, index)).join(' '),
274
+ 'aria-live': 'off',
275
+ },
276
+ };
277
+ }