@funstack/ui 0.1.0-alpha.2 → 0.1.0-alpha.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 (403) hide show
  1. package/dist/accordion/accordion-context.mjs.map +1 -1
  2. package/dist/accordion/accordion-item.mjs +18 -4
  3. package/dist/accordion/accordion-item.mjs.map +1 -1
  4. package/dist/accordion/accordion-panel.mjs +2 -3
  5. package/dist/accordion/accordion-panel.mjs.map +1 -1
  6. package/dist/accordion/accordion-root.d.mts.map +1 -1
  7. package/dist/accordion/accordion-root.mjs +34 -15
  8. package/dist/accordion/accordion-root.mjs.map +1 -1
  9. package/dist/accordion/accordion-trigger.mjs +4 -5
  10. package/dist/accordion/accordion-trigger.mjs.map +1 -1
  11. package/dist/checkbox/checkbox.d.mts +5 -3
  12. package/dist/checkbox/checkbox.d.mts.map +1 -1
  13. package/dist/checkbox/checkbox.mjs +25 -9
  14. package/dist/checkbox/checkbox.mjs.map +1 -1
  15. package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -1
  16. package/dist/checkbox-group/checkbox-group-item.d.mts +2 -1
  17. package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -1
  18. package/dist/checkbox-group/checkbox-group-item.mjs +3 -1
  19. package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -1
  20. package/dist/checkbox-group/checkbox-group-root.d.mts +5 -2
  21. package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -1
  22. package/dist/checkbox-group/checkbox-group-root.mjs +24 -5
  23. package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -1
  24. package/dist/combobox/combobox-clear.mjs +2 -1
  25. package/dist/combobox/combobox-clear.mjs.map +1 -1
  26. package/dist/combobox/combobox-context.mjs.map +1 -1
  27. package/dist/combobox/combobox-input.d.mts +3 -1
  28. package/dist/combobox/combobox-input.d.mts.map +1 -1
  29. package/dist/combobox/combobox-input.mjs +16 -2
  30. package/dist/combobox/combobox-input.mjs.map +1 -1
  31. package/dist/combobox/combobox-list.mjs +3 -2
  32. package/dist/combobox/combobox-list.mjs.map +1 -1
  33. package/dist/combobox/combobox-popup.d.mts.map +1 -1
  34. package/dist/combobox/combobox-popup.mjs +7 -2
  35. package/dist/combobox/combobox-popup.mjs.map +1 -1
  36. package/dist/combobox/combobox-root.d.mts.map +1 -1
  37. package/dist/combobox/combobox-root.mjs +20 -5
  38. package/dist/combobox/combobox-root.mjs.map +1 -1
  39. package/dist/combobox/combobox-trigger.mjs +2 -1
  40. package/dist/combobox/combobox-trigger.mjs.map +1 -1
  41. package/dist/dialog/dialog-close.d.mts +17 -10
  42. package/dist/dialog/dialog-close.d.mts.map +1 -1
  43. package/dist/dialog/dialog-close.mjs +33 -21
  44. package/dist/dialog/dialog-close.mjs.map +1 -1
  45. package/dist/dialog/dialog-context.mjs.map +1 -1
  46. package/dist/dialog/dialog-form.d.mts +23 -10
  47. package/dist/dialog/dialog-form.d.mts.map +1 -1
  48. package/dist/dialog/dialog-form.mjs +51 -32
  49. package/dist/dialog/dialog-form.mjs.map +1 -1
  50. package/dist/dialog/dialog-popup.d.mts +10 -4
  51. package/dist/dialog/dialog-popup.d.mts.map +1 -1
  52. package/dist/dialog/dialog-popup.mjs +117 -44
  53. package/dist/dialog/dialog-popup.mjs.map +1 -1
  54. package/dist/dialog/dialog-root.d.mts +14 -8
  55. package/dist/dialog/dialog-root.d.mts.map +1 -1
  56. package/dist/dialog/dialog-root.mjs +67 -12
  57. package/dist/dialog/dialog-root.mjs.map +1 -1
  58. package/dist/dialog/dialog-trigger.d.mts +3 -2
  59. package/dist/dialog/dialog-trigger.d.mts.map +1 -1
  60. package/dist/dialog/dialog-trigger.mjs +2 -1
  61. package/dist/dialog/dialog-trigger.mjs.map +1 -1
  62. package/dist/dialog/index.d.mts +4 -2
  63. package/dist/dialog/index.d.mts.map +1 -1
  64. package/dist/dialog/index.mjs +4 -2
  65. package/dist/dialog/index.mjs.map +1 -1
  66. package/dist/field/field-control.d.mts +33 -0
  67. package/dist/field/field-control.d.mts.map +1 -0
  68. package/dist/field/field-control.mjs +68 -0
  69. package/dist/field/field-control.mjs.map +1 -0
  70. package/dist/field/field-description.d.mts +24 -0
  71. package/dist/field/field-description.d.mts.map +1 -0
  72. package/dist/field/field-description.mjs +34 -0
  73. package/dist/field/field-description.mjs.map +1 -0
  74. package/dist/field/field-error.d.mts +30 -0
  75. package/dist/field/field-error.d.mts.map +1 -0
  76. package/dist/field/field-error.mjs +42 -0
  77. package/dist/field/field-error.mjs.map +1 -0
  78. package/dist/field/field-label.d.mts +25 -0
  79. package/dist/field/field-label.d.mts.map +1 -0
  80. package/dist/field/field-label.mjs +46 -0
  81. package/dist/field/field-label.mjs.map +1 -0
  82. package/dist/field/field-root.d.mts +53 -0
  83. package/dist/field/field-root.d.mts.map +1 -0
  84. package/dist/field/field-root.mjs +319 -0
  85. package/dist/field/field-root.mjs.map +1 -0
  86. package/dist/field/index.d.mts +18 -0
  87. package/dist/field/index.d.mts.map +1 -0
  88. package/dist/field/index.mjs +17 -0
  89. package/dist/field/index.mjs.map +1 -0
  90. package/dist/form/form-root.d.mts +58 -0
  91. package/dist/form/form-root.d.mts.map +1 -0
  92. package/dist/form/form-root.mjs +147 -0
  93. package/dist/form/form-root.mjs.map +1 -0
  94. package/dist/form/form-submit.d.mts +31 -0
  95. package/dist/form/form-submit.d.mts.map +1 -0
  96. package/dist/form/form-submit.mjs +53 -0
  97. package/dist/form/form-submit.mjs.map +1 -0
  98. package/dist/form/index.d.mts +11 -0
  99. package/dist/form/index.d.mts.map +1 -0
  100. package/dist/form/index.mjs +11 -0
  101. package/dist/form/index.mjs.map +1 -0
  102. package/dist/index.d.mts +53 -1
  103. package/dist/index.mjs +11 -1
  104. package/dist/internal/announce.mjs +53 -0
  105. package/dist/internal/announce.mjs.map +1 -0
  106. package/dist/internal/content-focus-probe.mjs +42 -0
  107. package/dist/internal/content-focus-probe.mjs.map +1 -0
  108. package/dist/internal/decimal.mjs +27 -0
  109. package/dist/internal/decimal.mjs.map +1 -0
  110. package/dist/internal/dev-warn.mjs +17 -0
  111. package/dist/internal/dev-warn.mjs.map +1 -0
  112. package/dist/internal/field-context.d.mts +19 -0
  113. package/dist/internal/field-context.d.mts.map +1 -0
  114. package/dist/internal/field-context.mjs +14 -0
  115. package/dist/internal/field-context.mjs.map +1 -0
  116. package/dist/internal/focus-first-invalid.mjs +67 -0
  117. package/dist/internal/focus-first-invalid.mjs.map +1 -0
  118. package/dist/internal/form-status-watcher.mjs +31 -0
  119. package/dist/internal/form-status-watcher.mjs.map +1 -0
  120. package/dist/internal/modal-registry.mjs +39 -0
  121. package/dist/internal/modal-registry.mjs.map +1 -0
  122. package/dist/internal/range-value.mjs +51 -0
  123. package/dist/internal/range-value.mjs.map +1 -0
  124. package/dist/internal/render-element.mjs +54 -0
  125. package/dist/internal/render-element.mjs.map +1 -0
  126. package/dist/internal/toolbar-context.mjs +17 -0
  127. package/dist/internal/toolbar-context.mjs.map +1 -0
  128. package/dist/internal/types.d.mts +3 -1
  129. package/dist/internal/types.d.mts.map +1 -1
  130. package/dist/internal/use-controllable-action.mjs +33 -15
  131. package/dist/internal/use-controllable-action.mjs.map +1 -1
  132. package/dist/internal/use-exit-animation.mjs +26 -6
  133. package/dist/internal/use-exit-animation.mjs.map +1 -1
  134. package/dist/internal/use-field-control.mjs +109 -0
  135. package/dist/internal/use-field-control.mjs.map +1 -0
  136. package/dist/internal/use-form-owner-event.mjs +44 -0
  137. package/dist/internal/use-form-owner-event.mjs.map +1 -0
  138. package/dist/internal/use-form-reset.mjs +10 -33
  139. package/dist/internal/use-form-reset.mjs.map +1 -1
  140. package/dist/internal/use-latest.mjs +32 -0
  141. package/dist/internal/use-latest.mjs.map +1 -0
  142. package/dist/internal/use-modal-registration.mjs +47 -0
  143. package/dist/internal/use-modal-registration.mjs.map +1 -0
  144. package/dist/internal/use-native-group-reconciliation.mjs +6 -5
  145. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  146. package/dist/internal/use-native-select-value.mjs +7 -5
  147. package/dist/internal/use-native-select-value.mjs.map +1 -1
  148. package/dist/internal/use-popover-popup.mjs +11 -24
  149. package/dist/internal/use-popover-popup.mjs.map +1 -1
  150. package/dist/internal/use-popover-root.mjs +58 -23
  151. package/dist/internal/use-popover-root.mjs.map +1 -1
  152. package/dist/internal/use-popover-trigger.mjs +1 -1
  153. package/dist/internal/use-render.mjs +11 -34
  154. package/dist/internal/use-render.mjs.map +1 -1
  155. package/dist/internal/use-roving-focus.mjs +255 -0
  156. package/dist/internal/use-roving-focus.mjs.map +1 -0
  157. package/dist/internal/validity.d.mts +24 -0
  158. package/dist/internal/validity.d.mts.map +1 -0
  159. package/dist/internal/validity.mjs +108 -0
  160. package/dist/internal/validity.mjs.map +1 -0
  161. package/dist/menu/menu-checkbox-item.mjs +2 -1
  162. package/dist/menu/menu-checkbox-item.mjs.map +1 -1
  163. package/dist/menu/menu-group.d.mts.map +1 -1
  164. package/dist/menu/menu-group.mjs +3 -2
  165. package/dist/menu/menu-group.mjs.map +1 -1
  166. package/dist/menu/menu-item.mjs +2 -1
  167. package/dist/menu/menu-item.mjs.map +1 -1
  168. package/dist/menu/menu-popup.d.mts.map +1 -1
  169. package/dist/menu/menu-popup.mjs +7 -2
  170. package/dist/menu/menu-popup.mjs.map +1 -1
  171. package/dist/menu/menu-radio-group.mjs +9 -4
  172. package/dist/menu/menu-radio-group.mjs.map +1 -1
  173. package/dist/menu/menu-radio-item.mjs +2 -1
  174. package/dist/menu/menu-radio-item.mjs.map +1 -1
  175. package/dist/menu/menu-root.mjs +1 -1
  176. package/dist/menu/menu-root.mjs.map +1 -1
  177. package/dist/menu/menu-trigger.d.mts +2 -1
  178. package/dist/menu/menu-trigger.d.mts.map +1 -1
  179. package/dist/menu/menu-trigger.mjs +15 -4
  180. package/dist/menu/menu-trigger.mjs.map +1 -1
  181. package/dist/meter/index.d.mts +24 -0
  182. package/dist/meter/index.d.mts.map +1 -0
  183. package/dist/meter/index.mjs +23 -0
  184. package/dist/meter/index.mjs.map +1 -0
  185. package/dist/meter/meter-context.mjs +13 -0
  186. package/dist/meter/meter-context.mjs.map +1 -0
  187. package/dist/meter/meter-indicator.d.mts +19 -0
  188. package/dist/meter/meter-indicator.d.mts.map +1 -0
  189. package/dist/meter/meter-indicator.mjs +25 -0
  190. package/dist/meter/meter-indicator.mjs.map +1 -0
  191. package/dist/meter/meter-label.d.mts +19 -0
  192. package/dist/meter/meter-label.d.mts.map +1 -0
  193. package/dist/meter/meter-label.mjs +28 -0
  194. package/dist/meter/meter-label.mjs.map +1 -0
  195. package/dist/meter/meter-region.d.mts +4 -0
  196. package/dist/meter/meter-region.d.mts.map +1 -0
  197. package/dist/meter/meter-region.mjs +39 -0
  198. package/dist/meter/meter-region.mjs.map +1 -0
  199. package/dist/meter/meter-root.d.mts +71 -0
  200. package/dist/meter/meter-root.d.mts.map +1 -0
  201. package/dist/meter/meter-root.mjs +83 -0
  202. package/dist/meter/meter-root.mjs.map +1 -0
  203. package/dist/meter/meter-track.d.mts +19 -0
  204. package/dist/meter/meter-track.d.mts.map +1 -0
  205. package/dist/meter/meter-track.mjs +25 -0
  206. package/dist/meter/meter-track.mjs.map +1 -0
  207. package/dist/meter/meter-value.d.mts +20 -0
  208. package/dist/meter/meter-value.d.mts.map +1 -0
  209. package/dist/meter/meter-value.mjs +29 -0
  210. package/dist/meter/meter-value.mjs.map +1 -0
  211. package/dist/number-field/index.d.mts +26 -0
  212. package/dist/number-field/index.d.mts.map +1 -0
  213. package/dist/number-field/index.mjs +26 -0
  214. package/dist/number-field/index.mjs.map +1 -0
  215. package/dist/number-field/number-field-arithmetic.mjs +78 -0
  216. package/dist/number-field/number-field-arithmetic.mjs.map +1 -0
  217. package/dist/number-field/number-field-context.d.mts +2 -0
  218. package/dist/number-field/number-field-context.mjs +13 -0
  219. package/dist/number-field/number-field-context.mjs.map +1 -0
  220. package/dist/number-field/number-field-decrement.d.mts +16 -0
  221. package/dist/number-field/number-field-decrement.d.mts.map +1 -0
  222. package/dist/number-field/number-field-decrement.mjs +19 -0
  223. package/dist/number-field/number-field-decrement.mjs.map +1 -0
  224. package/dist/number-field/number-field-format.mjs +279 -0
  225. package/dist/number-field/number-field-format.mjs.map +1 -0
  226. package/dist/number-field/number-field-increment.d.mts +32 -0
  227. package/dist/number-field/number-field-increment.d.mts.map +1 -0
  228. package/dist/number-field/number-field-increment.mjs +68 -0
  229. package/dist/number-field/number-field-increment.mjs.map +1 -0
  230. package/dist/number-field/number-field-input.d.mts +29 -0
  231. package/dist/number-field/number-field-input.d.mts.map +1 -0
  232. package/dist/number-field/number-field-input.mjs +163 -0
  233. package/dist/number-field/number-field-input.mjs.map +1 -0
  234. package/dist/number-field/number-field-label.d.mts +23 -0
  235. package/dist/number-field/number-field-label.d.mts.map +1 -0
  236. package/dist/number-field/number-field-label.mjs +47 -0
  237. package/dist/number-field/number-field-label.mjs.map +1 -0
  238. package/dist/number-field/number-field-root.d.mts +108 -0
  239. package/dist/number-field/number-field-root.d.mts.map +1 -0
  240. package/dist/number-field/number-field-root.mjs +523 -0
  241. package/dist/number-field/number-field-root.mjs.map +1 -0
  242. package/dist/number-field/use-step-button.mjs +107 -0
  243. package/dist/number-field/use-step-button.mjs.map +1 -0
  244. package/dist/popover/popover-close.mjs +2 -1
  245. package/dist/popover/popover-close.mjs.map +1 -1
  246. package/dist/popover/popover-popup.d.mts.map +1 -1
  247. package/dist/popover/popover-popup.mjs +7 -2
  248. package/dist/popover/popover-popup.mjs.map +1 -1
  249. package/dist/popover/popover-root.mjs +1 -1
  250. package/dist/progress/index.d.mts +24 -0
  251. package/dist/progress/index.d.mts.map +1 -0
  252. package/dist/progress/index.mjs +24 -0
  253. package/dist/progress/index.mjs.map +1 -0
  254. package/dist/progress/progress-context.mjs +13 -0
  255. package/dist/progress/progress-context.mjs.map +1 -0
  256. package/dist/progress/progress-indicator.d.mts +19 -0
  257. package/dist/progress/progress-indicator.d.mts.map +1 -0
  258. package/dist/progress/progress-indicator.mjs +29 -0
  259. package/dist/progress/progress-indicator.mjs.map +1 -0
  260. package/dist/progress/progress-label.d.mts +19 -0
  261. package/dist/progress/progress-label.d.mts.map +1 -0
  262. package/dist/progress/progress-label.mjs +30 -0
  263. package/dist/progress/progress-label.mjs.map +1 -0
  264. package/dist/progress/progress-root.d.mts +68 -0
  265. package/dist/progress/progress-root.d.mts.map +1 -0
  266. package/dist/progress/progress-root.mjs +80 -0
  267. package/dist/progress/progress-root.mjs.map +1 -0
  268. package/dist/progress/progress-track.d.mts +19 -0
  269. package/dist/progress/progress-track.d.mts.map +1 -0
  270. package/dist/progress/progress-track.mjs +29 -0
  271. package/dist/progress/progress-track.mjs.map +1 -0
  272. package/dist/progress/progress-value.d.mts +20 -0
  273. package/dist/progress/progress-value.d.mts.map +1 -0
  274. package/dist/progress/progress-value.mjs +33 -0
  275. package/dist/progress/progress-value.mjs.map +1 -0
  276. package/dist/radio-group/radio-group-root.d.mts +4 -2
  277. package/dist/radio-group/radio-group-root.d.mts.map +1 -1
  278. package/dist/radio-group/radio-group-root.mjs +34 -8
  279. package/dist/radio-group/radio-group-root.mjs.map +1 -1
  280. package/dist/select/select-group.d.mts.map +1 -1
  281. package/dist/select/select-group.mjs +6 -4
  282. package/dist/select/select-group.mjs.map +1 -1
  283. package/dist/select/select-root.d.mts +4 -2
  284. package/dist/select/select-root.d.mts.map +1 -1
  285. package/dist/select/select-root.mjs +26 -6
  286. package/dist/select/select-root.mjs.map +1 -1
  287. package/dist/slider/index.d.mts +32 -0
  288. package/dist/slider/index.d.mts.map +1 -0
  289. package/dist/slider/index.mjs +27 -0
  290. package/dist/slider/index.mjs.map +1 -0
  291. package/dist/slider/slider-arithmetic.mjs +104 -0
  292. package/dist/slider/slider-arithmetic.mjs.map +1 -0
  293. package/dist/slider/slider-context.mjs +13 -0
  294. package/dist/slider/slider-context.mjs.map +1 -0
  295. package/dist/slider/slider-indicator.d.mts +22 -0
  296. package/dist/slider/slider-indicator.d.mts.map +1 -0
  297. package/dist/slider/slider-indicator.mjs +36 -0
  298. package/dist/slider/slider-indicator.mjs.map +1 -0
  299. package/dist/slider/slider-label.d.mts +23 -0
  300. package/dist/slider/slider-label.d.mts.map +1 -0
  301. package/dist/slider/slider-label.mjs +44 -0
  302. package/dist/slider/slider-label.mjs.map +1 -0
  303. package/dist/slider/slider-root.d.mts +111 -0
  304. package/dist/slider/slider-root.d.mts.map +1 -0
  305. package/dist/slider/slider-root.mjs +583 -0
  306. package/dist/slider/slider-root.mjs.map +1 -0
  307. package/dist/slider/slider-thumb.d.mts +58 -0
  308. package/dist/slider/slider-thumb.d.mts.map +1 -0
  309. package/dist/slider/slider-thumb.mjs +146 -0
  310. package/dist/slider/slider-thumb.mjs.map +1 -0
  311. package/dist/slider/slider-track.d.mts +29 -0
  312. package/dist/slider/slider-track.d.mts.map +1 -0
  313. package/dist/slider/slider-track.mjs +55 -0
  314. package/dist/slider/slider-track.mjs.map +1 -0
  315. package/dist/slider/slider-value.d.mts +34 -0
  316. package/dist/slider/slider-value.d.mts.map +1 -0
  317. package/dist/slider/slider-value.mjs +38 -0
  318. package/dist/slider/slider-value.mjs.map +1 -0
  319. package/dist/switch/switch.d.mts +5 -3
  320. package/dist/switch/switch.d.mts.map +1 -1
  321. package/dist/switch/switch.mjs +24 -8
  322. package/dist/switch/switch.mjs.map +1 -1
  323. package/dist/tabs/tabs-indicator.mjs +2 -1
  324. package/dist/tabs/tabs-indicator.mjs.map +1 -1
  325. package/dist/tabs/tabs-root.mjs +13 -3
  326. package/dist/tabs/tabs-root.mjs.map +1 -1
  327. package/dist/tabs/tabs-tab.mjs +2 -1
  328. package/dist/tabs/tabs-tab.mjs.map +1 -1
  329. package/dist/toast/index.d.mts +25 -0
  330. package/dist/toast/index.d.mts.map +1 -0
  331. package/dist/toast/index.mjs +26 -0
  332. package/dist/toast/index.mjs.map +1 -0
  333. package/dist/toast/toast-action.d.mts +39 -0
  334. package/dist/toast/toast-action.d.mts.map +1 -0
  335. package/dist/toast/toast-action.mjs +65 -0
  336. package/dist/toast/toast-action.mjs.map +1 -0
  337. package/dist/toast/toast-close.d.mts +25 -0
  338. package/dist/toast/toast-close.d.mts.map +1 -0
  339. package/dist/toast/toast-close.mjs +47 -0
  340. package/dist/toast/toast-close.mjs.map +1 -0
  341. package/dist/toast/toast-context.mjs +19 -0
  342. package/dist/toast/toast-context.mjs.map +1 -0
  343. package/dist/toast/toast-description.d.mts +24 -0
  344. package/dist/toast/toast-description.d.mts.map +1 -0
  345. package/dist/toast/toast-description.mjs +35 -0
  346. package/dist/toast/toast-description.mjs.map +1 -0
  347. package/dist/toast/toast-root.d.mts +43 -0
  348. package/dist/toast/toast-root.d.mts.map +1 -0
  349. package/dist/toast/toast-root.mjs +205 -0
  350. package/dist/toast/toast-root.mjs.map +1 -0
  351. package/dist/toast/toast-title.d.mts +24 -0
  352. package/dist/toast/toast-title.d.mts.map +1 -0
  353. package/dist/toast/toast-title.mjs +33 -0
  354. package/dist/toast/toast-title.mjs.map +1 -0
  355. package/dist/toast/toast-viewport.d.mts +52 -0
  356. package/dist/toast/toast-viewport.d.mts.map +1 -0
  357. package/dist/toast/toast-viewport.mjs +644 -0
  358. package/dist/toast/toast-viewport.mjs.map +1 -0
  359. package/dist/toast/toast.d.mts +119 -0
  360. package/dist/toast/toast.d.mts.map +1 -0
  361. package/dist/toast/toast.mjs +157 -0
  362. package/dist/toast/toast.mjs.map +1 -0
  363. package/dist/toggle/toggle.mjs +2 -1
  364. package/dist/toggle/toggle.mjs.map +1 -1
  365. package/dist/toggle-group/index.d.mts +16 -0
  366. package/dist/toggle-group/index.d.mts.map +1 -0
  367. package/dist/toggle-group/index.mjs +15 -0
  368. package/dist/toggle-group/index.mjs.map +1 -0
  369. package/dist/toggle-group/toggle-group-context.d.mts +4 -0
  370. package/dist/toggle-group/toggle-group-context.d.mts.map +1 -0
  371. package/dist/toggle-group/toggle-group-context.mjs +13 -0
  372. package/dist/toggle-group/toggle-group-context.mjs.map +1 -0
  373. package/dist/toggle-group/toggle-group-item.d.mts +47 -0
  374. package/dist/toggle-group/toggle-group-item.d.mts.map +1 -0
  375. package/dist/toggle-group/toggle-group-item.mjs +63 -0
  376. package/dist/toggle-group/toggle-group-item.mjs.map +1 -0
  377. package/dist/toggle-group/toggle-group-root.d.mts +95 -0
  378. package/dist/toggle-group/toggle-group-root.d.mts.map +1 -0
  379. package/dist/toggle-group/toggle-group-root.mjs +211 -0
  380. package/dist/toggle-group/toggle-group-root.mjs.map +1 -0
  381. package/dist/toolbar/index.d.mts +18 -0
  382. package/dist/toolbar/index.d.mts.map +1 -0
  383. package/dist/toolbar/index.mjs +18 -0
  384. package/dist/toolbar/index.mjs.map +1 -0
  385. package/dist/toolbar/toolbar-button.d.mts +42 -0
  386. package/dist/toolbar/toolbar-button.d.mts.map +1 -0
  387. package/dist/toolbar/toolbar-button.mjs +50 -0
  388. package/dist/toolbar/toolbar-button.mjs.map +1 -0
  389. package/dist/toolbar/toolbar-root.d.mts +38 -0
  390. package/dist/toolbar/toolbar-root.d.mts.map +1 -0
  391. package/dist/toolbar/toolbar-root.mjs +66 -0
  392. package/dist/toolbar/toolbar-root.mjs.map +1 -0
  393. package/dist/toolbar/toolbar-separator.d.mts +25 -0
  394. package/dist/toolbar/toolbar-separator.d.mts.map +1 -0
  395. package/dist/toolbar/toolbar-separator.mjs +31 -0
  396. package/dist/toolbar/toolbar-separator.mjs.map +1 -0
  397. package/dist/tooltip/tooltip-popup.mjs +2 -1
  398. package/dist/tooltip/tooltip-popup.mjs.map +1 -1
  399. package/dist/tooltip/tooltip-root.mjs +16 -2
  400. package/dist/tooltip/tooltip-root.mjs.map +1 -1
  401. package/dist/tooltip/tooltip-trigger.mjs +2 -1
  402. package/dist/tooltip/tooltip-trigger.mjs.map +1 -1
  403. package/package.json +10 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-root.mjs","names":[],"sources":["../../src/progress/progress-root.tsx"],"sourcesContent":["// No \"use client\": `Progress.Root` uses only `useId`, arithmetic and `Intl`, and renders the\n// client context's provider (conventions 7.1's second exception). Rendered by a Server Component\n// it runs once, on the server (design/components/progress.md 8.1). It must not import from any\n// \"use client\" module except its context (checked by src/__tests__/directives.test.ts).\nimport { useId } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { warnOnce } from \"../internal/dev-warn.js\";\nimport { clamp, formatRangeValue, isDegenerate, percentage } from \"../internal/range-value.js\";\nimport { mergeRenderRef, renderElement, resolveStateValue } from \"../internal/render-element.js\";\nimport type { DataAttributes } from \"../internal/render-element.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { ProgressContext } from \"./progress-context.js\";\n\n/** The state every Progress part receives. */\nexport interface ProgressState {\n /** The value clamped to `[min, max]`, or `null` while indeterminate. */\n readonly value: number | null;\n readonly min: number;\n readonly max: number;\n /** `(value - min) / (max - min) * 100`, a number 0–100; `null` while indeterminate. */\n readonly percentage: number | null;\n /**\n * The `Intl.NumberFormat` text of the value (or of the fraction, for the percent style): what\n * `Progress.Value` shows. `null` while indeterminate.\n */\n readonly formattedValue: string | null;\n /** What `aria-valuetext` carries: `getAriaValueText`'s result, else `formattedValue`. */\n readonly valueText: string | null;\n /** `value` is `null`. */\n readonly indeterminate: boolean;\n /** The clamped value has reached `max`. */\n readonly complete: boolean;\n}\n\nexport interface ProgressRootProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n | \"role\"\n | \"aria-valuemin\"\n | \"aria-valuemax\"\n | \"aria-valuenow\"\n | \"aria-valuetext\"\n | \"defaultValue\"\n | \"defaultChecked\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** The current value. Absent or `null`: indeterminate. Clamped to `[min, max]`. */\n value?: number | null;\n /** @default 0 */\n min?: number;\n /** @default 100 */\n max?: number;\n /**\n * `Intl.NumberFormat` options for `aria-valuetext` and `Progress.Value`. Default\n * `{ style: \"percent\" }`. A `percent` style formats the fraction of the range; any other style\n * formats the value. Serialisable: a Server Component may pass it.\n */\n format?: Intl.NumberFormatOptions;\n /**\n * BCP 47 tag for `Intl.NumberFormat`; default: the runtime's locale. Pass it when a client\n * tree is server-rendered.\n */\n locale?: string;\n /**\n * The `aria-valuetext` to render instead of `formattedValue`. Called with the clamped value\n * (`null` while indeterminate) and the state as it would be without this prop. Return `null`\n * to render no `aria-valuetext`. A function: from a Server Component it works when this Root\n * is rendered by that Server Component (the Root runs on the server), not when the Root is\n * rendered by a client component.\n */\n getAriaValueText?: (value: number | null, state: ProgressState) => string | null | undefined;\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ProgressState>;\n}\n\n/**\n * `Progress.Root`: a `div[role=progressbar]` with the ARIA values, `aria-valuetext` from\n * `Intl.NumberFormat`, `data-indeterminate` / `data-complete`, and `--progress-value` (the\n * percentage, absent while indeterminate) in `style`, where the consumer's entries win. Owned\n * keys: `role`, `aria-valuemin`, `aria-valuemax`, `aria-valuenow`, `aria-valuetext`,\n * `aria-labelledby` (token-merged: the consumer's tokens, then `Progress.Label`'s id, always),\n * `data-indeterminate`, `data-complete`.\n */\nexport function ProgressRoot({\n value = null,\n min = 0,\n max = 100,\n format,\n locale,\n getAriaValueText,\n className,\n style,\n children,\n render,\n ref,\n ...rest\n}: ProgressRootProps) {\n const id = useId();\n\n let given = value;\n if (given !== null && !Number.isFinite(given)) {\n warnOnce(\n `Progress.Root:non-finite:${given}`,\n `Progress.Root: \\`value\\` is ${given}, which is not a finite number; the bar is rendered ` +\n \"as indeterminate. Pass `null` for an unknown value.\",\n );\n given = null;\n }\n const degenerate = isDegenerate(min, max);\n if (degenerate) {\n warnOnce(\n `Progress.Root:degenerate:${min}:${max}`,\n `Progress.Root: \\`max\\` (${max}) must be greater than \\`min\\` (${min}); the percentage is ` +\n \"rendered as 0. Pass `value={null}` while the total is unknown or empty.\",\n );\n }\n\n const clamped = given === null ? null : clamp(given, min, max);\n const formattedValue =\n clamped === null ? null : formatRangeValue(clamped, min, max, format, locale);\n const base: ProgressState = {\n value: clamped,\n min,\n max,\n percentage: clamped === null ? null : percentage(clamped, min, max),\n formattedValue,\n valueText: formattedValue,\n indeterminate: clamped === null,\n complete: clamped !== null && !degenerate && clamped >= max,\n };\n const valueText =\n getAriaValueText === undefined ? formattedValue : (getAriaValueText(clamped, base) ?? null);\n const state: ProgressState = valueText === base.valueText ? base : { ...base, valueText };\n\n const variables = state.percentage === null ? {} : { \"--progress-value\": `${state.percentage}%` };\n\n const libraryProps: Partial<ComponentPropsWithRef<\"div\">> & DataAttributes = {\n role: \"progressbar\",\n \"aria-valuemin\": min,\n \"aria-valuemax\": max,\n \"aria-valuenow\": clamped ?? undefined,\n \"aria-valuetext\": valueText ?? undefined,\n \"aria-labelledby\": `${id}-label`,\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n };\n\n const element = renderElement<ComponentPropsWithRef<\"div\">, ProgressState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n // The custom property loses to the consumer's own entry (design 3.1).\n style: (s) => ({ ...(variables as CSSProperties), ...resolveStateValue(style, s) }),\n children,\n props: rest,\n libraryProps,\n // Passed through to the element, never read during render.\n // oxlint-disable-next-line react/refs\n ref: mergeRenderRef(ref, render),\n });\n\n return <ProgressContext value={{ id, state }}>{element}</ProgressContext>;\n}\n\nProgressRoot.displayName = \"ProgressRoot\";\n"],"mappings":";;;;;;;;;;;;;;;;AAuFA,SAAgB,aAAa,EAC3B,QAAQ,MACR,MAAM,GACN,MAAM,KACN,QACA,QACA,kBACA,WACA,OACA,UACA,QACA,KACA,GAAG,QACiB;CACpB,MAAM,KAAK,MAAM;CAEjB,IAAI,QAAQ;CACZ,IAAI,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,GAAG;EAC7C,SACE,4BAA4B,SAC5B,+BAA+B,MAAM,0GAEvC;EACA,QAAQ;CACV;CACA,MAAM,aAAa,aAAa,KAAK,GAAG;CACxC,IAAI,YACF,SACE,4BAA4B,IAAI,GAAG,OACnC,2BAA2B,IAAI,kCAAkC,IAAI,+FAEvE;CAGF,MAAM,UAAU,UAAU,OAAO,OAAO,MAAM,OAAO,KAAK,GAAG;CAC7D,MAAM,iBACJ,YAAY,OAAO,OAAO,iBAAiB,SAAS,KAAK,KAAK,QAAQ,MAAM;CAC9E,MAAM,OAAsB;EAC1B,OAAO;EACP;EACA;EACA,YAAY,YAAY,OAAO,OAAO,WAAW,SAAS,KAAK,GAAG;EAClE;EACA,WAAW;EACX,eAAe,YAAY;EAC3B,UAAU,YAAY,QAAQ,CAAC,cAAc,WAAW;CAC1D;CACA,MAAM,YACJ,qBAAqB,KAAA,IAAY,iBAAkB,iBAAiB,SAAS,IAAI,KAAK;CACxF,MAAM,QAAuB,cAAc,KAAK,YAAY,OAAO;EAAE,GAAG;EAAM;CAAU;CAExF,MAAM,YAAY,MAAM,eAAe,OAAO,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,WAAW,GAAG;CAEhG,MAAM,eAAuE;EAC3E,MAAM;EACN,iBAAiB;EACjB,iBAAiB;EACjB,iBAAiB,WAAW,KAAA;EAC5B,kBAAkB,aAAa,KAAA;EAC/B,mBAAmB,GAAG,GAAG;EACzB,sBAAsB,SAAS,MAAM,aAAa;EAClD,iBAAiB,SAAS,MAAM,QAAQ;CAC1C;CAEA,MAAM,UAAU,cAA2D;EACzE,gBAAgB;EAChB;EACA;EACA;EAEA,QAAQ,OAAO;GAAE,GAAI;GAA6B,GAAG,kBAAkB,OAAO,CAAC;EAAE;EACjF;EACA,OAAO;EACP;EAGA,KAAK,eAAe,KAAK,MAAM;CACjC,CAAC;CAED,OAAO,oBAAC,iBAAD;EAAiB,OAAO;GAAE;GAAI;EAAM;EAAI,UAAA;CAAyB,CAAA;AAC1E;AAEA,aAAa,cAAc"}
