@octanejs/aria 0.0.1 → 0.0.4

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,430 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/numberfield/useNumberFieldState.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; `FocusableProps` comes from the ported interactions area (type-only —
4
+ // upstream's @react-types/shared version is typed over React synthetic events); the
5
+ // public value-level `onChange` callback is unchanged (the onInput rule applies only to
6
+ // DOM wiring); `Intl.NumberFormatOptions` dynamic-key reads go through `Record<string,
7
+ // any>` casts (upstream relies on looser index typing); explicit dependency arrays are
8
+ // kept verbatim (they retain React's exact behavior in octane).
9
+ import { clamp, snapValueToStep } from '../utils/number';
10
+
11
+ import type {
12
+ HelpTextProps,
13
+ InputBase,
14
+ LabelableProps,
15
+ RangeInputBase,
16
+ TextInputBase,
17
+ Validation,
18
+ ValueBase,
19
+ } from '@react-types/shared';
20
+ import { NumberFormatter, NumberParser } from '@internationalized/number';
21
+ import { useCallback, useMemo, useState } from 'octane';
22
+
23
+ import type { FocusableProps } from '../../interactions/useFocusable';
24
+
25
+ import { S, splitSlot, subSlot } from '../../internal';
26
+ import { type FormValidationState, useFormValidationState } from '../form/useFormValidationState';
27
+ import { useControlledState } from '../utils/useControlledState';
28
+
29
+ export interface NumberFieldProps
30
+ extends
31
+ InputBase,
32
+ Validation<number>,
33
+ FocusableProps,
34
+ TextInputBase,
35
+ ValueBase<number>,
36
+ RangeInputBase<number>,
37
+ LabelableProps,
38
+ HelpTextProps {
39
+ /**
40
+ * Formatting options for the value displayed in the number field.
41
+ * This also affects what characters are allowed to be typed by the user.
42
+ */
43
+ formatOptions?: Intl.NumberFormatOptions;
44
+ /**
45
+ * Controls the behavior of the number field when the user blurs the field after editing. 'snap'
46
+ * will clamp the value to the min/max values, and snap to the nearest step value. 'validate' will
47
+ * not clamp the value, and will validate that the value is within the min/max range and on a
48
+ * valid step.
49
+ *
50
+ * @default 'snap'
51
+ */
52
+ commitBehavior?: 'snap' | 'validate';
53
+ }
54
+
55
+ export interface NumberFieldState extends FormValidationState {
56
+ /**
57
+ * The current text value of the input. Updated as the user types,
58
+ * and formatted according to `formatOptions` on blur.
59
+ */
60
+ inputValue: string;
61
+ /**
62
+ * The currently parsed number value, or NaN if a valid number could not be parsed.
63
+ * Updated based on the `inputValue` as the user types.
64
+ */
65
+ numberValue: number;
66
+ /** The default value of the input. */
67
+ defaultNumberValue: number;
68
+ /** The minimum value of the number field. */
69
+ minValue?: number;
70
+ /** The maximum value of the number field. */
71
+ maxValue?: number;
72
+ /** Whether the current value can be incremented according to the maximum value and step. */
73
+ canIncrement: boolean;
74
+ /** Whether the current value can be decremented according to the minimum value and step. */
75
+ canDecrement: boolean;
76
+ /**
77
+ * Validates a user input string according to the current locale and format options. Values can be
78
+ * partially entered, and may be valid even if they cannot currently be parsed to a number. Can be
79
+ * used to implement validation as a user types.
80
+ */
81
+ validate(value: string): boolean;
82
+ /** Sets the current text value of the input. */
83
+ setInputValue(val: string): void;
84
+ /** Sets the number value. */
85
+ setNumberValue(val: number): void;
86
+ /**
87
+ * Commits the current input value. The value is parsed to a number, clamped according to the
88
+ * minimum and maximum values of the field, and snapped to the nearest step value. This will fire
89
+ * the `onChange` prop with the new value, and if uncontrolled, update the `numberValue`.
90
+ * Typically this is called when the field is blurred.
91
+ *
92
+ * @param value - The value to commit. If not provided, the current input value is used.
93
+ */
94
+ commit(value?: string): void;
95
+ /** Increments the current input value to the next step boundary, and fires `onChange`. */
96
+ increment(): void;
97
+ /** Decrements the current input value to the next step boundary, and fires `onChange`. */
98
+ decrement(): void;
99
+ /** Sets the current value to the `maxValue` if any, and fires `onChange`. */
100
+ incrementToMax(): void;
101
+ /** Sets the current value to the `minValue` if any, and fires `onChange`. */
102
+ decrementToMin(): void;
103
+ }
104
+
105
+ export interface NumberFieldStateOptions extends NumberFieldProps {
106
+ /**
107
+ * The locale that should be used for parsing.
108
+ *
109
+ * @default 'en-US'
110
+ */
111
+ locale: string;
112
+ }
113
+
114
+ /**
115
+ * Provides state management for a number field component. Number fields allow users to enter a
116
+ * number, and increment or decrement the value using stepper buttons.
117
+ */
118
+ export function useNumberFieldState(props: NumberFieldStateOptions): NumberFieldState;
119
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
120
+ export function useNumberFieldState(
121
+ props: NumberFieldStateOptions,
122
+ slot: symbol | undefined,
123
+ ): NumberFieldState;
124
+ export function useNumberFieldState(...args: any[]): NumberFieldState {
125
+ const [user, slotArg] = splitSlot(args);
126
+ const slot = slotArg ?? S('useNumberFieldState');
127
+ const props = user[0] as NumberFieldStateOptions;
128
+
129
+ let {
130
+ minValue,
131
+ maxValue,
132
+ step,
133
+ formatOptions,
134
+ value,
135
+ defaultValue = NaN,
136
+ onChange,
137
+ locale,
138
+ isDisabled,
139
+ isReadOnly,
140
+ commitBehavior = 'snap',
141
+ } = props;
142
+
143
+ if (value === null) {
144
+ value = NaN;
145
+ }
146
+
147
+ let snapValue = useCallback(
148
+ (value: number) => {
149
+ return step === undefined || isNaN(step)
150
+ ? clamp(value, minValue, maxValue)
151
+ : snapValueToStep(value, minValue, maxValue, step);
152
+ },
153
+ [step, minValue, maxValue],
154
+ subSlot(slot, 'snap'),
155
+ );
156
+
157
+ if (value !== undefined && !isNaN(value) && commitBehavior === 'snap') {
158
+ value = snapValue(value);
159
+ }
160
+
161
+ if (!isNaN(defaultValue) && commitBehavior === 'snap') {
162
+ defaultValue = snapValue(defaultValue);
163
+ }
164
+
165
+ let [numberValue, setNumberValue] = useControlledState<number>(
166
+ value,
167
+ isNaN(defaultValue) ? NaN : defaultValue,
168
+ onChange,
169
+ subSlot(slot, 'number'),
170
+ );
171
+ let [initialValue] = useState(numberValue, subSlot(slot, 'initial'));
172
+ let [inputValue, setInputValue] = useState(
173
+ () =>
174
+ isNaN(numberValue) ? '' : new NumberFormatter(locale, formatOptions).format(numberValue),
175
+ subSlot(slot, 'input'),
176
+ );
177
+
178
+ let numberParser = useMemo(
179
+ () => new NumberParser(locale, formatOptions),
180
+ [locale, formatOptions],
181
+ subSlot(slot, 'parser'),
182
+ );
183
+ let numberingSystem = useMemo(
184
+ () => numberParser.getNumberingSystem(inputValue),
185
+ [numberParser, inputValue],
186
+ subSlot(slot, 'numbering'),
187
+ );
188
+ let formatter = useMemo(
189
+ () => new NumberFormatter(locale, { ...formatOptions, numberingSystem }),
190
+ [locale, formatOptions, numberingSystem],
191
+ subSlot(slot, 'formatter'),
192
+ );
193
+ let intlOptions = useMemo(() => formatter.resolvedOptions(), [formatter], subSlot(slot, 'intl'));
194
+ let format = useCallback(
195
+ (value: number) => (isNaN(value) || value === null ? '' : formatter.format(value)),
196
+ [formatter],
197
+ subSlot(slot, 'format'),
198
+ );
199
+
200
+ let validation = useFormValidationState(
201
+ {
202
+ ...props,
203
+ value: numberValue,
204
+ },
205
+ subSlot(slot, 'validation'),
206
+ );
207
+
208
+ let clampStep = step !== undefined && !isNaN(step) ? step : 1;
209
+ if (intlOptions.style === 'percent' && (step === undefined || isNaN(step))) {
210
+ clampStep = 0.01;
211
+ }
212
+
213
+ // Update the input value when the number value or format options change. This is done
214
+ // in a useEffect so that the controlled behavior is correct and we only update the
215
+ // textfield after prop changes.
216
+ let [prevValue, setPrevValue] = useState(numberValue, subSlot(slot, 'prevValue'));
217
+ let [prevLocale, setPrevLocale] = useState(locale, subSlot(slot, 'prevLocale'));
218
+ let [prevFormatOptions, setPrevFormatOptions] = useState(
219
+ formatOptions,
220
+ subSlot(slot, 'prevFormat'),
221
+ );
222
+ if (
223
+ !Object.is(numberValue, prevValue) ||
224
+ locale !== prevLocale ||
225
+ !isEqualFormatOptions(formatOptions, prevFormatOptions)
226
+ ) {
227
+ setInputValue(format(numberValue));
228
+ setPrevValue(numberValue);
229
+ setPrevLocale(locale);
230
+ setPrevFormatOptions(formatOptions);
231
+ }
232
+
233
+ let parsedValue = useMemo(
234
+ () => numberParser.parse(inputValue),
235
+ [numberParser, inputValue],
236
+ subSlot(slot, 'parsed'),
237
+ );
238
+ let commit = (overrideValue?: string) => {
239
+ let newInputValue = overrideValue === undefined ? inputValue : overrideValue;
240
+ let newParsedValue = parsedValue;
241
+ if (overrideValue !== undefined) {
242
+ newParsedValue = numberParser.parse(newInputValue);
243
+ }
244
+ // Set to empty state if input value is empty
245
+ if (!newInputValue.length) {
246
+ setNumberValue(NaN);
247
+ setInputValue(value === undefined ? '' : format(numberValue));
248
+ return;
249
+ }
250
+
251
+ // if it failed to parse, then reset input to formatted version of current number
252
+ if (isNaN(newParsedValue)) {
253
+ setInputValue(format(numberValue));
254
+ return;
255
+ }
256
+
257
+ // Clamp to min and max, round to the nearest step, and round to specified number of digits
258
+ let clampedValue = commitBehavior === 'snap' ? snapValue(newParsedValue) : newParsedValue;
259
+ clampedValue = numberParser.parse(format(clampedValue));
260
+ let shouldValidate = clampedValue !== numberValue;
261
+ setNumberValue(clampedValue);
262
+
263
+ // in a controlled state, the numberValue won't change, so we won't go back to our old input without help
264
+ setInputValue(format(value === undefined ? clampedValue : numberValue));
265
+ if (shouldValidate) {
266
+ validation.commitValidation();
267
+ }
268
+ };
269
+
270
+ let safeNextStep = (operation: '+' | '-', minMax: number = 0) => {
271
+ let prev = parsedValue;
272
+
273
+ if (isNaN(prev)) {
274
+ // if the input is empty, start from the min/max value when incrementing/decrementing,
275
+ // or zero if there is no min/max value defined.
276
+ let newValue = isNaN(minMax) ? 0 : minMax;
277
+ return snapValueToStep(newValue, minValue, maxValue, clampStep);
278
+ } else {
279
+ // otherwise, first snap the current value to the nearest step. if it moves in the direction
280
+ // we're going, use that value, otherwise add the step and snap that value.
281
+ let newValue = snapValueToStep(prev, minValue, maxValue, clampStep);
282
+ if ((operation === '+' && newValue > prev) || (operation === '-' && newValue < prev)) {
283
+ return newValue;
284
+ }
285
+
286
+ return snapValueToStep(
287
+ handleDecimalOperation(operation, prev, clampStep),
288
+ minValue,
289
+ maxValue,
290
+ clampStep,
291
+ );
292
+ }
293
+ };
294
+
295
+ let increment = () => {
296
+ let newValue = safeNextStep('+', minValue);
297
+
298
+ // if we've arrived at the same value that was previously in the state, the
299
+ // input value should be updated to match
300
+ // ex type 4, press increment, highlight the number in the input, type 4 again, press increment
301
+ // you'd be at 5, then incrementing to 5 again, so no re-render would happen and 4 would be left in the input
302
+ if (newValue === numberValue) {
303
+ setInputValue(format(newValue));
304
+ }
305
+
306
+ setNumberValue(newValue);
307
+ validation.commitValidation();
308
+ };
309
+
310
+ let decrement = () => {
311
+ let newValue = safeNextStep('-', maxValue);
312
+
313
+ if (newValue === numberValue) {
314
+ setInputValue(format(newValue));
315
+ }
316
+
317
+ setNumberValue(newValue);
318
+ validation.commitValidation();
319
+ };
320
+
321
+ let incrementToMax = () => {
322
+ if (maxValue != null) {
323
+ setNumberValue(snapValueToStep(maxValue, minValue, maxValue, clampStep));
324
+ validation.commitValidation();
325
+ }
326
+ };
327
+
328
+ let decrementToMin = () => {
329
+ if (minValue != null) {
330
+ setNumberValue(minValue);
331
+ validation.commitValidation();
332
+ }
333
+ };
334
+
335
+ let canIncrement = useMemo(
336
+ () =>
337
+ !isDisabled &&
338
+ !isReadOnly &&
339
+ (isNaN(parsedValue) ||
340
+ maxValue === undefined ||
341
+ isNaN(maxValue) ||
342
+ snapValueToStep(parsedValue, minValue, maxValue, clampStep) > parsedValue ||
343
+ handleDecimalOperation('+', parsedValue, clampStep) <= maxValue),
344
+ [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue],
345
+ subSlot(slot, 'canInc'),
346
+ );
347
+
348
+ let canDecrement = useMemo(
349
+ () =>
350
+ !isDisabled &&
351
+ !isReadOnly &&
352
+ (isNaN(parsedValue) ||
353
+ minValue === undefined ||
354
+ isNaN(minValue) ||
355
+ snapValueToStep(parsedValue, minValue, maxValue, clampStep) < parsedValue ||
356
+ handleDecimalOperation('-', parsedValue, clampStep) >= minValue),
357
+ [isDisabled, isReadOnly, minValue, maxValue, clampStep, parsedValue],
358
+ subSlot(slot, 'canDec'),
359
+ );
360
+
361
+ let validate = (value: string) => numberParser.isValidPartialNumber(value, minValue, maxValue);
362
+
363
+ return {
364
+ ...validation,
365
+ validate,
366
+ increment,
367
+ incrementToMax,
368
+ decrement,
369
+ decrementToMin,
370
+ canIncrement,
371
+ canDecrement,
372
+ minValue,
373
+ maxValue,
374
+ numberValue: parsedValue,
375
+ defaultNumberValue: isNaN(defaultValue) ? initialValue : defaultValue,
376
+ setNumberValue,
377
+ setInputValue,
378
+ inputValue,
379
+ commit,
380
+ };
381
+ }
382
+
383
+ // Shallow equality is sufficient here because all values in Intl.NumberFormatOptions are primitives.
384
+ function isEqualFormatOptions(
385
+ a: Intl.NumberFormatOptions | undefined,
386
+ b: Intl.NumberFormatOptions | undefined,
387
+ ) {
388
+ if (a === b) {
389
+ return true;
390
+ }
391
+ if (!a || !b) {
392
+ return false;
393
+ }
394
+ let aKeys = Object.keys(a);
395
+ let bKeys = Object.keys(b);
396
+ if (aKeys.length !== bKeys.length) {
397
+ return false;
398
+ }
399
+ for (let key of aKeys) {
400
+ if ((b as Record<string, any>)[key] !== (a as Record<string, any>)[key]) {
401
+ return false;
402
+ }
403
+ }
404
+ return true;
405
+ }
406
+
407
+ function handleDecimalOperation(operator: '-' | '+', value1: number, value2: number): number {
408
+ let result = operator === '+' ? value1 + value2 : value1 - value2;
409
+
410
+ // Check if we have decimals
411
+ if (value1 % 1 !== 0 || value2 % 1 !== 0) {
412
+ const value1Decimal = value1.toString().split('.');
413
+ const value2Decimal = value2.toString().split('.');
414
+ const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;
415
+ const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;
416
+ const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
417
+
418
+ // Transform the decimals to integers based on the precision
419
+ value1 = Math.round(value1 * multiplier);
420
+ value2 = Math.round(value2 * multiplier);
421
+
422
+ // Perform the operation on integers values to make sure we don't get a fancy decimal value
423
+ result = operator === '+' ? value1 + value2 : value1 - value2;
424
+
425
+ // Transform the integer result back to decimal
426
+ result /= multiplier;
427
+ }
428
+
429
+ return result;
430
+ }
@@ -0,0 +1,85 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/overlays/useOverlayTriggerState.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; the public value-level `onOpenChange` callback is unchanged (the onInput
4
+ // rule applies only to DOM wiring); explicit dependency arrays are kept verbatim.
5
+ import { useCallback } from 'octane';
6
+
7
+ import { S, splitSlot, subSlot } from '../../internal';
8
+ import { useControlledState } from '../utils/useControlledState';
9
+
10
+ export interface OverlayTriggerProps {
11
+ /** Whether the overlay is open by default (controlled). */
12
+ isOpen?: boolean;
13
+ /** Whether the overlay is open by default (uncontrolled). */
14
+ defaultOpen?: boolean;
15
+ /** Handler that is called when the overlay's open state changes. */
16
+ onOpenChange?: (isOpen: boolean) => void;
17
+ }
18
+
19
+ export interface OverlayTriggerState {
20
+ /** Whether the overlay is currently open. */
21
+ readonly isOpen: boolean;
22
+ /** Sets whether the overlay is open. */
23
+ setOpen(isOpen: boolean): void;
24
+ /** Opens the overlay. */
25
+ open(): void;
26
+ /** Closes the overlay. */
27
+ close(): void;
28
+ /** Toggles the overlay's visibility. */
29
+ toggle(): void;
30
+ }
31
+
32
+ /**
33
+ * Manages state for an overlay trigger. Tracks whether the overlay is open, and provides
34
+ * methods to toggle this state.
35
+ */
36
+ export function useOverlayTriggerState(props: OverlayTriggerProps): OverlayTriggerState;
37
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
38
+ export function useOverlayTriggerState(
39
+ props: OverlayTriggerProps,
40
+ slot: symbol | undefined,
41
+ ): OverlayTriggerState;
42
+ export function useOverlayTriggerState(...args: any[]): OverlayTriggerState {
43
+ const [user, slotArg] = splitSlot(args);
44
+ const slot = slotArg ?? S('useOverlayTriggerState');
45
+ const props = user[0] as OverlayTriggerProps;
46
+
47
+ let [isOpen, setOpen] = useControlledState(
48
+ props.isOpen,
49
+ props.defaultOpen || false,
50
+ props.onOpenChange,
51
+ subSlot(slot, 'open'),
52
+ );
53
+
54
+ const open = useCallback(
55
+ () => {
56
+ setOpen(true);
57
+ },
58
+ [setOpen],
59
+ subSlot(slot, 'openCb'),
60
+ );
61
+
62
+ const close = useCallback(
63
+ () => {
64
+ setOpen(false);
65
+ },
66
+ [setOpen],
67
+ subSlot(slot, 'closeCb'),
68
+ );
69
+
70
+ const toggle = useCallback(
71
+ () => {
72
+ setOpen(!isOpen);
73
+ },
74
+ [setOpen, isOpen],
75
+ subSlot(slot, 'toggleCb'),
76
+ );
77
+
78
+ return {
79
+ isOpen,
80
+ setOpen,
81
+ open,
82
+ close,
83
+ toggle,
84
+ };
85
+ }
@@ -0,0 +1,150 @@
1
+ // Ported from react-stately (source: .react-spectrum/packages/react-stately/src/radio/useRadioGroupState.ts).
2
+ // octane adaptations: public-hook slot threading (splitSlot/subSlot) per the binding
3
+ // convention; the module-level instance/name counters port verbatim. The public
4
+ // value-level `onChange` callback is unchanged (the onInput rule applies only to DOM wiring).
5
+ import type {
6
+ FocusEvents,
7
+ HelpTextProps,
8
+ InputBase,
9
+ InputDOMProps,
10
+ LabelableProps,
11
+ Orientation,
12
+ Validation,
13
+ ValidationState,
14
+ ValueBase,
15
+ } from '@react-types/shared';
16
+ import { useMemo, useState } from 'octane';
17
+
18
+ import { S, splitSlot, subSlot } from '../../internal';
19
+ import { FormValidationState, useFormValidationState } from '../form/useFormValidationState';
20
+ import { useControlledState } from '../utils/useControlledState';
21
+
22
+ export interface RadioGroupProps
23
+ extends
24
+ ValueBase<string | null, string>,
25
+ InputBase,
26
+ Pick<InputDOMProps, 'name'>,
27
+ Validation<string>,
28
+ LabelableProps,
29
+ HelpTextProps,
30
+ FocusEvents {
31
+ /**
32
+ * The axis the Radio Button(s) should align with.
33
+ *
34
+ * @default 'vertical'
35
+ */
36
+ orientation?: Orientation;
37
+ }
38
+
39
+ export interface RadioGroupState extends FormValidationState {
40
+ /**
41
+ * The name for the group, used for native form submission.
42
+ *
43
+ * @private
44
+ * @deprecated
45
+ */
46
+ readonly name: string;
47
+
48
+ /** Whether the radio group is disabled. */
49
+ readonly isDisabled: boolean;
50
+
51
+ /** Whether the radio group is read only. */
52
+ readonly isReadOnly: boolean;
53
+
54
+ /** Whether the radio group is required. */
55
+ readonly isRequired: boolean;
56
+
57
+ /**
58
+ * Whether the radio group is valid or invalid.
59
+ *
60
+ * @deprecated Use `isInvalid` instead.
61
+ */
62
+ readonly validationState: ValidationState | null;
63
+
64
+ /** Whether the radio group is invalid. */
65
+ readonly isInvalid: boolean;
66
+
67
+ /** The currently selected value. */
68
+ readonly selectedValue: string | null;
69
+
70
+ /** The default selected value. */
71
+ readonly defaultSelectedValue: string | null;
72
+
73
+ /** Sets the selected value. */
74
+ setSelectedValue(value: string | null): void;
75
+
76
+ /** The value of the last focused radio. */
77
+ readonly lastFocusedValue: string | null;
78
+
79
+ /** Sets the last focused value. */
80
+ setLastFocusedValue(value: string | null): void;
81
+ }
82
+
83
+ let instance = Math.round(Math.random() * 10000000000);
84
+ let i = 0;
85
+
86
+ /**
87
+ * Provides state management for a radio group component. Provides a name for the group,
88
+ * and manages selection and focus state.
89
+ */
90
+ export function useRadioGroupState(props: RadioGroupProps): RadioGroupState;
91
+ // Slot-threading form: sibling ported hooks pass their derived sub-slot as the trailing arg.
92
+ export function useRadioGroupState(
93
+ props: RadioGroupProps,
94
+ slot: symbol | undefined,
95
+ ): RadioGroupState;
96
+ export function useRadioGroupState(...args: any[]): RadioGroupState {
97
+ const [user, slotArg] = splitSlot(args);
98
+ const slot = slotArg ?? S('useRadioGroupState');
99
+ const props = user[0] as RadioGroupProps;
100
+
101
+ // Preserved here for backward compatibility. React Aria now generates the name instead of stately.
102
+ let name = useMemo(
103
+ () => props.name || `radio-group-${instance}-${++i}`,
104
+ [props.name],
105
+ subSlot(slot, 'name'),
106
+ );
107
+ let [selectedValue, setSelected] = useControlledState(
108
+ props.value,
109
+ props.defaultValue ?? null,
110
+ props.onChange,
111
+ subSlot(slot, 'selected'),
112
+ );
113
+ let [initialValue] = useState(selectedValue, subSlot(slot, 'initial'));
114
+ let [lastFocusedValue, setLastFocusedValue] = useState<string | null>(
115
+ null,
116
+ subSlot(slot, 'lastFocused'),
117
+ );
118
+
119
+ let validation = useFormValidationState(
120
+ {
121
+ ...props,
122
+ value: selectedValue,
123
+ },
124
+ subSlot(slot, 'validation'),
125
+ );
126
+
127
+ let setSelectedValue = (value: string | null) => {
128
+ if (!props.isReadOnly && !props.isDisabled) {
129
+ setSelected(value);
130
+ validation.commitValidation();
131
+ }
132
+ };
133
+
134
+ let isInvalid = validation.displayValidation.isInvalid;
135
+
136
+ return {
137
+ ...validation,
138
+ name,
139
+ selectedValue: selectedValue,
140
+ defaultSelectedValue: props.value !== undefined ? initialValue : (props.defaultValue ?? null),
141
+ setSelectedValue,
142
+ lastFocusedValue,
143
+ setLastFocusedValue,
144
+ isDisabled: props.isDisabled || false,
145
+ isReadOnly: props.isReadOnly || false,
146
+ isRequired: props.isRequired || false,
147
+ validationState: props.validationState || (isInvalid ? 'invalid' : null),
148
+ isInvalid,
149
+ };
150
+ }