@@ -0,0 +1,19 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ProgressState } from "./progress-root.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/progress/progress-track.d.ts
5
+ export interface ProgressTrackProps extends Omit<ComponentPropsWithRef<"div">, "className" | "style" | "children"> {
6
+ className?: StateValue<string | undefined, ProgressState>;
7
+ style?: StateValue<CSSProperties | undefined, ProgressState>;
8
+ children?: StateValue<ReactNode, ProgressState>;
9
+ render?: RenderProp<ComponentPropsWithRef<"div">, ProgressState>;
10
+ }
11
+ /**
12
+ * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.
13
+ */
14
+ export declare function ProgressTrack({ className, style, children, render, ...rest }: ProgressTrackProps): ReactNode;
15
+ export declare namespace ProgressTrack {
16
+ var displayName: string;
17
+ }
18
+ //#endregion
19
+ //# sourceMappingURL=progress-track.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-track.d.mts","names":[],"sources":["../../src/progress/progress-track.tsx"],"mappings":";;;;iBAQiB,2BAA2B,KAC1C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,8BAA8B;;;;;wBAMpC,gBAAgB,WAAW,OAAO,UAAU,WAAW,QAAQ,qBAAkB;yBAAjF"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
+ import { useProgressContext } from "./progress-context.mjs";
5
+ //#region src/progress/progress-track.tsx
6
+ /**
7
+ * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.
8
+ */
9
+ function ProgressTrack({ className, style, children, render, ...rest }) {
10
+ const { state } = useProgressContext("Progress.Track");
11
+ return useRender({
12
+ defaultElement: "div",
13
+ render,
14
+ state,
15
+ className,
16
+ style,
17
+ children,
18
+ props: rest,
19
+ libraryProps: {
20
+ "data-indeterminate": dataAttr(state.indeterminate),
21
+ "data-complete": dataAttr(state.complete)
22
+ }
23
+ });
24
+ }
25
+ ProgressTrack.displayName = "ProgressTrack";
26
+ //#endregion
27
+ export { ProgressTrack };
28
+
29
+ //# sourceMappingURL=progress-track.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-track.mjs","names":[],"sources":["../../src/progress/progress-track.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useProgressContext } from \"./progress-context.js\";\nimport type { ProgressState } from \"./progress-root.js\";\n\nexport interface ProgressTrackProps extends Omit<\n ComponentPropsWithRef<\"div\">,\n \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"div\">, ProgressState>;\n}\n\n/**\n * `Progress.Track`: the rail. It renders nothing but the state's data attributes. Owned keys: `data-indeterminate`, `data-complete`.\n */\nexport function ProgressTrack({ className, style, children, render, ...rest }: ProgressTrackProps) {\n const { state } = useProgressContext(\"Progress.Track\");\n return useRender<ComponentPropsWithRef<\"div\">, ProgressState>({\n defaultElement: \"div\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n },\n });\n}\n\nProgressTrack.displayName = \"ProgressTrack\";\n"],"mappings":";;;;;;;;AAqBA,SAAgB,cAAc,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA4B;CACjG,MAAM,EAAE,UAAU,mBAAmB,gBAAgB;CACrD,OAAO,UAAuD;EAC5D,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,sBAAsB,SAAS,MAAM,aAAa;GAClD,iBAAiB,SAAS,MAAM,QAAQ;EAC1C;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
@@ -0,0 +1,20 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { ProgressState } from "./progress-root.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/progress/progress-value.d.ts
5
+ export interface ProgressValueProps extends Omit<ComponentPropsWithRef<"span">, "className" | "style" | "children"> {
6
+ className?: StateValue<string | undefined, ProgressState>;
7
+ style?: StateValue<CSSProperties | undefined, ProgressState>;
8
+ /** Default: `state.formattedValue` (nothing while indeterminate). */
9
+ children?: StateValue<ReactNode, ProgressState>;
10
+ render?: RenderProp<ComponentPropsWithRef<"span">, ProgressState>;
11
+ }
12
+ /**
13
+ * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden="true"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.
14
+ */
15
+ export declare function ProgressValue({ className, style, children, render, ...rest }: ProgressValueProps): ReactNode;
16
+ export declare namespace ProgressValue {
17
+ var displayName: string;
18
+ }
19
+ //#endregion
20
+ //# sourceMappingURL=progress-value.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-value.d.mts","names":[],"sources":["../../src/progress/progress-value.tsx"],"mappings":";;;;iBAQiB,2BAA2B,KAC1C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,+BAA+B;;;;;wBAMrC,gBAAgB,WAAW,OAAO,UAAU,WAAW,QAAQ,qBAAkB;yBAAjF"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useRender } from "../internal/use-render.mjs";
4
+ import { useProgressContext } from "./progress-context.mjs";
5
+ //#region src/progress/progress-value.tsx
6
+ /**
7
+ * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden="true"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.
8
+ */
9
+ function ProgressValue({ className, style, children, render, ...rest }) {
10
+ const { state } = useProgressContext("Progress.Value");
11
+ const props = {
12
+ ...rest,
13
+ "aria-hidden": rest["aria-hidden"] ?? true
14
+ };
15
+ return useRender({
16
+ defaultElement: "span",
17
+ render,
18
+ state,
19
+ className,
20
+ style,
21
+ children: children ?? state.formattedValue,
22
+ props,
23
+ libraryProps: {
24
+ "data-indeterminate": dataAttr(state.indeterminate),
25
+ "data-complete": dataAttr(state.complete)
26
+ }
27
+ });
28
+ }
29
+ ProgressValue.displayName = "ProgressValue";
30
+ //#endregion
31
+ export { ProgressValue };
32
+
33
+ //# sourceMappingURL=progress-value.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-value.mjs","names":[],"sources":["../../src/progress/progress-value.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useProgressContext } from \"./progress-context.js\";\nimport type { ProgressState } from \"./progress-root.js\";\n\nexport interface ProgressValueProps extends Omit<\n ComponentPropsWithRef<\"span\">,\n \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, ProgressState>;\n style?: StateValue<CSSProperties | undefined, ProgressState>;\n /** Default: `state.formattedValue` (nothing while indeterminate). */\n children?: StateValue<ReactNode, ProgressState>;\n render?: RenderProp<ComponentPropsWithRef<\"span\">, ProgressState>;\n}\n\n/**\n * `Progress.Value`: shows `state.formattedValue` or `children(state)`. `aria-hidden=\"true\"` is a default the consumer may override, not an owned key: the same text is in the Root's `aria-valuetext`. Owned keys: `data-indeterminate`, `data-complete`.\n */\nexport function ProgressValue({ className, style, children, render, ...rest }: ProgressValueProps) {\n const { state } = useProgressContext(\"Progress.Value\");\n const props = { ...rest, \"aria-hidden\": rest[\"aria-hidden\"] ?? true };\n return useRender<ComponentPropsWithRef<\"span\">, ProgressState>({\n defaultElement: \"span\",\n render,\n state,\n className,\n style,\n children: children ?? state.formattedValue,\n props,\n libraryProps: {\n \"data-indeterminate\": dataAttr(state.indeterminate),\n \"data-complete\": dataAttr(state.complete),\n },\n });\n}\n\nProgressValue.displayName = \"ProgressValue\";\n"],"mappings":";;;;;;;;AAsBA,SAAgB,cAAc,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA4B;CACjG,MAAM,EAAE,UAAU,mBAAmB,gBAAgB;CACrD,MAAM,QAAQ;EAAE,GAAG;EAAM,eAAe,KAAK,kBAAkB;CAAK;CACpE,OAAO,UAAwD;EAC7D,gBAAgB;EAChB;EACA;EACA;EACA;EACA,UAAU,YAAY,MAAM;EAC5B;EACA,cAAc;GACZ,sBAAsB,SAAS,MAAM,aAAa;GAClD,iBAAiB,SAAS,MAAM,QAAQ;EAC1C;CACF,CAAC;AACH;AAEA,cAAc,cAAc"}
@@ -76,7 +76,9 @@ export interface RadioGroupRootProps extends Omit<ComponentPropsWithRef<"fieldse
76
76
  * Carries `data-pending` while `valueChangeAction` is in flight.
77
77
  *
78
78
  * Owned keys (conventions 1.2): `role`, `aria-required`, `disabled`, `form`, `data-pending`,
79
- * `data-disabled`.
79
+ * `data-disabled`; inside a `Field.Root` also `aria-labelledby` (→ `Field.Label`, token-merged),
80
+ * `aria-describedby` (token-merged), `aria-invalid` and `data-invalid`, and `name` / `required` /
81
+ * `disabled` default from the Field.
80
82
  *
81
83
  * Keep every Item in the same Suspense boundary as its Root when server rendering. Partial
82
84
  * hydration of a group (a boundary between Root and Items that stays dehydrated while the user
@@ -84,7 +86,7 @@ export interface RadioGroupRootProps extends Omit<ComponentPropsWithRef<"fieldse
84
86
  * still dehydrated makes react-dom throw "Mixing React and non-React radio inputs with the same
85
87
  * `name` is not supported". Development warns when Items hydrate after their Root.
86
88
  */
87
- export declare function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp, form, required, disabled, className, style, children, render, ...rest }: RadioGroupRootProps): import("react").JSX.Element;
89
+ export declare function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp, form, required: requiredProp, disabled: disabledProp, className, style, children, render, ...rest }: RadioGroupRootProps): import("react").JSX.Element;
88
90
  export declare namespace RadioGroupRoot {
89
91
  var displayName: string;
90
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group-root.d.mts","names":[],"sources":["../../src/radio-group/radio-group-root.tsx"],"mappings":";;;;iBAsBiB,qCAAqC;;;;;;;WAO3C,QAAQ;;iBAGF;;WAEN;;WAEA;;WAEA;;iBAGM,4BAA4B,KAC3C;;;;;;;;;;;EAoBA;;;;;EAKA;;;;;;;;;;;;EAYA,oBAAoB,4BAA4B;;;;;;EAMhD;;EAEA;;;;;;EAMA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,mCAAmC;;;;;;;;;;;;;;;;wBAkCzC,iBACd,OACA,cACA,mBACA,MAAM,UACN,MACA,UACA,UACA,WACA,OACA,UACA,WACG,QACF,sCAAmB,IAAA;yBAbN"}
1
+ {"version":3,"file":"radio-group-root.d.mts","names":[],"sources":["../../src/radio-group/radio-group-root.tsx"],"mappings":";;;;iBA2BiB,qCAAqC;;;;;;;WAO3C,QAAQ;;iBAGF;;WAEN;;WAEA;;WAEA;;iBAGM,4BAA4B,KAC3C;;;;;;;;;;;EAoBA;;;;;EAKA;;;;;;;;;;;;EAYA,oBAAoB,4BAA4B;;;;;;EAMhD;;EAEA;;;;;;EAMA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,mCAAmC;;;;;;;;;;;;;;;;;;wBAoCzC,iBACd,OACA,cACA,mBACA,MAAM,UACN,MACA,UAAU,cACV,UAAU,cACV,WACA,OACA,UACA,WACG,QACF,sCAAmB,IAAA;yBAbN"}
@@ -4,9 +4,10 @@ import { dataAttr } from "../internal/data-attr.mjs";
4
4
  import { transitionTypes } from "../internal/transition-types.mjs";
5
5
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
6
6
  import { useRender } from "../internal/use-render.mjs";
7
+ import { useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
7
8
  import { RadioGroupContext } from "./radio-group-context.mjs";
8
9
  import { useNativeGroupReconciliation } from "../internal/use-native-group-reconciliation.mjs";
9
- import { useCallback, useId, useLayoutEffect, useRef } from "react";
10
+ import { useCallback, useId, useLayoutEffect, useMemo, useRef } from "react";
10
11
  import { jsx } from "react/jsx-runtime";
11
12
  //#region src/radio-group/radio-group-root.tsx
12
13
  const isDev = process.env.NODE_ENV !== "production";
@@ -26,7 +27,9 @@ function readGroup(fieldset, name, prop) {
26
27
  * Carries `data-pending` while `valueChangeAction` is in flight.
27
28
  *
28
29
  * Owned keys (conventions 1.2): `role`, `aria-required`, `disabled`, `form`, `data-pending`,
29
- * `data-disabled`.
30
+ * `data-disabled`; inside a `Field.Root` also `aria-labelledby` (→ `Field.Label`, token-merged),
31
+ * `aria-describedby` (token-merged), `aria-invalid` and `data-invalid`, and `name` / `required` /
32
+ * `disabled` default from the Field.
30
33
  *
31
34
  * Keep every Item in the same Suspense boundary as its Root when server rendering. Partial
32
35
  * hydration of a group (a boundary between Root and Items that stays dehydrated while the user
@@ -34,9 +37,18 @@ function readGroup(fieldset, name, prop) {
34
37
  * still dehydrated makes react-dom throw "Mixing React and non-React radio inputs with the same
35
38
  * `name` is not supported". Development warns when Items hydrate after their Root.
36
39
  */
37
- function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp, form, required = false, disabled = false, className, style, children, render, ...rest }) {
40
+ function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp, form, required: requiredProp, disabled: disabledProp, className, style, children, render, ...rest }) {
41
+ const field = useFieldControl({
42
+ labelable: false,
43
+ name: nameProp,
44
+ disabled: disabledProp,
45
+ required: requiredProp,
46
+ component: "RadioGroup.Root"
47
+ });
48
+ const required = field.required;
49
+ const disabled = field.disabled;
38
50
  const fallbackName = useId();
39
- const name = nameProp ?? fallbackName;
51
+ const name = field.name ?? fallbackName;
40
52
  const fieldsetRef = useRef(null);
41
53
  const warnedElement = useRef(false);
42
54
  const { optimistic, pending, dispatch, latestInFlight } = useControllableAction({
@@ -50,6 +62,7 @@ function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp
50
62
  prop: "value"
51
63
  }
52
64
  });
65
+ useFieldValueChange(optimistic);
53
66
  /** What the user intends: the latest in-flight dispatch, else optimistic (conventions 3.8 rule 1). */
54
67
  const base = () => {
55
68
  const inFlight = latestInFlight();
@@ -89,20 +102,32 @@ function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp
89
102
  fieldsetRef.current = null;
90
103
  };
91
104
  }, []);
92
- const context = {
105
+ const rootRef = useMergedRef(libraryRef, field.ref);
106
+ const contextDefault = value === void 0 ? defaultValue ?? null : void 0;
107
+ const context = useMemo(() => ({
93
108
  name,
94
109
  form,
95
110
  required,
96
111
  optimistic,
97
112
  pending,
98
113
  disabled,
99
- defaultValue: value === void 0 ? defaultValue ?? null : void 0,
114
+ defaultValue: contextDefault,
100
115
  onItemMounted: onItemMountedWithCheck,
101
116
  select: (next, event) => {
102
117
  if (next === optimistic) return;
103
118
  dispatch(next, createActionDetails(event, { reason: "activate" }));
104
119
  }
105
- };
120
+ }), [
121
+ name,
122
+ form,
123
+ required,
124
+ optimistic,
125
+ pending,
126
+ disabled,
127
+ contextDefault,
128
+ onItemMountedWithCheck,
129
+ dispatch
130
+ ]);
106
131
  const element = useRender({
107
132
  defaultElement: "fieldset",
108
133
  render,
@@ -116,6 +141,7 @@ function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp
116
141
  children,
117
142
  props: rest,
118
143
  libraryProps: {
144
+ ...field.attributes,
119
145
  role: "radiogroup",
120
146
  "aria-required": required ? "true" : void 0,
121
147
  disabled,
@@ -123,7 +149,7 @@ function RadioGroupRoot({ value, defaultValue, valueChangeAction, name: nameProp
123
149
  "data-pending": dataAttr(pending),
124
150
  "data-disabled": dataAttr(disabled)
125
151
  },
126
- ref: libraryRef
152
+ ref: rootRef
127
153
  });
128
154
  return /* @__PURE__ */ jsx(RadioGroupContext, {
129
155
  value: context,
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group-root.mjs","names":[],"sources":["../../src/radio-group/radio-group-root.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useId, useLayoutEffect, useRef } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useNativeGroupReconciliation } from \"../internal/use-native-group-reconciliation.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { RadioGroupContext } from \"./radio-group-context.js\";\nimport type { RadioGroupContextValue } from \"./radio-group-context.js\";\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/** Details passed as the second argument of `valueChangeAction`. */\nexport interface RadioGroupValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user checked a radio (click, Space, label click, or an arrow key, all of\n * which arrive as a native `click`). `\"platform\"`: the browser changed the checked radio\n * itself: a form reset (`details.event` is the `reset` event), or a click before hydration /\n * Firefox form-state restoration found at mount (`details.event` is `undefined`).\n */\n readonly reason: ChangeReason;\n}\n\nexport interface RadioGroupRootState {\n /** Optimistic checked value, or `null`. Content rendered from it must not suspend. */\n readonly value: string | null;\n /** An action dispatched through this group is in flight. */\n readonly pending: boolean;\n /** The `disabled` prop. */\n readonly disabled: boolean;\n}\n\nexport interface RadioGroupRootProps extends Omit<\n ComponentPropsWithRef<\"fieldset\">,\n | \"className\"\n | \"style\"\n | \"children\"\n | \"defaultValue\"\n | \"defaultChecked\"\n | \"name\"\n | \"disabled\"\n | \"form\"\n> {\n /**\n * Controlled checked value. `null` checks nothing; `undefined` means uncontrolled.\n *\n * A form reset returns each radio to the `checked` it had when *that radio* mounted (React sets\n * `defaultChecked` once, from the initial `checked`). An Item added on the client while `value`\n * equals its value therefore also gets `defaultChecked`, so two radios may carry it and the\n * reset target is not necessarily the group's mount-time value. The reset is offered to\n * `valueChangeAction` as usual; for a stable target remount the group with a `key` or use\n * `defaultValue`, whose latest value every Item mirrors.\n */\n value?: string | null;\n /**\n * Initial value in uncontrolled mode. Defaults to `null` (nothing checked). Also the value a\n * form reset returns to: the latest prop value is mirrored into the radios' `defaultChecked`.\n */\n defaultValue?: string | null;\n /**\n * Runs inside the Root's transition whenever the checked radio changes. May be sync or async\n * (also a Server Function); rejections reach the nearest Error Boundary and roll the selection\n * back.\n *\n * `next` is a string for every user interaction. It is `null` only with\n * `details.reason === \"platform\"`, when a form reset returned the group to \"nothing checked\".\n * Every arrow key press dispatches; the latest dispatch wins. A `setState` placed after your\n * own `await` is not a Transition update; wrap it in `startTransition` (React limitation).\n * `details.event.preventDefault()` is not a veto; use controlled mode to veto a change.\n */\n valueChangeAction?: ChangeAction<string | null, RadioGroupValueChangeDetails>;\n /**\n * The `name` shared by every radio in the group (form data key). Defaults to a `useId()` value;\n * pass a real name when the group is inside a `<form>` you submit. Must be unique within the\n * form: react-dom throws if a non-React radio shares it.\n */\n name?: string;\n /** The `form` attribute, applied to the fieldset and to every radio. */\n form?: string;\n /**\n * Marks every radio `required`, which makes the group required (one checked radio satisfies it),\n * and renders `aria-required=\"true\"` on the fieldset so the radiogroup itself is exposed as\n * required.\n */\n required?: boolean;\n /** Renders `<fieldset disabled>`: every radio is disabled, unfocusable and skipped by arrows. */\n disabled?: boolean;\n className?: StateValue<string | undefined, RadioGroupRootState>;\n style?: StateValue<CSSProperties | undefined, RadioGroupRootState>;\n children?: StateValue<ReactNode, RadioGroupRootState>;\n /** Replace the rendered element. Must keep a `<fieldset>`. */\n render?: RenderProp<ComponentPropsWithRef<\"fieldset\">, RadioGroupRootState>;\n}\n\n/**\n * Value of the group's checked radio as the DOM shows it (`prop: \"checked\"`) or as a form reset\n * leaves it (`prop: \"defaultChecked\"`), or `null`. Only radios of this group's `name` count, so a\n * nested group is ignored.\n */\nfunction readGroup(\n fieldset: HTMLFieldSetElement | null,\n name: string,\n prop: \"checked\" | \"defaultChecked\",\n): string | null {\n if (fieldset === null) return null;\n for (const radio of fieldset.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]')) {\n if (radio.name === name && radio[prop]) return radio.value;\n }\n return null;\n}\n\n/**\n * `<fieldset role=\"radiogroup\">` that owns the group's state, the transition, the shared `name`,\n * the form-reset listener and the mount reconciliation (design/components/radio-group.md 13.3).\n * Carries `data-pending` while `valueChangeAction` is in flight.\n *\n * Owned keys (conventions 1.2): `role`, `aria-required`, `disabled`, `form`, `data-pending`,\n * `data-disabled`.\n *\n * Keep every Item in the same Suspense boundary as its Root when server rendering. Partial\n * hydration of a group (a boundary between Root and Items that stays dehydrated while the user\n * interacts) is not supported by React: clicking a hydrated radio while same-`name` siblings are\n * still dehydrated makes react-dom throw \"Mixing React and non-React radio inputs with the same\n * `name` is not supported\". Development warns when Items hydrate after their Root.\n */\nexport function RadioGroupRoot({\n value,\n defaultValue,\n valueChangeAction,\n name: nameProp,\n form,\n required = false,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: RadioGroupRootProps) {\n const fallbackName = useId();\n const name = nameProp ?? fallbackName;\n const fieldsetRef = useRef<HTMLFieldSetElement | null>(null);\n const warnedElement = useRef(false);\n\n const { optimistic, pending, dispatch, latestInFlight } = useControllableAction<\n string | null,\n RadioGroupValueChangeDetails\n >({\n controlled: value,\n defaultValue,\n initialValue: null,\n action: valueChangeAction,\n transitionTypes: () => transitionTypes(\"radio-group\"),\n warn: { component: \"RadioGroup.Root\", prop: \"value\" },\n });\n // Deliberately no warning when neither `value` nor `defaultValue` is given: an unchecked group\n // is the HTML default (design decision 2).\n\n /** What the user intends: the latest in-flight dispatch, else optimistic (conventions 3.8 rule 1). */\n const base = (): string | null => {\n const inFlight = latestInFlight();\n // Not `?.next ?? optimistic`: an in-flight reset to `null` is a real intent.\n return inFlight === null ? optimistic : inFlight.next;\n };\n\n // The residual browser paths (design section 5): one dispatch per group, from here. Items that\n // mount after the Root report through `onItemMounted` so the group is reconciled again.\n const { onItemMounted } = useNativeGroupReconciliation<string | null>({\n element: fieldsetRef,\n readCurrent: () => readGroup(fieldsetRef.current, name, \"checked\"),\n readDefault: () => readGroup(fieldsetRef.current, name, \"defaultChecked\"),\n base,\n onPlatformChange: (next, event) =>\n dispatch(next, createActionDetails(event, { reason: \"platform\" })),\n });\n\n // Dev-only partial-hydration detection. The radios present in the fieldset when the Root\n // mounts are either mounted in the Root's commit or still dehydrated server HTML. An Item that\n // mounts later on one of those elements hydrated after the Root (an Item created on the client\n // gets a new element). Items of the Root's own commit run their mount effect before this one,\n // while the snapshot is still `null`; StrictMode's re-run finds it reset by the cleanup.\n const serverRadios = useRef<ReadonlySet<Element> | null>(null);\n const warnedPartialHydration = useRef(false);\n useLayoutEffect(() => {\n if (!isDev) return;\n const el = fieldsetRef.current;\n serverRadios.current = new Set(el === null ? [] : el.querySelectorAll('input[type=\"radio\"]'));\n return () => {\n serverRadios.current = null;\n };\n }, []);\n const onItemMountedWithCheck = useCallback(\n (element?: Element | null) => {\n if (\n isDev &&\n !warnedPartialHydration.current &&\n element != null &&\n serverRadios.current?.has(element) === true\n ) {\n warnedPartialHydration.current = true;\n console.error(\n `RadioGroup.Item: an Item hydrated after its RadioGroup.Root (a Suspense boundary ` +\n `between them). Partial hydration of a radio group is not supported by React: ` +\n `clicking a hydrated radio while same-name radios are still dehydrated makes ` +\n `react-dom throw \"Mixing React and non-React radio inputs with the same name is not ` +\n `supported\". Keep every Item in the same Suspense boundary as its Root.`,\n );\n }\n onItemMounted(element);\n },\n [onItemMounted],\n );\n\n const libraryRef = useCallback((el: HTMLFieldSetElement) => {\n fieldsetRef.current = el;\n if (isDev && !warnedElement.current && el.tagName !== \"FIELDSET\") {\n warnedElement.current = true;\n console.error(\n `RadioGroup.Root: expected to render a <fieldset> element but got ` +\n `<${el.tagName.toLowerCase()}>. The platform semantics (legend naming, disabled ` +\n `inheritance, form reset) need a real <fieldset>.`,\n );\n }\n return () => {\n fieldsetRef.current = null;\n };\n }, []);\n\n const context: RadioGroupContextValue = {\n name,\n form,\n required,\n optimistic,\n pending,\n disabled,\n defaultValue: value === undefined ? (defaultValue ?? null) : undefined,\n onItemMounted: onItemMountedWithCheck,\n select: (next, event) => {\n // No-op rule against the optimistic value (conventions 2.3 item 7, design 4.2).\n if (next === optimistic) return;\n dispatch(next, createActionDetails(event, { reason: \"activate\" }));\n },\n };\n\n const state: RadioGroupRootState = { value: optimistic, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"fieldset\">, RadioGroupRootState>({\n defaultElement: \"fieldset\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n role: \"radiogroup\",\n \"aria-required\": required ? \"true\" : undefined,\n disabled,\n form,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n },\n ref: libraryRef,\n });\n\n return <RadioGroupContext value={context}>{element}</RadioGroupContext>;\n}\n\nRadioGroupRoot.displayName = \"RadioGroupRoot\";\n"],"mappings":";;;;;;;;;;;AAmBA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;;AAyFvC,SAAS,UACP,UACA,MACA,MACe;CACf,IAAI,aAAa,MAAM,OAAO;CAC9B,KAAK,MAAM,SAAS,SAAS,iBAAmC,uBAAqB,GACnF,IAAI,MAAM,SAAS,QAAQ,MAAM,OAAO,OAAO,MAAM;CAEvD,OAAO;AACT;;;;;;;;;;;;;;;AAgBA,SAAgB,eAAe,EAC7B,OACA,cACA,mBACA,MAAM,UACN,MACA,WAAW,OACX,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACmB;CACtB,MAAM,eAAe,MAAM;CAC3B,MAAM,OAAO,YAAY;CACzB,MAAM,cAAc,OAAmC,IAAI;CAC3D,MAAM,gBAAgB,OAAO,KAAK;CAElC,MAAM,EAAE,YAAY,SAAS,UAAU,mBAAmB,sBAGxD;EACA,YAAY;EACZ;EACA,cAAc;EACd,QAAQ;EACR,uBAAuB,gBAAgB,aAAa;EACpD,MAAM;GAAE,WAAW;GAAmB,MAAM;EAAQ;CACtD,CAAC;;CAKD,MAAM,aAA4B;EAChC,MAAM,WAAW,eAAe;EAEhC,OAAO,aAAa,OAAO,aAAa,SAAS;CACnD;CAIA,MAAM,EAAE,kBAAkB,6BAA4C;EACpE,SAAS;EACT,mBAAmB,UAAU,YAAY,SAAS,MAAM,SAAS;EACjE,mBAAmB,UAAU,YAAY,SAAS,MAAM,gBAAgB;EACxE;EACA,mBAAmB,MAAM,UACvB,SAAS,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;CACrE,CAAC;CAOD,MAAM,eAAe,OAAoC,IAAI;CAC7D,MAAM,yBAAyB,OAAO,KAAK;CAC3C,sBAAsB;EACpB,IAAI,CAAC,OAAO;EACZ,MAAM,KAAK,YAAY;EACvB,aAAa,UAAU,IAAI,IAAI,OAAO,OAAO,CAAC,IAAI,GAAG,iBAAiB,uBAAqB,CAAC;EAC5F,aAAa;GACX,aAAa,UAAU;EACzB;CACF,GAAG,CAAC,CAAC;CACL,MAAM,yBAAyB,aAC5B,YAA6B;EAC5B,IACE,SACA,CAAC,uBAAuB,WACxB,WAAW,QACX,aAAa,SAAS,IAAI,OAAO,MAAM,MACvC;GACA,uBAAuB,UAAU;GACjC,QAAQ,MACN,uYAKF;EACF;EACA,cAAc,OAAO;CACvB,GACA,CAAC,aAAa,CAChB;CAEA,MAAM,aAAa,aAAa,OAA4B;EAC1D,YAAY,UAAU;EACtB,IAAI,SAAS,CAAC,cAAc,WAAW,GAAG,YAAY,YAAY;GAChE,cAAc,UAAU;GACxB,QAAQ,MACN,qEACM,GAAG,QAAQ,YAAY,EAAE,oGAEjC;EACF;EACA,aAAa;GACX,YAAY,UAAU;EACxB;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,UAAkC;EACtC;EACA;EACA;EACA;EACA;EACA;EACA,cAAc,UAAU,KAAA,IAAa,gBAAgB,OAAQ,KAAA;EAC7D,eAAe;EACf,SAAS,MAAM,UAAU;GAEvB,IAAI,SAAS,YAAY;GACzB,SAAS,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;EACnE;CACF;CAIA,MAAM,UAAU,UAAkE;EAChF,gBAAgB;EAChB;EACA,OAAA;GALmC,OAAO;GAAY;GAAS;EAK3D;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,MAAM;GACN,iBAAiB,WAAW,SAAS,KAAA;GACrC;GACA;GACA,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;EACpC;EACA,KAAK;CACP,CAAC;CAED,OAAO,oBAAC,mBAAD;EAAmB,OAAO;EAAU,UAAA;CAA2B,CAAA;AACxE;AAEA,eAAe,cAAc"}
1
+ {"version":3,"file":"radio-group-root.mjs","names":[],"sources":["../../src/radio-group/radio-group-root.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback, useId, useLayoutEffect, useMemo, useRef } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useNativeGroupReconciliation } from \"../internal/use-native-group-reconciliation.js\";\nimport {\n useFieldControl,\n useFieldValueChange,\n useMergedRef,\n} from \"../internal/use-field-control.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { RadioGroupContext } from \"./radio-group-context.js\";\nimport type { RadioGroupContextValue } from \"./radio-group-context.js\";\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\n/** Details passed as the second argument of `valueChangeAction`. */\nexport interface RadioGroupValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user checked a radio (click, Space, label click, or an arrow key, all of\n * which arrive as a native `click`). `\"platform\"`: the browser changed the checked radio\n * itself: a form reset (`details.event` is the `reset` event), or a click before hydration /\n * Firefox form-state restoration found at mount (`details.event` is `undefined`).\n */\n readonly reason: ChangeReason;\n}\n\nexport interface RadioGroupRootState {\n /** Optimistic checked value, or `null`. Content rendered from it must not suspend. */\n readonly value: string | null;\n /** An action dispatched through this group is in flight. */\n readonly pending: boolean;\n /** The `disabled` prop. */\n readonly disabled: boolean;\n}\n\nexport interface RadioGroupRootProps extends Omit<\n ComponentPropsWithRef<\"fieldset\">,\n | \"className\"\n | \"style\"\n | \"children\"\n | \"defaultValue\"\n | \"defaultChecked\"\n | \"name\"\n | \"disabled\"\n | \"form\"\n> {\n /**\n * Controlled checked value. `null` checks nothing; `undefined` means uncontrolled.\n *\n * A form reset returns each radio to the `checked` it had when *that radio* mounted (React sets\n * `defaultChecked` once, from the initial `checked`). An Item added on the client while `value`\n * equals its value therefore also gets `defaultChecked`, so two radios may carry it and the\n * reset target is not necessarily the group's mount-time value. The reset is offered to\n * `valueChangeAction` as usual; for a stable target remount the group with a `key` or use\n * `defaultValue`, whose latest value every Item mirrors.\n */\n value?: string | null;\n /**\n * Initial value in uncontrolled mode. Defaults to `null` (nothing checked). Also the value a\n * form reset returns to: the latest prop value is mirrored into the radios' `defaultChecked`.\n */\n defaultValue?: string | null;\n /**\n * Runs inside the Root's transition whenever the checked radio changes. May be sync or async\n * (also a Server Function); rejections reach the nearest Error Boundary and roll the selection\n * back.\n *\n * `next` is a string for every user interaction. It is `null` only with\n * `details.reason === \"platform\"`, when a form reset returned the group to \"nothing checked\".\n * Every arrow key press dispatches; the latest dispatch wins. A `setState` placed after your\n * own `await` is not a Transition update; wrap it in `startTransition` (React limitation).\n * `details.event.preventDefault()` is not a veto; use controlled mode to veto a change.\n */\n valueChangeAction?: ChangeAction<string | null, RadioGroupValueChangeDetails>;\n /**\n * The `name` shared by every radio in the group (form data key). Defaults to a `useId()` value;\n * pass a real name when the group is inside a `<form>` you submit. Must be unique within the\n * form: react-dom throws if a non-React radio shares it.\n */\n name?: string;\n /** The `form` attribute, applied to the fieldset and to every radio. */\n form?: string;\n /**\n * Marks every radio `required`, which makes the group required (one checked radio satisfies it),\n * and renders `aria-required=\"true\"` on the fieldset so the radiogroup itself is exposed as\n * required.\n */\n required?: boolean;\n /** Renders `<fieldset disabled>`: every radio is disabled, unfocusable and skipped by arrows. */\n disabled?: boolean;\n className?: StateValue<string | undefined, RadioGroupRootState>;\n style?: StateValue<CSSProperties | undefined, RadioGroupRootState>;\n children?: StateValue<ReactNode, RadioGroupRootState>;\n /** Replace the rendered element. Must keep a `<fieldset>`. */\n render?: RenderProp<ComponentPropsWithRef<\"fieldset\">, RadioGroupRootState>;\n}\n\n/**\n * Value of the group's checked radio as the DOM shows it (`prop: \"checked\"`) or as a form reset\n * leaves it (`prop: \"defaultChecked\"`), or `null`. Only radios of this group's `name` count, so a\n * nested group is ignored.\n */\nfunction readGroup(\n fieldset: HTMLFieldSetElement | null,\n name: string,\n prop: \"checked\" | \"defaultChecked\",\n): string | null {\n if (fieldset === null) return null;\n for (const radio of fieldset.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]')) {\n if (radio.name === name && radio[prop]) return radio.value;\n }\n return null;\n}\n\n/**\n * `<fieldset role=\"radiogroup\">` that owns the group's state, the transition, the shared `name`,\n * the form-reset listener and the mount reconciliation (design/components/radio-group.md 13.3).\n * Carries `data-pending` while `valueChangeAction` is in flight.\n *\n * Owned keys (conventions 1.2): `role`, `aria-required`, `disabled`, `form`, `data-pending`,\n * `data-disabled`; inside a `Field.Root` also `aria-labelledby` (→ `Field.Label`, token-merged),\n * `aria-describedby` (token-merged), `aria-invalid` and `data-invalid`, and `name` / `required` /\n * `disabled` default from the Field.\n *\n * Keep every Item in the same Suspense boundary as its Root when server rendering. Partial\n * hydration of a group (a boundary between Root and Items that stays dehydrated while the user\n * interacts) is not supported by React: clicking a hydrated radio while same-`name` siblings are\n * still dehydrated makes react-dom throw \"Mixing React and non-React radio inputs with the same\n * `name` is not supported\". Development warns when Items hydrate after their Root.\n */\nexport function RadioGroupRoot({\n value,\n defaultValue,\n valueChangeAction,\n name: nameProp,\n form,\n required: requiredProp,\n disabled: disabledProp,\n className,\n style,\n children,\n render,\n ...rest\n}: RadioGroupRootProps) {\n // Inside a Field.Root (design/components/field-form.md 7.2) the fieldset is the Field's group\n // control: `aria-labelledby` → `Field.Label`, the ARIA wiring, and `name` / `required` /\n // `disabled` defaulting from the Field.\n const field = useFieldControl({\n labelable: false,\n name: nameProp,\n disabled: disabledProp,\n required: requiredProp,\n component: \"RadioGroup.Root\",\n });\n const required = field.required;\n const disabled = field.disabled;\n const fallbackName = useId();\n const name = field.name ?? fallbackName;\n const fieldsetRef = useRef<HTMLFieldSetElement | null>(null);\n const warnedElement = useRef(false);\n\n const { optimistic, pending, dispatch, latestInFlight } = useControllableAction<\n string | null,\n RadioGroupValueChangeDetails\n >({\n controlled: value,\n defaultValue,\n initialValue: null,\n action: valueChangeAction,\n transitionTypes: () => transitionTypes(\"radio-group\"),\n warn: { component: \"RadioGroup.Root\", prop: \"value\" },\n });\n // Inside a Field: a value React writes with no event (a rejected action rolling back, a\n // controlled change) re-reads validity and `validate` after the commit.\n useFieldValueChange(optimistic);\n // Deliberately no warning when neither `value` nor `defaultValue` is given: an unchecked group\n // is the HTML default (design decision 2).\n\n /** What the user intends: the latest in-flight dispatch, else optimistic (conventions 3.8 rule 1). */\n const base = (): string | null => {\n const inFlight = latestInFlight();\n // Not `?.next ?? optimistic`: an in-flight reset to `null` is a real intent.\n return inFlight === null ? optimistic : inFlight.next;\n };\n\n // The residual browser paths (design section 5): one dispatch per group, from here. Items that\n // mount after the Root report through `onItemMounted` so the group is reconciled again.\n const { onItemMounted } = useNativeGroupReconciliation<string | null>({\n element: fieldsetRef,\n readCurrent: () => readGroup(fieldsetRef.current, name, \"checked\"),\n readDefault: () => readGroup(fieldsetRef.current, name, \"defaultChecked\"),\n base,\n onPlatformChange: (next, event) =>\n dispatch(next, createActionDetails(event, { reason: \"platform\" })),\n });\n\n // Dev-only partial-hydration detection. The radios present in the fieldset when the Root\n // mounts are either mounted in the Root's commit or still dehydrated server HTML. An Item that\n // mounts later on one of those elements hydrated after the Root (an Item created on the client\n // gets a new element). Items of the Root's own commit run their mount effect before this one,\n // while the snapshot is still `null`; StrictMode's re-run finds it reset by the cleanup.\n const serverRadios = useRef<ReadonlySet<Element> | null>(null);\n const warnedPartialHydration = useRef(false);\n useLayoutEffect(() => {\n if (!isDev) return;\n const el = fieldsetRef.current;\n serverRadios.current = new Set(el === null ? [] : el.querySelectorAll('input[type=\"radio\"]'));\n return () => {\n serverRadios.current = null;\n };\n }, []);\n const onItemMountedWithCheck = useCallback(\n (element?: Element | null) => {\n if (\n isDev &&\n !warnedPartialHydration.current &&\n element != null &&\n serverRadios.current?.has(element) === true\n ) {\n warnedPartialHydration.current = true;\n console.error(\n `RadioGroup.Item: an Item hydrated after its RadioGroup.Root (a Suspense boundary ` +\n `between them). Partial hydration of a radio group is not supported by React: ` +\n `clicking a hydrated radio while same-name radios are still dehydrated makes ` +\n `react-dom throw \"Mixing React and non-React radio inputs with the same name is not ` +\n `supported\". Keep every Item in the same Suspense boundary as its Root.`,\n );\n }\n onItemMounted(element);\n },\n [onItemMounted],\n );\n\n const libraryRef = useCallback((el: HTMLFieldSetElement) => {\n fieldsetRef.current = el;\n if (isDev && !warnedElement.current && el.tagName !== \"FIELDSET\") {\n warnedElement.current = true;\n console.error(\n `RadioGroup.Root: expected to render a <fieldset> element but got ` +\n `<${el.tagName.toLowerCase()}>. The platform semantics (legend naming, disabled ` +\n `inheritance, form reset) need a real <fieldset>.`,\n );\n }\n return () => {\n fieldsetRef.current = null;\n };\n }, []);\n const rootRef = useMergedRef<HTMLFieldSetElement>(libraryRef, field.ref);\n\n // Memoised (#48): `dispatch` and `onItemMountedWithCheck` are stable, so this changes only with\n // the state and the props below.\n const contextDefault = value === undefined ? (defaultValue ?? null) : undefined;\n const context = useMemo<RadioGroupContextValue>(\n () => ({\n name,\n form,\n required,\n optimistic,\n pending,\n disabled,\n defaultValue: contextDefault,\n onItemMounted: onItemMountedWithCheck,\n select: (next, event) => {\n // No-op rule against the optimistic value (conventions 2.3 item 7, design 4.2).\n if (next === optimistic) return;\n dispatch(next, createActionDetails(event, { reason: \"activate\" }));\n },\n }),\n [\n name,\n form,\n required,\n optimistic,\n pending,\n disabled,\n contextDefault,\n onItemMountedWithCheck,\n dispatch,\n ],\n );\n\n const state: RadioGroupRootState = { value: optimistic, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"fieldset\">, RadioGroupRootState>({\n defaultElement: \"fieldset\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...field.attributes,\n role: \"radiogroup\",\n \"aria-required\": required ? \"true\" : undefined,\n disabled,\n form,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n },\n ref: rootRef,\n });\n\n return <RadioGroupContext value={context}>{element}</RadioGroupContext>;\n}\n\nRadioGroupRoot.displayName = \"RadioGroupRoot\";\n"],"mappings":";;;;;;;;;;;;AAwBA,MAAM,QAAQ,QAAQ,IAAI,aAAa;;;;;;AAyFvC,SAAS,UACP,UACA,MACA,MACe;CACf,IAAI,aAAa,MAAM,OAAO;CAC9B,KAAK,MAAM,SAAS,SAAS,iBAAmC,uBAAqB,GACnF,IAAI,MAAM,SAAS,QAAQ,MAAM,OAAO,OAAO,MAAM;CAEvD,OAAO;AACT;;;;;;;;;;;;;;;;;AAkBA,SAAgB,eAAe,EAC7B,OACA,cACA,mBACA,MAAM,UACN,MACA,UAAU,cACV,UAAU,cACV,WACA,OACA,UACA,QACA,GAAG,QACmB;CAItB,MAAM,QAAQ,gBAAgB;EAC5B,WAAW;EACX,MAAM;EACN,UAAU;EACV,UAAU;EACV,WAAW;CACb,CAAC;CACD,MAAM,WAAW,MAAM;CACvB,MAAM,WAAW,MAAM;CACvB,MAAM,eAAe,MAAM;CAC3B,MAAM,OAAO,MAAM,QAAQ;CAC3B,MAAM,cAAc,OAAmC,IAAI;CAC3D,MAAM,gBAAgB,OAAO,KAAK;CAElC,MAAM,EAAE,YAAY,SAAS,UAAU,mBAAmB,sBAGxD;EACA,YAAY;EACZ;EACA,cAAc;EACd,QAAQ;EACR,uBAAuB,gBAAgB,aAAa;EACpD,MAAM;GAAE,WAAW;GAAmB,MAAM;EAAQ;CACtD,CAAC;CAGD,oBAAoB,UAAU;;CAK9B,MAAM,aAA4B;EAChC,MAAM,WAAW,eAAe;EAEhC,OAAO,aAAa,OAAO,aAAa,SAAS;CACnD;CAIA,MAAM,EAAE,kBAAkB,6BAA4C;EACpE,SAAS;EACT,mBAAmB,UAAU,YAAY,SAAS,MAAM,SAAS;EACjE,mBAAmB,UAAU,YAAY,SAAS,MAAM,gBAAgB;EACxE;EACA,mBAAmB,MAAM,UACvB,SAAS,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;CACrE,CAAC;CAOD,MAAM,eAAe,OAAoC,IAAI;CAC7D,MAAM,yBAAyB,OAAO,KAAK;CAC3C,sBAAsB;EACpB,IAAI,CAAC,OAAO;EACZ,MAAM,KAAK,YAAY;EACvB,aAAa,UAAU,IAAI,IAAI,OAAO,OAAO,CAAC,IAAI,GAAG,iBAAiB,uBAAqB,CAAC;EAC5F,aAAa;GACX,aAAa,UAAU;EACzB;CACF,GAAG,CAAC,CAAC;CACL,MAAM,yBAAyB,aAC5B,YAA6B;EAC5B,IACE,SACA,CAAC,uBAAuB,WACxB,WAAW,QACX,aAAa,SAAS,IAAI,OAAO,MAAM,MACvC;GACA,uBAAuB,UAAU;GACjC,QAAQ,MACN,uYAKF;EACF;EACA,cAAc,OAAO;CACvB,GACA,CAAC,aAAa,CAChB;CAEA,MAAM,aAAa,aAAa,OAA4B;EAC1D,YAAY,UAAU;EACtB,IAAI,SAAS,CAAC,cAAc,WAAW,GAAG,YAAY,YAAY;GAChE,cAAc,UAAU;GACxB,QAAQ,MACN,qEACM,GAAG,QAAQ,YAAY,EAAE,oGAEjC;EACF;EACA,aAAa;GACX,YAAY,UAAU;EACxB;CACF,GAAG,CAAC,CAAC;CACL,MAAM,UAAU,aAAkC,YAAY,MAAM,GAAG;CAIvE,MAAM,iBAAiB,UAAU,KAAA,IAAa,gBAAgB,OAAQ,KAAA;CACtE,MAAM,UAAU,eACP;EACL;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;EACd,eAAe;EACf,SAAS,MAAM,UAAU;GAEvB,IAAI,SAAS,YAAY;GACzB,SAAS,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;EACnE;CACF,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAIA,MAAM,UAAU,UAAkE;EAChF,gBAAgB;EAChB;EACA,OAAA;GALmC,OAAO;GAAY;GAAS;EAK3D;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAG,MAAM;GACT,MAAM;GACN,iBAAiB,WAAW,SAAS,KAAA;GACrC;GACA;GACA,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;EACpC;EACA,KAAK;CACP,CAAC;CAED,OAAO,oBAAC,mBAAD;EAAmB,OAAO;EAAU,UAAA;CAA2B,CAAA;AACxE;AAEA,eAAe,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"select-group.d.mts","names":[],"sources":["../../src/select/select-group.tsx"],"mappings":";;;;iBAQiB,yBAAyB,KACxC;;;;;EAOA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,mCAAmC;;;;;;wBAOzC,cACd,OACA,UACA,WACA,OACA,UACA,WACG,QACF,mCAAgB,IAAA;yBARH"}
1
+ {"version":3,"file":"select-group.d.mts","names":[],"sources":["../../src/select/select-group.tsx"],"mappings":";;;;iBASiB,yBAAyB,KACxC;;;;;EAOA;;EAEA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,mCAAmC;;;;;;wBAOzC,cACd,OACA,UACA,WACA,OACA,UACA,WACG,QACF,mCAAgB,IAAA;yBARH"}
@@ -2,6 +2,7 @@
2
2
  import { useRender } from "../internal/use-render.mjs";
3
3
  import { SelectContext, useSelectContext } from "./select-context.mjs";
4
4
  import { useSelectPartRef } from "./select-dom.mjs";
5
+ import { useMemo } from "react";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  //#region src/select/select-group.tsx
7
8
  /**
@@ -30,11 +31,12 @@ function SelectGroup({ label, disabled = false, className, style, children, rend
30
31
  libraryProps: { label },
31
32
  ref
32
33
  });
34
+ const context = useMemo(() => ({
35
+ ...ctx,
36
+ groupDisabled: disabled
37
+ }), [ctx, disabled]);
33
38
  return /* @__PURE__ */ jsx(SelectContext, {
34
- value: {
35
- ...ctx,
36
- groupDisabled: disabled
37
- },
39
+ value: context,
38
40
  children: element
39
41
  });
40
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"select-group.mjs","names":[],"sources":["../../src/select/select-group.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { SelectContext, useSelectContext } from \"./select-context.js\";\nimport { useSelectPartRef } from \"./select-dom.js\";\nimport type { SelectRootState } from \"./select-root.js\";\n\nexport interface SelectGroupProps extends Omit<\n ComponentPropsWithRef<\"optgroup\">,\n \"label\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * The `<optgroup label>`: shown by native pickers (Firefox today) and read by assistive\n * technology. Required. Keep it equal to the text of a `Select.GroupLabel`, if any.\n */\n label: string;\n /** Native `disabled`: every option in the group is disabled. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SelectRootState>;\n style?: StateValue<CSSProperties | undefined, SelectRootState>;\n children?: StateValue<ReactNode, SelectRootState>;\n /** Replace the rendered element. Must keep an `<optgroup>`. */\n render?: RenderProp<ComponentPropsWithRef<\"optgroup\">, SelectRootState>;\n}\n\n/**\n * An `<optgroup>` of options. Its state is the Root's state. Owned key: `label`. Its `disabled`\n * reaches the Options' `state.disabled` / `data-disabled` through context, as `:disabled` does.\n */\nexport function SelectGroup({\n label,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: SelectGroupProps) {\n const ctx = useSelectContext(\"Select.Group\");\n const state: SelectRootState = {\n value: ctx.optimistic,\n pending: ctx.pending,\n disabled: ctx.disabled,\n };\n const { ref } = useSelectPartRef<HTMLOptGroupElement>(\"Select.Group\", \"optgroup\");\n const element = useRender<ComponentPropsWithRef<\"optgroup\">, SelectRootState>({\n defaultElement: \"optgroup\",\n render,\n state,\n className,\n style,\n children,\n props: { ...rest, disabled },\n libraryProps: { label },\n ref,\n });\n // Nested groups are not valid HTML, so this only ever turns `false` into the group's value.\n return <SelectContext value={{ ...ctx, groupDisabled: disabled }}>{element}</SelectContext>;\n}\n\nSelectGroup.displayName = \"SelectGroup\";\n"],"mappings":";;;;;;;;;;AA8BA,SAAgB,YAAY,EAC1B,OACA,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACgB;CACnB,MAAM,MAAM,iBAAiB,cAAc;CAC3C,MAAM,QAAyB;EAC7B,OAAO,IAAI;EACX,SAAS,IAAI;EACb,UAAU,IAAI;CAChB;CACA,MAAM,EAAE,QAAQ,iBAAsC,gBAAgB,UAAU;CAChF,MAAM,UAAU,UAA8D;EAC5E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;GAAE,GAAG;GAAM;EAAS;EAC3B,cAAc,EAAE,MAAM;EACtB;CACF,CAAC;CAED,OAAO,oBAAC,eAAD;EAAe,OAAO;GAAE,GAAG;GAAK,eAAe;EAAS;EAAI,UAAA;CAAuB,CAAA;AAC5F;AAEA,YAAY,cAAc"}
1
+ {"version":3,"file":"select-group.mjs","names":[],"sources":["../../src/select/select-group.tsx"],"sourcesContent":["\"use client\";\nimport { useMemo } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { SelectContext, useSelectContext } from \"./select-context.js\";\nimport { useSelectPartRef } from \"./select-dom.js\";\nimport type { SelectRootState } from \"./select-root.js\";\n\nexport interface SelectGroupProps extends Omit<\n ComponentPropsWithRef<\"optgroup\">,\n \"label\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * The `<optgroup label>`: shown by native pickers (Firefox today) and read by assistive\n * technology. Required. Keep it equal to the text of a `Select.GroupLabel`, if any.\n */\n label: string;\n /** Native `disabled`: every option in the group is disabled. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SelectRootState>;\n style?: StateValue<CSSProperties | undefined, SelectRootState>;\n children?: StateValue<ReactNode, SelectRootState>;\n /** Replace the rendered element. Must keep an `<optgroup>`. */\n render?: RenderProp<ComponentPropsWithRef<\"optgroup\">, SelectRootState>;\n}\n\n/**\n * An `<optgroup>` of options. Its state is the Root's state. Owned key: `label`. Its `disabled`\n * reaches the Options' `state.disabled` / `data-disabled` through context, as `:disabled` does.\n */\nexport function SelectGroup({\n label,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: SelectGroupProps) {\n const ctx = useSelectContext(\"Select.Group\");\n const state: SelectRootState = {\n value: ctx.optimistic,\n pending: ctx.pending,\n disabled: ctx.disabled,\n };\n const { ref } = useSelectPartRef<HTMLOptGroupElement>(\"Select.Group\", \"optgroup\");\n const element = useRender<ComponentPropsWithRef<\"optgroup\">, SelectRootState>({\n defaultElement: \"optgroup\",\n render,\n state,\n className,\n style,\n children,\n props: { ...rest, disabled },\n libraryProps: { label },\n ref,\n });\n // Nested groups are not valid HTML, so this only ever turns `false` into the group's value.\n const context = useMemo(() => ({ ...ctx, groupDisabled: disabled }), [ctx, disabled]);\n return <SelectContext value={context}>{element}</SelectContext>;\n}\n\nSelectGroup.displayName = \"SelectGroup\";\n"],"mappings":";;;;;;;;;;;AA+BA,SAAgB,YAAY,EAC1B,OACA,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACgB;CACnB,MAAM,MAAM,iBAAiB,cAAc;CAC3C,MAAM,QAAyB;EAC7B,OAAO,IAAI;EACX,SAAS,IAAI;EACb,UAAU,IAAI;CAChB;CACA,MAAM,EAAE,QAAQ,iBAAsC,gBAAgB,UAAU;CAChF,MAAM,UAAU,UAA8D;EAC5E,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;GAAE,GAAG;GAAM;EAAS;EAC3B,cAAc,EAAE,MAAM;EACtB;CACF,CAAC;CAED,MAAM,UAAU,eAAe;EAAE,GAAG;EAAK,eAAe;CAAS,IAAI,CAAC,KAAK,QAAQ,CAAC;CACpF,OAAO,oBAAC,eAAD;EAAe,OAAO;EAAU,UAAA;CAAuB,CAAA;AAChE;AAEA,YAAY,cAAc"}
@@ -56,9 +56,11 @@ export interface SelectRootProps extends Omit<ComponentPropsWithRef<"select">, "
56
56
  * `value={optimistic}`: react-dom restores a controlled select to its props after every event,
57
57
  * and only the sync-lane optimistic value survives that restore.
58
58
  *
59
- * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`.
59
+ * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`;
60
+ * inside a `Field.Root` also `id`, `name`, `required`, `aria-invalid`, `aria-describedby`
61
+ * (token-merged) and `data-invalid`, and `disabled` / `name` / `required` default from the Field.
60
62
  */
61
- export declare function SelectRoot({ value, defaultValue, valueChangeAction, disabled, className, style, children, render, ...rest }: SelectRootProps): import("react").JSX.Element;
63
+ export declare function SelectRoot({ value, defaultValue, valueChangeAction, disabled: disabledProp, className, style, children, render, ...rest }: SelectRootProps): import("react").JSX.Element;
62
64
  export declare namespace SelectRoot {
63
65
  var displayName: string;
64
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"select-root.d.mts","names":[],"sources":["../../src/select/select-root.tsx"],"mappings":";;;;iBAqBiB,iCAAiC;;;;;;;;WAQvC,QAAQ;;iBAGF;;WAEN;;WAEA;;WAEA;;iBAGM,wBAAwB,KACvC;;EAYA;;;;;;;;EAQA;;;;;;;;;;;EAWA,oBAAoB,qBAAqB;;EAEzC;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;wBAWvC,aACd,OACA,cACA,mBACA,UACA,WACA,OACA,UACA,WACG,QACF,kCAAe,IAAA;yBAVF"}
1
+ {"version":3,"file":"select-root.d.mts","names":[],"sources":["../../src/select/select-root.tsx"],"mappings":";;;;iBA2BiB,iCAAiC;;;;;;;;WAQvC,QAAQ;;iBAGF;;WAEN;;WAEA;;WAEA;;iBAGM,wBAAwB,KACvC;;EAYA;;;;;;;;EAQA;;;;;;;;;;;EAWA,oBAAoB,qBAAqB;;EAEzC;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAavC,aACd,OACA,cACA,mBACA,UAAU,cACV,WACA,OACA,UACA,WACG,QACF,kCAAe,IAAA;yBAVF"}
@@ -4,10 +4,11 @@ import { dataAttr } from "../internal/data-attr.mjs";
4
4
  import { transitionTypes } from "../internal/transition-types.mjs";
5
5
  import { useControllableAction } from "../internal/use-controllable-action.mjs";
6
6
  import { useRender } from "../internal/use-render.mjs";
7
+ import { fieldInputProps, useFieldControl, useFieldValueChange, useMergedRef } from "../internal/use-field-control.mjs";
7
8
  import { SelectContext } from "./select-context.mjs";
8
9
  import { useSelectPartRef } from "./select-dom.mjs";
9
10
  import { useNativeSelectValue } from "../internal/use-native-select-value.mjs";
10
- import { useRef, useState } from "react";
11
+ import { useMemo, useRef, useState } from "react";
11
12
  import { jsx } from "react/jsx-runtime";
12
13
  //#region src/select/select-root.tsx
13
14
  /**
@@ -16,10 +17,22 @@ import { jsx } from "react/jsx-runtime";
16
17
  * `value={optimistic}`: react-dom restores a controlled select to its props after every event,
17
18
  * and only the sync-lane optimistic value survives that restore.
18
19
  *
19
- * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`.
20
+ * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`;
21
+ * inside a `Field.Root` also `id`, `name`, `required`, `aria-invalid`, `aria-describedby`
22
+ * (token-merged) and `data-invalid`, and `disabled` / `name` / `required` default from the Field.
20
23
  */
21
- function SelectRoot({ value, defaultValue, valueChangeAction, disabled = false, className, style, children, render, ...rest }) {
24
+ function SelectRoot({ value, defaultValue, valueChangeAction, disabled: disabledProp, className, style, children, render, ...rest }) {
22
25
  const { ref: libraryRef, node: selectRef } = useSelectPartRef("Select.Root", "select");
26
+ const field = useFieldControl({
27
+ labelable: true,
28
+ name: rest.name,
29
+ disabled: disabledProp,
30
+ required: rest.required,
31
+ id: rest.id,
32
+ component: "Select.Root"
33
+ });
34
+ const disabled = field.disabled;
35
+ const rootRef = useMergedRef(libraryRef, field.ref);
23
36
  const { optimistic, pending, dispatch, latestInFlight, adopt } = useControllableAction({
24
37
  controlled: value,
25
38
  defaultValue,
@@ -31,6 +44,7 @@ function SelectRoot({ value, defaultValue, valueChangeAction, disabled = false,
31
44
  prop: "value"
32
45
  }
33
46
  });
47
+ useFieldValueChange(optimistic);
34
48
  const [mountValue] = useState(value);
35
49
  const resetTarget = value === void 0 ? defaultValue : mountValue ?? value;
36
50
  const established = useRef(false);
@@ -49,13 +63,18 @@ function SelectRoot({ value, defaultValue, valueChangeAction, disabled = false,
49
63
  } : void 0,
50
64
  onPlatformChange: (next, event) => dispatchChange(next, createActionDetails(event, { reason: "platform" }))
51
65
  });
52
- const context = {
66
+ const context = useMemo(() => ({
53
67
  optimistic,
54
68
  pending,
55
69
  disabled,
56
70
  groupDisabled: false,
57
71
  optionMounted
58
- };
72
+ }), [
73
+ optimistic,
74
+ pending,
75
+ disabled,
76
+ optionMounted
77
+ ]);
59
78
  const element = useRender({
60
79
  defaultElement: "select",
61
80
  render,
@@ -69,6 +88,7 @@ function SelectRoot({ value, defaultValue, valueChangeAction, disabled = false,
69
88
  children,
70
89
  props: rest,
71
90
  libraryProps: {
91
+ ...fieldInputProps(field),
72
92
  value: optimistic,
73
93
  disabled,
74
94
  "data-pending": dataAttr(pending),
@@ -80,7 +100,7 @@ function SelectRoot({ value, defaultValue, valueChangeAction, disabled = false,
80
100
  dispatchChange(next, createActionDetails(event.nativeEvent, { reason: "activate" }));
81
101
  }
82
102
  },
83
- ref: libraryRef
103
+ ref: rootRef
84
104
  });
85
105
  return /* @__PURE__ */ jsx(SelectContext, {
86
106
  value: context,
@@ -1 +1 @@
1
- {"version":3,"file":"select-root.mjs","names":[],"sources":["../../src/select/select-root.tsx"],"sourcesContent":["\"use client\";\nimport { useRef, useState } from \"react\";\nimport type { ChangeEvent, ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useNativeSelectValue } from \"../internal/use-native-select-value.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { SelectContext } from \"./select-context.js\";\nimport type { SelectContextValue } from \"./select-context.js\";\nimport { useSelectPartRef } from \"./select-dom.js\";\n\n/** Details passed as the second argument of `valueChangeAction`. */\nexport interface SelectValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user picked an option (pointer, keyboard, typeahead, or browser autofill,\n * which the library cannot tell from a pick); `details.event` is the native `change` event.\n * `\"platform\"`: the browser changed the value without a pick the library saw: a form reset\n * (`details.event` is the `reset` event), or a pick before hydration / Firefox form-state\n * restoration reconciled at mount (`details.event` is `undefined`).\n */\n readonly reason: ChangeReason;\n}\n\nexport interface SelectRootState {\n /** Optimistic value. Content rendered from it must not suspend. */\n readonly value: string;\n /** An action dispatched through this Select is in flight. */\n readonly pending: boolean;\n /** The `disabled` prop. */\n readonly disabled: boolean;\n}\n\nexport interface SelectRootProps extends Omit<\n ComponentPropsWithRef<\"select\">,\n | \"value\"\n | \"defaultValue\"\n | \"onChange\"\n | \"multiple\"\n | \"size\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Controlled value. `undefined` means uncontrolled. Use `\"\"` for the placeholder option. */\n value?: string;\n /**\n * Initial value in uncontrolled mode, and the value a form reset returns to (the latest prop is\n * mirrored into the options' `defaultSelected`). When omitted, the browser's choice (an option\n * whose value is `\"\"`, else the first enabled option) is adopted at mount, without a dispatch,\n * and is what a form reset returns to. Until a pick (or a platform change) sets the value,\n * options that mount later without the adopted one (a Suspense fallback) adopt again.\n */\n defaultValue?: string;\n /**\n * Runs inside the Root's transition whenever the selected option changes. May be sync or async\n * (also a Server Function); rejections reach the nearest Error Boundary and roll the selection\n * back.\n *\n * In engines whose closed select changes the value on every arrow press (Firefox, Safari with\n * native appearance), every press dispatches; the latest dispatch wins. A `setState` placed\n * after your own `await` is not a Transition update; wrap it in `startTransition` (React\n * limitation). Controlled mode is the way to veto a change.\n */\n valueChangeAction?: ChangeAction<string, SelectValueChangeDetails>;\n /** Native `disabled`. Never set by the library while pending. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SelectRootState>;\n style?: StateValue<CSSProperties | undefined, SelectRootState>;\n children?: StateValue<ReactNode, SelectRootState>;\n /** Replace the rendered element. Must keep a `<select>`. */\n render?: RenderProp<ComponentPropsWithRef<\"select\">, SelectRootState>;\n}\n\n/**\n * The `<select>` itself: owns the value, the transition, the form-reset listener, the mount\n * reconciliation and the re-apply of late options (design/components/select.md 15.2). Renders\n * `value={optimistic}`: react-dom restores a controlled select to its props after every event,\n * and only the sync-lane optimistic value survives that restore.\n *\n * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`.\n */\nexport function SelectRoot({\n value,\n defaultValue,\n valueChangeAction,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: SelectRootProps) {\n const { ref: libraryRef, node: selectRef } = useSelectPartRef<HTMLSelectElement>(\n \"Select.Root\",\n \"select\",\n );\n\n const { optimistic, pending, dispatch, latestInFlight, adopt } = useControllableAction<\n string,\n SelectValueChangeDetails\n >({\n controlled: value,\n defaultValue,\n initialValue: \"\",\n action: valueChangeAction,\n transitionTypes: () => transitionTypes(\"select\"),\n warn: { component: \"Select.Root\", prop: \"value\" },\n });\n // Deliberately no warning when neither `value` nor `defaultValue` is given: the browser's\n // first-option default is adopted (design decision 3, product-owner decision 4).\n\n // Controlled: the mount-time value is the reset target (conventions 3.8 rule 6). Neither\n // `value` nor `defaultValue`: the value adopted at mount, chosen inside the hook.\n const [mountValue] = useState(value);\n const resetTarget = value === undefined ? defaultValue : (mountValue ?? value);\n\n // Any dispatch, a pick or a platform change, ends the adoption of the browser's default.\n const established = useRef(false);\n const dispatchChange = (next: string, details: SelectValueChangeDetails) => {\n established.current = true;\n dispatch(next, details);\n };\n\n const { optionMounted } = useNativeSelectValue({\n ref: selectRef,\n optimistic,\n latestInFlight,\n resetTarget,\n adoptDefault:\n value === undefined && defaultValue === undefined\n ? { adopt, established: () => established.current }\n : undefined,\n onPlatformChange: (next, event) =>\n dispatchChange(next, createActionDetails(event, { reason: \"platform\" })),\n });\n\n const context: SelectContextValue = {\n optimistic,\n pending,\n disabled,\n groupDisabled: false,\n optionMounted,\n };\n const state: SelectRootState = { value: optimistic, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"select\">, SelectRootState>({\n defaultElement: \"select\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n value: optimistic,\n disabled,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onChange: (event: ChangeEvent<HTMLSelectElement>) => {\n // A natively disabled select fires no change; this covers `render` elements.\n if (disabled) return;\n const next = event.currentTarget.value;\n // No-op rule against the optimistic value (conventions 2.3, design 4.2).\n if (next === optimistic) return;\n dispatchChange(next, createActionDetails(event.nativeEvent, { reason: \"activate\" }));\n },\n },\n ref: libraryRef,\n });\n\n return <SelectContext value={context}>{element}</SelectContext>;\n}\n\nSelectRoot.displayName = \"SelectRoot\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,WAAW,EACzB,OACA,cACA,mBACA,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACe;CAClB,MAAM,EAAE,KAAK,YAAY,MAAM,cAAc,iBAC3C,eACA,QACF;CAEA,MAAM,EAAE,YAAY,SAAS,UAAU,gBAAgB,UAAU,sBAG/D;EACA,YAAY;EACZ;EACA,cAAc;EACd,QAAQ;EACR,uBAAuB,gBAAgB,QAAQ;EAC/C,MAAM;GAAE,WAAW;GAAe,MAAM;EAAQ;CAClD,CAAC;CAMD,MAAM,CAAC,cAAc,SAAS,KAAK;CACnC,MAAM,cAAc,UAAU,KAAA,IAAY,eAAgB,cAAc;CAGxE,MAAM,cAAc,OAAO,KAAK;CAChC,MAAM,kBAAkB,MAAc,YAAsC;EAC1E,YAAY,UAAU;EACtB,SAAS,MAAM,OAAO;CACxB;CAEA,MAAM,EAAE,kBAAkB,qBAAqB;EAC7C,KAAK;EACL;EACA;EACA;EACA,cACE,UAAU,KAAA,KAAa,iBAAiB,KAAA,IACpC;GAAE;GAAO,mBAAmB,YAAY;EAAQ,IAChD,KAAA;EACN,mBAAmB,MAAM,UACvB,eAAe,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;CAC3E,CAAC;CAED,MAAM,UAA8B;EAClC;EACA;EACA;EACA,eAAe;EACf;CACF;CAGA,MAAM,UAAU,UAA4D;EAC1E,gBAAgB;EAChB;EACA,OAAA;GAL+B,OAAO;GAAY;GAAS;EAKvD;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,OAAO;GACP;GACA,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,WAAW,UAA0C;IAEnD,IAAI,UAAU;IACd,MAAM,OAAO,MAAM,cAAc;IAEjC,IAAI,SAAS,YAAY;IACzB,eAAe,MAAM,oBAAoB,MAAM,aAAa,EAAE,QAAQ,WAAW,CAAC,CAAC;GACrF;EACF;EACA,KAAK;CACP,CAAC;CAED,OAAO,oBAAC,eAAD;EAAe,OAAO;EAAU,UAAA;CAAuB,CAAA;AAChE;AAEA,WAAW,cAAc"}
1
+ {"version":3,"file":"select-root.mjs","names":[],"sources":["../../src/select/select-root.tsx"],"sourcesContent":["\"use client\";\nimport { useMemo, useRef, useState } from \"react\";\nimport type { ChangeEvent, ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { transitionTypes } from \"../internal/transition-types.js\";\nimport type {\n ActionDetails,\n ChangeAction,\n ChangeReason,\n RenderProp,\n StateValue,\n} from \"../internal/types.js\";\nimport { useControllableAction } from \"../internal/use-controllable-action.js\";\nimport { useNativeSelectValue } from \"../internal/use-native-select-value.js\";\nimport {\n fieldInputProps,\n useFieldControl,\n useFieldValueChange,\n useMergedRef,\n} from \"../internal/use-field-control.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { SelectContext } from \"./select-context.js\";\nimport type { SelectContextValue } from \"./select-context.js\";\nimport { useSelectPartRef } from \"./select-dom.js\";\n\n/** Details passed as the second argument of `valueChangeAction`. */\nexport interface SelectValueChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user picked an option (pointer, keyboard, typeahead, or browser autofill,\n * which the library cannot tell from a pick); `details.event` is the native `change` event.\n * `\"platform\"`: the browser changed the value without a pick the library saw: a form reset\n * (`details.event` is the `reset` event), or a pick before hydration / Firefox form-state\n * restoration reconciled at mount (`details.event` is `undefined`).\n */\n readonly reason: ChangeReason;\n}\n\nexport interface SelectRootState {\n /** Optimistic value. Content rendered from it must not suspend. */\n readonly value: string;\n /** An action dispatched through this Select is in flight. */\n readonly pending: boolean;\n /** The `disabled` prop. */\n readonly disabled: boolean;\n}\n\nexport interface SelectRootProps extends Omit<\n ComponentPropsWithRef<\"select\">,\n | \"value\"\n | \"defaultValue\"\n | \"onChange\"\n | \"multiple\"\n | \"size\"\n | \"disabled\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** Controlled value. `undefined` means uncontrolled. Use `\"\"` for the placeholder option. */\n value?: string;\n /**\n * Initial value in uncontrolled mode, and the value a form reset returns to (the latest prop is\n * mirrored into the options' `defaultSelected`). When omitted, the browser's choice (an option\n * whose value is `\"\"`, else the first enabled option) is adopted at mount, without a dispatch,\n * and is what a form reset returns to. Until a pick (or a platform change) sets the value,\n * options that mount later without the adopted one (a Suspense fallback) adopt again.\n */\n defaultValue?: string;\n /**\n * Runs inside the Root's transition whenever the selected option changes. May be sync or async\n * (also a Server Function); rejections reach the nearest Error Boundary and roll the selection\n * back.\n *\n * In engines whose closed select changes the value on every arrow press (Firefox, Safari with\n * native appearance), every press dispatches; the latest dispatch wins. A `setState` placed\n * after your own `await` is not a Transition update; wrap it in `startTransition` (React\n * limitation). Controlled mode is the way to veto a change.\n */\n valueChangeAction?: ChangeAction<string, SelectValueChangeDetails>;\n /** Native `disabled`. Never set by the library while pending. */\n disabled?: boolean;\n className?: StateValue<string | undefined, SelectRootState>;\n style?: StateValue<CSSProperties | undefined, SelectRootState>;\n children?: StateValue<ReactNode, SelectRootState>;\n /** Replace the rendered element. Must keep a `<select>`. */\n render?: RenderProp<ComponentPropsWithRef<\"select\">, SelectRootState>;\n}\n\n/**\n * The `<select>` itself: owns the value, the transition, the form-reset listener, the mount\n * reconciliation and the re-apply of late options (design/components/select.md 15.2). Renders\n * `value={optimistic}`: react-dom restores a controlled select to its props after every event,\n * and only the sync-lane optimistic value survives that restore.\n *\n * Owned keys (conventions 1.2): `value`, `disabled`, `data-pending`, `data-disabled`, `onChange`;\n * inside a `Field.Root` also `id`, `name`, `required`, `aria-invalid`, `aria-describedby`\n * (token-merged) and `data-invalid`, and `disabled` / `name` / `required` default from the Field.\n */\nexport function SelectRoot({\n value,\n defaultValue,\n valueChangeAction,\n disabled: disabledProp,\n className,\n style,\n children,\n render,\n ...rest\n}: SelectRootProps) {\n const { ref: libraryRef, node: selectRef } = useSelectPartRef<HTMLSelectElement>(\n \"Select.Root\",\n \"select\",\n );\n // Inside a Field.Root (design/components/field-form.md 7.2) the Field owns the id and the ARIA\n // wiring, and `name` / `required` / `disabled` default from it.\n const field = useFieldControl({\n labelable: true,\n name: rest.name,\n disabled: disabledProp,\n required: rest.required,\n id: rest.id,\n component: \"Select.Root\",\n });\n const disabled = field.disabled;\n const rootRef = useMergedRef<HTMLSelectElement>(libraryRef, field.ref);\n\n const { optimistic, pending, dispatch, latestInFlight, adopt } = useControllableAction<\n string,\n SelectValueChangeDetails\n >({\n controlled: value,\n defaultValue,\n initialValue: \"\",\n action: valueChangeAction,\n transitionTypes: () => transitionTypes(\"select\"),\n warn: { component: \"Select.Root\", prop: \"value\" },\n });\n // Inside a Field: a value React writes with no event (a rejected action rolling back, a\n // controlled change) re-reads validity and `validate` after the commit.\n useFieldValueChange(optimistic);\n // Deliberately no warning when neither `value` nor `defaultValue` is given: the browser's\n // first-option default is adopted (design decision 3, product-owner decision 4).\n\n // Controlled: the mount-time value is the reset target (conventions 3.8 rule 6). Neither\n // `value` nor `defaultValue`: the value adopted at mount, chosen inside the hook.\n const [mountValue] = useState(value);\n const resetTarget = value === undefined ? defaultValue : (mountValue ?? value);\n\n // Any dispatch, a pick or a platform change, ends the adoption of the browser's default.\n const established = useRef(false);\n const dispatchChange = (next: string, details: SelectValueChangeDetails) => {\n established.current = true;\n dispatch(next, details);\n };\n\n const { optionMounted } = useNativeSelectValue({\n ref: selectRef,\n optimistic,\n latestInFlight,\n resetTarget,\n adoptDefault:\n value === undefined && defaultValue === undefined\n ? { adopt, established: () => established.current }\n : undefined,\n onPlatformChange: (next, event) =>\n dispatchChange(next, createActionDetails(event, { reason: \"platform\" })),\n });\n\n // Memoised (#48): every member is a state value, a prop or a stable callback.\n const context = useMemo<SelectContextValue>(\n () => ({ optimistic, pending, disabled, groupDisabled: false, optionMounted }),\n [optimistic, pending, disabled, optionMounted],\n );\n const state: SelectRootState = { value: optimistic, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"select\">, SelectRootState>({\n defaultElement: \"select\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...fieldInputProps(field),\n value: optimistic,\n disabled,\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onChange: (event: ChangeEvent<HTMLSelectElement>) => {\n // A natively disabled select fires no change; this covers `render` elements.\n if (disabled) return;\n const next = event.currentTarget.value;\n // No-op rule against the optimistic value (conventions 2.3, design 4.2).\n if (next === optimistic) return;\n dispatchChange(next, createActionDetails(event.nativeEvent, { reason: \"activate\" }));\n },\n },\n ref: rootRef,\n });\n\n return <SelectContext value={context}>{element}</SelectContext>;\n}\n\nSelectRoot.displayName = \"SelectRoot\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmGA,SAAgB,WAAW,EACzB,OACA,cACA,mBACA,UAAU,cACV,WACA,OACA,UACA,QACA,GAAG,QACe;CAClB,MAAM,EAAE,KAAK,YAAY,MAAM,cAAc,iBAC3C,eACA,QACF;CAGA,MAAM,QAAQ,gBAAgB;EAC5B,WAAW;EACX,MAAM,KAAK;EACX,UAAU;EACV,UAAU,KAAK;EACf,IAAI,KAAK;EACT,WAAW;CACb,CAAC;CACD,MAAM,WAAW,MAAM;CACvB,MAAM,UAAU,aAAgC,YAAY,MAAM,GAAG;CAErE,MAAM,EAAE,YAAY,SAAS,UAAU,gBAAgB,UAAU,sBAG/D;EACA,YAAY;EACZ;EACA,cAAc;EACd,QAAQ;EACR,uBAAuB,gBAAgB,QAAQ;EAC/C,MAAM;GAAE,WAAW;GAAe,MAAM;EAAQ;CAClD,CAAC;CAGD,oBAAoB,UAAU;CAM9B,MAAM,CAAC,cAAc,SAAS,KAAK;CACnC,MAAM,cAAc,UAAU,KAAA,IAAY,eAAgB,cAAc;CAGxE,MAAM,cAAc,OAAO,KAAK;CAChC,MAAM,kBAAkB,MAAc,YAAsC;EAC1E,YAAY,UAAU;EACtB,SAAS,MAAM,OAAO;CACxB;CAEA,MAAM,EAAE,kBAAkB,qBAAqB;EAC7C,KAAK;EACL;EACA;EACA;EACA,cACE,UAAU,KAAA,KAAa,iBAAiB,KAAA,IACpC;GAAE;GAAO,mBAAmB,YAAY;EAAQ,IAChD,KAAA;EACN,mBAAmB,MAAM,UACvB,eAAe,MAAM,oBAAoB,OAAO,EAAE,QAAQ,WAAW,CAAC,CAAC;CAC3E,CAAC;CAGD,MAAM,UAAU,eACP;EAAE;EAAY;EAAS;EAAU,eAAe;EAAO;CAAc,IAC5E;EAAC;EAAY;EAAS;EAAU;CAAa,CAC/C;CAGA,MAAM,UAAU,UAA4D;EAC1E,gBAAgB;EAChB;EACA,OAAA;GAL+B,OAAO;GAAY;GAAS;EAKvD;EACJ;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAG,gBAAgB,KAAK;GACxB,OAAO;GACP;GACA,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,WAAW,UAA0C;IAEnD,IAAI,UAAU;IACd,MAAM,OAAO,MAAM,cAAc;IAEjC,IAAI,SAAS,YAAY;IACzB,eAAe,MAAM,oBAAoB,MAAM,aAAa,EAAE,QAAQ,WAAW,CAAC,CAAC;GACrF;EACF;EACA,KAAK;CACP,CAAC;CAED,OAAO,oBAAC,eAAD;EAAe,OAAO;EAAU,UAAA;CAAuB,CAAA;AAChE;AAEA,WAAW,cAAc"}
@@ -0,0 +1,32 @@
1
+ import "../internal/platform-attributes.mjs";
2
+ import { SliderOrientation, SliderRootProps, SliderRootState, SliderValue, SliderValueChangeDetails, SliderValueCommitDetails } from "./slider-root.mjs";
3
+ import { SliderTrack, SliderTrackProps, SliderTrackState } from "./slider-track.mjs";
4
+ import { SliderIndicator, SliderIndicatorProps, SliderIndicatorState } from "./slider-indicator.mjs";
5
+ import { SliderLabel, SliderLabelProps } from "./slider-label.mjs";
6
+ import { SliderThumb, SliderThumbProps, SliderThumbState } from "./slider-thumb.mjs";
7
+ import { SliderValuePart, SliderValueProps, SliderValueState } from "./slider-value.mjs";
8
+ //#region src/slider/index.d.ts
9
+ /**
10
+ * Slider (WAI-ARIA APG Slider and Slider (Multi-Thumb) patterns): `Root` (`role="group"` with
11
+ * several thumbs), `Label`, `Track` (owns the pointer), `Indicator` (the fill), one `Thumb` per
12
+ * value (a styled element containing a visually hidden native `<input type="range">`), and
13
+ * `Value`. Two actions: `valueChangeAction` on every step (a transition; keep it cheap) and
14
+ * `valueCommitAction` once per gesture (the save; uncontrolled state is committed when it
15
+ * resolves and rolls back when it rejects).
16
+ */
17
+ export declare const Slider: {
18
+ readonly Root: {
19
+ (props: SliderRootProps<number>): import("react").ReactNode;
20
+ (props: SliderRootProps<readonly number[]>): import("react").ReactNode;
21
+ (props: SliderRootProps<SliderValue>): import("react").ReactNode;
22
+ displayName?: string;
23
+ };
24
+ readonly Label: typeof SliderLabel;
25
+ readonly Track: typeof SliderTrack;
26
+ readonly Indicator: typeof SliderIndicator;
27
+ readonly Thumb: typeof SliderThumb;
28
+ readonly Value: typeof SliderValuePart;
29
+ };
30
+ //#endregion
31
+ export type { SliderIndicatorProps, SliderIndicatorState, SliderLabelProps, SliderOrientation, SliderRootProps, SliderRootState, SliderThumbProps, SliderThumbState, SliderTrackProps, SliderTrackState, SliderValue, SliderValueChangeDetails, SliderValueCommitDetails, SliderValueProps, SliderValueState };
32
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":["_$__slider_root_js0.SliderRootProps","_$__slider_root_js0.SliderValue"],"sources":["../../src/slider/index.ts"],"mappings":";;;;;;;;;;;;;;;;qBAkBa;WACX;K,OADWA,0C;;;;;WAEX,cAAK;WACL,cAAK;WACL,kBAAS;WACT,cAAK;WACL,cAAK"}