@funstack/ui 0.0.0-stage → 0.1.0-alpha.1

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 (299) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -2
  3. package/dist/accordion/accordion-context.d.mts +5 -0
  4. package/dist/accordion/accordion-context.d.mts.map +1 -0
  5. package/dist/accordion/accordion-context.mjs +9 -0
  6. package/dist/accordion/accordion-context.mjs.map +1 -0
  7. package/dist/accordion/accordion-item.d.mts +53 -0
  8. package/dist/accordion/accordion-item.d.mts.map +1 -0
  9. package/dist/accordion/accordion-item.mjs +85 -0
  10. package/dist/accordion/accordion-item.mjs.map +1 -0
  11. package/dist/accordion/accordion-panel.d.mts +40 -0
  12. package/dist/accordion/accordion-panel.d.mts.map +1 -0
  13. package/dist/accordion/accordion-panel.mjs +40 -0
  14. package/dist/accordion/accordion-panel.mjs.map +1 -0
  15. package/dist/accordion/accordion-root.d.mts +90 -0
  16. package/dist/accordion/accordion-root.d.mts.map +1 -0
  17. package/dist/accordion/accordion-root.mjs +229 -0
  18. package/dist/accordion/accordion-root.mjs.map +1 -0
  19. package/dist/accordion/accordion-trigger.d.mts +37 -0
  20. package/dist/accordion/accordion-trigger.d.mts.map +1 -0
  21. package/dist/accordion/accordion-trigger.mjs +81 -0
  22. package/dist/accordion/accordion-trigger.mjs.map +1 -0
  23. package/dist/accordion/index.d.mts +20 -0
  24. package/dist/accordion/index.d.mts.map +1 -0
  25. package/dist/accordion/index.mjs +20 -0
  26. package/dist/accordion/index.mjs.map +1 -0
  27. package/dist/checkbox/checkbox.d.mts +92 -0
  28. package/dist/checkbox/checkbox.d.mts.map +1 -0
  29. package/dist/checkbox/checkbox.mjs +82 -0
  30. package/dist/checkbox/checkbox.mjs.map +1 -0
  31. package/dist/checkbox/index.d.mts +3 -0
  32. package/dist/checkbox/index.mjs +1 -0
  33. package/dist/checkbox-group/checkbox-group-context.mjs +24 -0
  34. package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -0
  35. package/dist/checkbox-group/checkbox-group-item.d.mts +55 -0
  36. package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -0
  37. package/dist/checkbox-group/checkbox-group-item.mjs +90 -0
  38. package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -0
  39. package/dist/checkbox-group/checkbox-group-label.d.mts +21 -0
  40. package/dist/checkbox-group/checkbox-group-label.d.mts.map +1 -0
  41. package/dist/checkbox-group/checkbox-group-label.mjs +30 -0
  42. package/dist/checkbox-group/checkbox-group-label.mjs.map +1 -0
  43. package/dist/checkbox-group/checkbox-group-parent.d.mts +68 -0
  44. package/dist/checkbox-group/checkbox-group-parent.d.mts.map +1 -0
  45. package/dist/checkbox-group/checkbox-group-parent.mjs +145 -0
  46. package/dist/checkbox-group/checkbox-group-parent.mjs.map +1 -0
  47. package/dist/checkbox-group/checkbox-group-root.d.mts +100 -0
  48. package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -0
  49. package/dist/checkbox-group/checkbox-group-root.mjs +291 -0
  50. package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -0
  51. package/dist/checkbox-group/index.d.mts +23 -0
  52. package/dist/checkbox-group/index.d.mts.map +1 -0
  53. package/dist/checkbox-group/index.mjs +23 -0
  54. package/dist/checkbox-group/index.mjs.map +1 -0
  55. package/dist/dialog/dialog-close.d.mts +44 -0
  56. package/dist/dialog/dialog-close.d.mts.map +1 -0
  57. package/dist/dialog/dialog-close.mjs +76 -0
  58. package/dist/dialog/dialog-close.mjs.map +1 -0
  59. package/dist/dialog/dialog-context.mjs +13 -0
  60. package/dist/dialog/dialog-context.mjs.map +1 -0
  61. package/dist/dialog/dialog-description.d.mts +22 -0
  62. package/dist/dialog/dialog-description.d.mts.map +1 -0
  63. package/dist/dialog/dialog-description.mjs +31 -0
  64. package/dist/dialog/dialog-description.mjs.map +1 -0
  65. package/dist/dialog/dialog-form.d.mts +58 -0
  66. package/dist/dialog/dialog-form.d.mts.map +1 -0
  67. package/dist/dialog/dialog-form.mjs +108 -0
  68. package/dist/dialog/dialog-form.mjs.map +1 -0
  69. package/dist/dialog/dialog-popup.d.mts +81 -0
  70. package/dist/dialog/dialog-popup.d.mts.map +1 -0
  71. package/dist/dialog/dialog-popup.mjs +367 -0
  72. package/dist/dialog/dialog-popup.mjs.map +1 -0
  73. package/dist/dialog/dialog-root.d.mts +70 -0
  74. package/dist/dialog/dialog-root.d.mts.map +1 -0
  75. package/dist/dialog/dialog-root.mjs +113 -0
  76. package/dist/dialog/dialog-root.mjs.map +1 -0
  77. package/dist/dialog/dialog-title.d.mts +23 -0
  78. package/dist/dialog/dialog-title.d.mts.map +1 -0
  79. package/dist/dialog/dialog-title.mjs +31 -0
  80. package/dist/dialog/dialog-title.mjs.map +1 -0
  81. package/dist/dialog/dialog-trigger.d.mts +39 -0
  82. package/dist/dialog/dialog-trigger.d.mts.map +1 -0
  83. package/dist/dialog/dialog-trigger.mjs +80 -0
  84. package/dist/dialog/dialog-trigger.mjs.map +1 -0
  85. package/dist/dialog/index.d.mts +28 -0
  86. package/dist/dialog/index.d.mts.map +1 -0
  87. package/dist/dialog/index.mjs +28 -0
  88. package/dist/dialog/index.mjs.map +1 -0
  89. package/dist/index.d.mts +60 -0
  90. package/dist/index.mjs +12 -0
  91. package/dist/internal/action-details.mjs +47 -0
  92. package/dist/internal/action-details.mjs.map +1 -0
  93. package/dist/internal/anchor-position.d.mts +7 -0
  94. package/dist/internal/anchor-position.d.mts.map +1 -0
  95. package/dist/internal/anchor-position.mjs +16 -0
  96. package/dist/internal/anchor-position.mjs.map +1 -0
  97. package/dist/internal/data-attr.mjs +13 -0
  98. package/dist/internal/data-attr.mjs.map +1 -0
  99. package/dist/internal/merge-props.mjs +119 -0
  100. package/dist/internal/merge-props.mjs.map +1 -0
  101. package/dist/internal/platform-attributes.d.mts +55 -0
  102. package/dist/internal/platform-attributes.d.mts.map +1 -0
  103. package/dist/internal/sync-presence.mjs +19 -0
  104. package/dist/internal/sync-presence.mjs.map +1 -0
  105. package/dist/internal/transition-boundary.mjs +52 -0
  106. package/dist/internal/transition-boundary.mjs.map +1 -0
  107. package/dist/internal/transition-types.mjs +15 -0
  108. package/dist/internal/transition-types.mjs.map +1 -0
  109. package/dist/internal/types.d.mts +38 -0
  110. package/dist/internal/types.d.mts.map +1 -0
  111. package/dist/internal/use-action-trigger.mjs +58 -0
  112. package/dist/internal/use-action-trigger.mjs.map +1 -0
  113. package/dist/internal/use-controllable-action.mjs +115 -0
  114. package/dist/internal/use-controllable-action.mjs.map +1 -0
  115. package/dist/internal/use-delayed-pair.mjs +40 -0
  116. package/dist/internal/use-delayed-pair.mjs.map +1 -0
  117. package/dist/internal/use-dev-warning.mjs +21 -0
  118. package/dist/internal/use-dev-warning.mjs.map +1 -0
  119. package/dist/internal/use-exit-animation.mjs +55 -0
  120. package/dist/internal/use-exit-animation.mjs.map +1 -0
  121. package/dist/internal/use-form-reset.mjs +50 -0
  122. package/dist/internal/use-form-reset.mjs.map +1 -0
  123. package/dist/internal/use-native-checked.mjs +113 -0
  124. package/dist/internal/use-native-checked.mjs.map +1 -0
  125. package/dist/internal/use-native-group-reconciliation.mjs +64 -0
  126. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -0
  127. package/dist/internal/use-popover-popup.mjs +274 -0
  128. package/dist/internal/use-popover-popup.mjs.map +1 -0
  129. package/dist/internal/use-popover-root.d.mts +2 -0
  130. package/dist/internal/use-popover-root.mjs +112 -0
  131. package/dist/internal/use-popover-root.mjs.map +1 -0
  132. package/dist/internal/use-popover-trigger.mjs +86 -0
  133. package/dist/internal/use-popover-trigger.mjs.map +1 -0
  134. package/dist/internal/use-render.mjs +51 -0
  135. package/dist/internal/use-render.mjs.map +1 -0
  136. package/dist/internal/use-until-found.mjs +40 -0
  137. package/dist/internal/use-until-found.mjs.map +1 -0
  138. package/dist/menu/index.d.mts +34 -0
  139. package/dist/menu/index.d.mts.map +1 -0
  140. package/dist/menu/index.mjs +34 -0
  141. package/dist/menu/index.mjs.map +1 -0
  142. package/dist/menu/menu-checkbox-item.d.mts +42 -0
  143. package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
  144. package/dist/menu/menu-checkbox-item.mjs +71 -0
  145. package/dist/menu/menu-checkbox-item.mjs.map +1 -0
  146. package/dist/menu/menu-context.d.mts +1 -0
  147. package/dist/menu/menu-context.mjs +28 -0
  148. package/dist/menu/menu-context.mjs.map +1 -0
  149. package/dist/menu/menu-dom.mjs +37 -0
  150. package/dist/menu/menu-dom.mjs.map +1 -0
  151. package/dist/menu/menu-group.d.mts +48 -0
  152. package/dist/menu/menu-group.d.mts.map +1 -0
  153. package/dist/menu/menu-group.mjs +69 -0
  154. package/dist/menu/menu-group.mjs.map +1 -0
  155. package/dist/menu/menu-hover.mjs +29 -0
  156. package/dist/menu/menu-hover.mjs.map +1 -0
  157. package/dist/menu/menu-item.d.mts +45 -0
  158. package/dist/menu/menu-item.d.mts.map +1 -0
  159. package/dist/menu/menu-item.mjs +54 -0
  160. package/dist/menu/menu-item.mjs.map +1 -0
  161. package/dist/menu/menu-popup.d.mts +69 -0
  162. package/dist/menu/menu-popup.d.mts.map +1 -0
  163. package/dist/menu/menu-popup.mjs +207 -0
  164. package/dist/menu/menu-popup.mjs.map +1 -0
  165. package/dist/menu/menu-radio-group.d.mts +37 -0
  166. package/dist/menu/menu-radio-group.d.mts.map +1 -0
  167. package/dist/menu/menu-radio-group.mjs +72 -0
  168. package/dist/menu/menu-radio-group.mjs.map +1 -0
  169. package/dist/menu/menu-radio-item.d.mts +33 -0
  170. package/dist/menu/menu-radio-item.d.mts.map +1 -0
  171. package/dist/menu/menu-radio-item.mjs +62 -0
  172. package/dist/menu/menu-radio-item.mjs.map +1 -0
  173. package/dist/menu/menu-root.d.mts +54 -0
  174. package/dist/menu/menu-root.d.mts.map +1 -0
  175. package/dist/menu/menu-root.mjs +102 -0
  176. package/dist/menu/menu-root.mjs.map +1 -0
  177. package/dist/menu/menu-submenu-trigger.d.mts +31 -0
  178. package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
  179. package/dist/menu/menu-submenu-trigger.mjs +92 -0
  180. package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
  181. package/dist/menu/menu-trigger.d.mts +36 -0
  182. package/dist/menu/menu-trigger.d.mts.map +1 -0
  183. package/dist/menu/menu-trigger.mjs +81 -0
  184. package/dist/menu/menu-trigger.mjs.map +1 -0
  185. package/dist/menu/use-menu-item.mjs +54 -0
  186. package/dist/menu/use-menu-item.mjs.map +1 -0
  187. package/dist/popover/index.d.mts +28 -0
  188. package/dist/popover/index.d.mts.map +1 -0
  189. package/dist/popover/index.mjs +28 -0
  190. package/dist/popover/index.mjs.map +1 -0
  191. package/dist/popover/popover-close.d.mts +41 -0
  192. package/dist/popover/popover-close.d.mts.map +1 -0
  193. package/dist/popover/popover-close.mjs +90 -0
  194. package/dist/popover/popover-close.mjs.map +1 -0
  195. package/dist/popover/popover-context.mjs +26 -0
  196. package/dist/popover/popover-context.mjs.map +1 -0
  197. package/dist/popover/popover-description.d.mts +22 -0
  198. package/dist/popover/popover-description.d.mts.map +1 -0
  199. package/dist/popover/popover-description.mjs +28 -0
  200. package/dist/popover/popover-description.mjs.map +1 -0
  201. package/dist/popover/popover-popup.d.mts +82 -0
  202. package/dist/popover/popover-popup.d.mts.map +1 -0
  203. package/dist/popover/popover-popup.mjs +93 -0
  204. package/dist/popover/popover-popup.mjs.map +1 -0
  205. package/dist/popover/popover-root.d.mts +64 -0
  206. package/dist/popover/popover-root.d.mts.map +1 -0
  207. package/dist/popover/popover-root.mjs +39 -0
  208. package/dist/popover/popover-root.mjs.map +1 -0
  209. package/dist/popover/popover-title.d.mts +23 -0
  210. package/dist/popover/popover-title.d.mts.map +1 -0
  211. package/dist/popover/popover-title.mjs +28 -0
  212. package/dist/popover/popover-title.mjs.map +1 -0
  213. package/dist/popover/popover-trigger.d.mts +37 -0
  214. package/dist/popover/popover-trigger.d.mts.map +1 -0
  215. package/dist/popover/popover-trigger.mjs +40 -0
  216. package/dist/popover/popover-trigger.mjs.map +1 -0
  217. package/dist/radio-group/index.d.mts +20 -0
  218. package/dist/radio-group/index.d.mts.map +1 -0
  219. package/dist/radio-group/index.mjs +20 -0
  220. package/dist/radio-group/index.mjs.map +1 -0
  221. package/dist/radio-group/radio-group-context.mjs +13 -0
  222. package/dist/radio-group/radio-group-context.mjs.map +1 -0
  223. package/dist/radio-group/radio-group-item.d.mts +54 -0
  224. package/dist/radio-group/radio-group-item.d.mts.map +1 -0
  225. package/dist/radio-group/radio-group-item.mjs +83 -0
  226. package/dist/radio-group/radio-group-item.mjs.map +1 -0
  227. package/dist/radio-group/radio-group-label.d.mts +21 -0
  228. package/dist/radio-group/radio-group-label.d.mts.map +1 -0
  229. package/dist/radio-group/radio-group-label.mjs +30 -0
  230. package/dist/radio-group/radio-group-label.mjs.map +1 -0
  231. package/dist/radio-group/radio-group-root.d.mts +92 -0
  232. package/dist/radio-group/radio-group-root.d.mts.map +1 -0
  233. package/dist/radio-group/radio-group-root.mjs +137 -0
  234. package/dist/radio-group/radio-group-root.mjs.map +1 -0
  235. package/dist/switch/index.d.mts +3 -0
  236. package/dist/switch/index.mjs +1 -0
  237. package/dist/switch/switch.d.mts +78 -0
  238. package/dist/switch/switch.d.mts.map +1 -0
  239. package/dist/switch/switch.mjs +77 -0
  240. package/dist/switch/switch.mjs.map +1 -0
  241. package/dist/tabs/index.d.mts +24 -0
  242. package/dist/tabs/index.d.mts.map +1 -0
  243. package/dist/tabs/index.mjs +23 -0
  244. package/dist/tabs/index.mjs.map +1 -0
  245. package/dist/tabs/tabs-context.d.mts +7 -0
  246. package/dist/tabs/tabs-context.d.mts.map +1 -0
  247. package/dist/tabs/tabs-context.mjs +14 -0
  248. package/dist/tabs/tabs-context.mjs.map +1 -0
  249. package/dist/tabs/tabs-ids.mjs +39 -0
  250. package/dist/tabs/tabs-ids.mjs.map +1 -0
  251. package/dist/tabs/tabs-indicator.d.mts +32 -0
  252. package/dist/tabs/tabs-indicator.d.mts.map +1 -0
  253. package/dist/tabs/tabs-indicator.mjs +49 -0
  254. package/dist/tabs/tabs-indicator.mjs.map +1 -0
  255. package/dist/tabs/tabs-list.d.mts +34 -0
  256. package/dist/tabs/tabs-list.d.mts.map +1 -0
  257. package/dist/tabs/tabs-list.mjs +130 -0
  258. package/dist/tabs/tabs-list.mjs.map +1 -0
  259. package/dist/tabs/tabs-panel.d.mts +50 -0
  260. package/dist/tabs/tabs-panel.d.mts.map +1 -0
  261. package/dist/tabs/tabs-panel.mjs +81 -0
  262. package/dist/tabs/tabs-panel.mjs.map +1 -0
  263. package/dist/tabs/tabs-root.d.mts +64 -0
  264. package/dist/tabs/tabs-root.d.mts.map +1 -0
  265. package/dist/tabs/tabs-root.mjs +90 -0
  266. package/dist/tabs/tabs-root.mjs.map +1 -0
  267. package/dist/tabs/tabs-tab.d.mts +49 -0
  268. package/dist/tabs/tabs-tab.d.mts.map +1 -0
  269. package/dist/tabs/tabs-tab.mjs +89 -0
  270. package/dist/tabs/tabs-tab.mjs.map +1 -0
  271. package/dist/toggle/index.d.mts +3 -0
  272. package/dist/toggle/index.mjs +1 -0
  273. package/dist/toggle/toggle.d.mts +57 -0
  274. package/dist/toggle/toggle.d.mts.map +1 -0
  275. package/dist/toggle/toggle.mjs +59 -0
  276. package/dist/toggle/toggle.mjs.map +1 -0
  277. package/dist/tooltip/index.d.mts +20 -0
  278. package/dist/tooltip/index.d.mts.map +1 -0
  279. package/dist/tooltip/index.mjs +19 -0
  280. package/dist/tooltip/index.mjs.map +1 -0
  281. package/dist/tooltip/tooltip-context.d.mts +5 -0
  282. package/dist/tooltip/tooltip-context.d.mts.map +1 -0
  283. package/dist/tooltip/tooltip-context.mjs +13 -0
  284. package/dist/tooltip/tooltip-context.mjs.map +1 -0
  285. package/dist/tooltip/tooltip-popup.d.mts +49 -0
  286. package/dist/tooltip/tooltip-popup.d.mts.map +1 -0
  287. package/dist/tooltip/tooltip-popup.mjs +52 -0
  288. package/dist/tooltip/tooltip-popup.mjs.map +1 -0
  289. package/dist/tooltip/tooltip-root.d.mts +41 -0
  290. package/dist/tooltip/tooltip-root.d.mts.map +1 -0
  291. package/dist/tooltip/tooltip-root.mjs +86 -0
  292. package/dist/tooltip/tooltip-root.mjs.map +1 -0
  293. package/dist/tooltip/tooltip-trigger.d.mts +38 -0
  294. package/dist/tooltip/tooltip-trigger.d.mts.map +1 -0
  295. package/dist/tooltip/tooltip-trigger.mjs +55 -0
  296. package/dist/tooltip/tooltip-trigger.mjs.map +1 -0
  297. package/dist/tooltip/use-tooltip-interaction.mjs +119 -0
  298. package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -0
  299. package/package.json +73 -3
@@ -0,0 +1,93 @@
1
+ "use client";
2
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
+ import { resolveStateValue, useRender } from "../internal/use-render.mjs";
4
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
5
+ import { POSITION_TRY_FALLBACKS, positionArea } from "../internal/anchor-position.mjs";
6
+ import { PopoverPopupContext, usePopoverContext } from "./popover-context.mjs";
7
+ import { usePopoverPopup } from "../internal/use-popover-popup.mjs";
8
+ import { Activity } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ //#region src/popover/popover-popup.tsx
11
+ /**
12
+ * The popover itself: a `<dialog popover="auto" aria-modal="false" role="dialog">` with the id
13
+ * the Trigger's `commandfor` names, placed against the Trigger with CSS Anchor Positioning and
14
+ * wired to Title and Description through `aria-labelledby` / `aria-describedby`. Style it with
15
+ * `:popover-open`; it emits `data-side` / `data-align` but no `data-open`.
16
+ *
17
+ * In library mode the children render from committed state, so content that suspends keeps the
18
+ * popover closed (and the Trigger pending) until it is ready; `showPopover({ source: trigger })`
19
+ * runs in the layout effect of the commit that mounted them, and a library-driven close runs
20
+ * `hidePopover()` in the commit that ends it. Dismissals are the browser's: the native `toggle`
21
+ * event becomes `openChangeAction(false, { reason: "dismiss" })`.
22
+ *
23
+ * Owned keys (conventions 1.2): `id`, `popover`, `open`, `aria-modal`, `aria-labelledby` and
24
+ * `aria-describedby` (token-merged), and `data-side` / `data-align` unless `side` is `null`.
25
+ * `role` is a default (`"dialog"`) the consumer may override.
26
+ */
27
+ function PopoverPopup({ side = "bottom", align = "center", keepMounted, initialFocus, transition, className, style, children, render, ...rest }) {
28
+ const ctx = usePopoverContext("Popover.Popup");
29
+ const isLibrary = ctx.mode === "library";
30
+ const { ids } = ctx;
31
+ useDevWarning(!isLibrary && transition !== void 0, "Popover.Popup: `transition` has no effect in JS-free mode; the browser opens and closes the popover outside any React transition. Animate it with CSS (`@starting-style`).");
32
+ useDevWarning(!isLibrary && keepMounted === false, "Popover.Popup: `keepMounted={false}` cannot be honoured in JS-free mode; the content is always mounted so that the server HTML is complete.");
33
+ const { setElement, visible, wrapContent } = usePopoverPopup(ctx, {
34
+ part: "Popover.Popup",
35
+ initialFocus,
36
+ keepMounted,
37
+ transition: isLibrary ? transition : void 0
38
+ });
39
+ const state = {
40
+ open: ctx.committed,
41
+ side,
42
+ align
43
+ };
44
+ const content = (s) => {
45
+ let node;
46
+ if (!isLibrary) node = resolveStateValue(children, s);
47
+ else if (keepMounted === true) node = /* @__PURE__ */ jsx(Activity, {
48
+ mode: visible ? "visible" : "hidden",
49
+ children: wrapContent(resolveStateValue(children, s))
50
+ });
51
+ else node = visible ? wrapContent(resolveStateValue(children, s)) : null;
52
+ return /* @__PURE__ */ jsx(PopoverPopupContext, {
53
+ value: s,
54
+ children: node
55
+ });
56
+ };
57
+ const libraryProps = {
58
+ id: ids.popup,
59
+ popover: "auto",
60
+ open: void 0,
61
+ "aria-modal": "false",
62
+ "aria-labelledby": ids.title,
63
+ "aria-describedby": ids.description,
64
+ ...side !== null && {
65
+ "data-side": side,
66
+ "data-align": align
67
+ }
68
+ };
69
+ const element = useRender({
70
+ defaultElement: "dialog",
71
+ render,
72
+ state,
73
+ className,
74
+ style: side === null ? style : (s) => ({
75
+ positionArea: positionArea(side, align),
76
+ positionTryFallbacks: POSITION_TRY_FALLBACKS,
77
+ ...resolveStateValue(style, s)
78
+ }),
79
+ children: content,
80
+ props: {
81
+ role: "dialog",
82
+ ...rest
83
+ },
84
+ libraryProps,
85
+ ref: setElement
86
+ });
87
+ return useTransitionBoundary("Popover.Popup", isLibrary ? transition : void 0, element);
88
+ }
89
+ PopoverPopup.displayName = "PopoverPopup";
90
+ //#endregion
91
+ export { PopoverPopup };
92
+
93
+ //# sourceMappingURL=popover-popup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-popup.mjs","names":[],"sources":["../../src/popover/popover-popup.tsx"],"sourcesContent":["\"use client\";\nimport { Activity } from \"react\";\nimport type {\n ComponentPropsWithRef,\n CSSProperties,\n ReactNode,\n RefObject,\n ViewTransitionClass,\n} from \"react\";\nimport { POSITION_TRY_FALLBACKS, positionArea } from \"../internal/anchor-position.js\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { usePopoverPopup } from \"../internal/use-popover-popup.js\";\nimport { resolveStateValue, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { PopoverPopupContext, usePopoverContext } from \"./popover-context.js\";\n\nexport type PopoverSide = \"top\" | \"bottom\" | \"left\" | \"right\";\nexport type PopoverAlign = \"start\" | \"center\" | \"end\";\n\nexport interface PopoverPopupState {\n /** Committed open state (library mode); `false` in JS-free mode. Read `:popover-open` for the DOM truth. */\n readonly open: boolean;\n readonly side: PopoverSide | null;\n readonly align: PopoverAlign;\n}\n\nexport interface PopoverPopupProps extends Omit<\n ComponentPropsWithRef<\"dialog\">,\n | \"id\"\n | \"popover\"\n | \"open\"\n | \"aria-modal\"\n | \"onToggle\"\n | \"onBeforeToggle\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /**\n * Placement relative to the Trigger through inline `position-area`, with\n * `position-try-fallbacks` flipping it when it does not fit. Default `\"bottom\"`. `null` emits\n * no inline positioning (and no `data-side` / `data-align`), so a stylesheet owns placement.\n */\n side?: PopoverSide | null;\n /** Alignment along the side. Default `\"center\"`. Ignored when `side` is `null`. */\n align?: PopoverAlign;\n /**\n * Library mode: what happens to the children while the popover is closed.\n * - `false` (default): not rendered. Mounting them is part of the opening transition, so\n * content that suspends holds the open until it is ready. Unmount waits for the popover's\n * exit animation (CSS), or happens in the close commit when `transition` is set.\n * - `true`: rendered inside `<Activity mode=\"hidden\">`: DOM and state preserved, effects\n * stopped, pre-rendered at low priority. Not in the server HTML.\n *\n * Ignored in JS-free mode (always mounted).\n */\n keepMounted?: boolean;\n /**\n * Element to focus when the popover opens: a ref, or a selector resolved inside the popup.\n * The library writes `autofocus` on it right before `showPopover()` and the platform focuses\n * it. Default: the platform's choice for a `<dialog>` (first focusable descendant; the popup\n * itself if none); for `render={<div />}` focus stays on the Trigger.\n *\n * In JS-free mode the browser opens the popover itself, so the attribute is written after\n * hydration and kept while mounted; before hydration only `autoFocus` in the markup works.\n */\n initialFocus?: RefObject<HTMLElement | null> | string;\n /**\n * Library mode only. Forwarded to the `<ViewTransition default>` around the popover element\n * itself. Animates the opening commit, content changes while open, and every library-driven\n * close (Trigger, Close, controlled `open={false}`), in all engines; dismissals (Escape,\n * click outside) are the browser's and animate with CSS only. Ignored (dev warning) in JS-free\n * mode.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. A Root inserted by a transition with\n * `transition` set on its Popup pays the page cross-fade (issue #35); a plain open does not,\n * because the children mount under the already-mounted popover element.\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, PopoverPopupState>;\n style?: StateValue<CSSProperties | undefined, PopoverPopupState>;\n children?: StateValue<ReactNode, PopoverPopupState>;\n /** A `<dialog>` (default) or a `<div>` (focus stays on the Trigger). */\n render?: RenderProp<ComponentPropsWithRef<\"dialog\">, PopoverPopupState>;\n}\n\n/**\n * The popover itself: a `<dialog popover=\"auto\" aria-modal=\"false\" role=\"dialog\">` with the id\n * the Trigger's `commandfor` names, placed against the Trigger with CSS Anchor Positioning and\n * wired to Title and Description through `aria-labelledby` / `aria-describedby`. Style it with\n * `:popover-open`; it emits `data-side` / `data-align` but no `data-open`.\n *\n * In library mode the children render from committed state, so content that suspends keeps the\n * popover closed (and the Trigger pending) until it is ready; `showPopover({ source: trigger })`\n * runs in the layout effect of the commit that mounted them, and a library-driven close runs\n * `hidePopover()` in the commit that ends it. Dismissals are the browser's: the native `toggle`\n * event becomes `openChangeAction(false, { reason: \"dismiss\" })`.\n *\n * Owned keys (conventions 1.2): `id`, `popover`, `open`, `aria-modal`, `aria-labelledby` and\n * `aria-describedby` (token-merged), and `data-side` / `data-align` unless `side` is `null`.\n * `role` is a default (`\"dialog\"`) the consumer may override.\n */\nexport function PopoverPopup({\n side = \"bottom\",\n align = \"center\",\n keepMounted,\n initialFocus,\n transition,\n className,\n style,\n children,\n render,\n ...rest\n}: PopoverPopupProps) {\n const ctx = usePopoverContext(\"Popover.Popup\");\n const isLibrary = ctx.mode === \"library\";\n const { ids } = ctx;\n\n useDevWarning(\n !isLibrary && transition !== undefined,\n \"Popover.Popup: `transition` has no effect in JS-free mode; the browser opens and closes the \" +\n \"popover outside any React transition. Animate it with CSS (`@starting-style`).\",\n );\n useDevWarning(\n !isLibrary && keepMounted === false,\n \"Popover.Popup: `keepMounted={false}` cannot be honoured in JS-free mode; the content is \" +\n \"always mounted so that the server HTML is complete.\",\n );\n\n const { setElement, visible, wrapContent } = usePopoverPopup(ctx, {\n part: \"Popover.Popup\",\n initialFocus,\n keepMounted,\n transition: isLibrary ? transition : undefined,\n });\n\n const state: PopoverPopupState = { open: ctx.committed, side, align };\n\n const content = (s: PopoverPopupState): ReactNode => {\n let node: ReactNode;\n if (!isLibrary) {\n node = resolveStateValue(children, s);\n } else if (keepMounted === true) {\n // The mode changes with committed state, inside the Root's transition (conventions 5.5);\n // it stays visible while an exit animation runs.\n node = (\n <Activity mode={visible ? \"visible\" : \"hidden\"}>\n {wrapContent(resolveStateValue(children, s))}\n </Activity>\n );\n } else {\n node = visible ? wrapContent(resolveStateValue(children, s)) : null;\n }\n return <PopoverPopupContext value={s}>{node}</PopoverPopupContext>;\n };\n\n const libraryProps: ComponentPropsWithRef<\"dialog\"> & DataAttributes = {\n id: ids.popup,\n popover: \"auto\",\n // Never rendered: `showPopover()` does not set it, and an `open` attribute would show the\n // <dialog> outside the top layer. Owned so a `render` element cannot add it.\n open: undefined,\n // Chromium exposes a <dialog popover> as modal without it (research; issue #44).\n \"aria-modal\": \"false\",\n \"aria-labelledby\": ids.title,\n \"aria-describedby\": ids.description,\n // Not owned with `side={null}`: the stylesheet (or a render element) may set them.\n ...(side !== null && { \"data-side\": side, \"data-align\": align }),\n };\n\n const element = useRender<ComponentPropsWithRef<\"dialog\">, PopoverPopupState>({\n defaultElement: \"dialog\",\n render,\n state,\n className,\n // The inline placement sits under the consumer's style: the consumer wins (design 8).\n style:\n side === null\n ? style\n : (s) => ({\n positionArea: positionArea(side, align),\n positionTryFallbacks: POSITION_TRY_FALLBACKS,\n ...resolveStateValue(style, s),\n }),\n children: content,\n // `role` is a default the consumer's `rest` overrides (design 3.3): WebKit implements no\n // minimum role for `[popover]`, and a `<div>` popup needs it.\n props: { role: \"dialog\", ...rest },\n libraryProps,\n ref: setElement,\n });\n\n return useTransitionBoundary(\"Popover.Popup\", isLibrary ? transition : undefined, element);\n}\n\nPopoverPopup.displayName = \"PopoverPopup\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAyGA,SAAgB,aAAa,EAC3B,OAAO,UACP,QAAQ,UACR,aACA,cACA,YACA,WACA,OACA,UACA,QACA,GAAG,QACiB;CACpB,MAAM,MAAM,kBAAkB,eAAe;CAC7C,MAAM,YAAY,IAAI,SAAS;CAC/B,MAAM,EAAE,QAAQ;CAEhB,cACE,CAAC,aAAa,eAAe,KAAA,GAC7B,4KAEF;CACA,cACE,CAAC,aAAa,gBAAgB,OAC9B,6IAEF;CAEA,MAAM,EAAE,YAAY,SAAS,gBAAgB,gBAAgB,KAAK;EAChE,MAAM;EACN;EACA;EACA,YAAY,YAAY,aAAa,KAAA;CACvC,CAAC;CAED,MAAM,QAA2B;EAAE,MAAM,IAAI;EAAW;EAAM;CAAM;CAEpE,MAAM,WAAW,MAAoC;EACnD,IAAI;EACJ,IAAI,CAAC,WACH,OAAO,kBAAkB,UAAU,CAAC;OAC/B,IAAI,gBAAgB,MAGzB,OACE,oBAAC,UAAD;GAAU,MAAM,UAAU,YAAY;GACnC,UAAA,YAAY,kBAAkB,UAAU,CAAC,CAAC;EACnC,CAAA;OAGZ,OAAO,UAAU,YAAY,kBAAkB,UAAU,CAAC,CAAC,IAAI;EAEjE,OAAO,oBAAC,qBAAD;GAAqB,OAAO;GAAI,UAAA;EAA0B,CAAA;CACnE;CAEA,MAAM,eAAiE;EACrE,IAAI,IAAI;EACR,SAAS;EAGT,MAAM,KAAA;EAEN,cAAc;EACd,mBAAmB,IAAI;EACvB,oBAAoB,IAAI;EAExB,GAAI,SAAS,QAAQ;GAAE,aAAa;GAAM,cAAc;EAAM;CAChE;CAEA,MAAM,UAAU,UAA8D;EAC5E,gBAAgB;EAChB;EACA;EACA;EAEA,OACE,SAAS,OACL,SACC,OAAO;GACN,cAAc,aAAa,MAAM,KAAK;GACtC,sBAAsB;GACtB,GAAG,kBAAkB,OAAO,CAAC;EAC/B;EACN,UAAU;EAGV,OAAO;GAAE,MAAM;GAAU,GAAG;EAAK;EACjC;EACA,KAAK;CACP,CAAC;CAED,OAAO,sBAAsB,iBAAiB,YAAY,aAAa,KAAA,GAAW,OAAO;AAC3F;AAEA,aAAa,cAAc"}
@@ -0,0 +1,64 @@
1
+ import { ActionDetails, ChangeAction, ChangeReason, StateValue } from "../internal/types.mjs";
2
+ import { ReactNode } from "react";
3
+ //#region src/popover/popover-root.d.ts
4
+ /** Details passed as the second argument of `openChangeAction`. */
5
+ export interface PopoverOpenChangeDetails extends ActionDetails {
6
+ /**
7
+ * `"activate"`: the user acted on a part: Trigger (open or close), Close, or a foreign invoker
8
+ * (`details.event` is a `CommandEvent` / `ToggleEvent` then).
9
+ * `"dismiss"`: the user closed the popover without a part: Escape, Android back, an assistive-
10
+ * technology dismiss gesture, a click outside; or script / another top-layer element hid it.
11
+ * `"platform"`: the popover was found open on mount (opened before hydration); `event` is
12
+ * `undefined`.
13
+ */
14
+ readonly reason: ChangeReason;
15
+ }
16
+ export interface PopoverRootState {
17
+ /** Optimistic open state (`false` in JS-free mode). Content rendered from it must not suspend. */
18
+ readonly open: boolean;
19
+ /** An `openChangeAction` dispatched through this Popover is in flight (library mode only). */
20
+ readonly pending: boolean;
21
+ }
22
+ export interface PopoverRootProps {
23
+ /**
24
+ * Controlled open state. `undefined` means uncontrolled (and, with `defaultOpen` and
25
+ * `openChangeAction` also absent, JS-free mode).
26
+ */
27
+ open?: boolean;
28
+ /**
29
+ * Initial open state in uncontrolled library mode. Opens after hydration, never in the server
30
+ * HTML.
31
+ */
32
+ defaultOpen?: boolean;
33
+ /**
34
+ * Awaited for `true` (the popover opens when it resolves and the content has rendered) and for
35
+ * a `false` the user asked a part for (Trigger, Close: the popover hides when it resolves, with
36
+ * a view transition if `transition` is set; a controlled parent that keeps `open` vetoes it).
37
+ * A notification for a dismissal (Escape, click outside: the popover is already hidden; the
38
+ * action runs inside the Root's transition, and a controlled parent that keeps `open` gets it
39
+ * re-opened, which is not a veto). May be a Server Function. Rejections reach the nearest
40
+ * Error Boundary above Root.
41
+ *
42
+ * A `setState` placed after your own `await` is not a Transition update; wrap it in
43
+ * `startTransition` (React limitation).
44
+ */
45
+ openChangeAction?: ChangeAction<boolean, PopoverOpenChangeDetails>;
46
+ children?: StateValue<ReactNode, PopoverRootState>;
47
+ }
48
+ /**
49
+ * Owns the ids, the mode, the open state and the context. Renders no DOM, so it has no `ref`,
50
+ * `className` or `style`; `pending` is exposed through `children(state)` and the Trigger.
51
+ *
52
+ * Without `open`, `defaultOpen` and `openChangeAction` the Popover runs in **JS-free mode**: the
53
+ * Trigger is a native `command="toggle-popover"` invoker and the browser owns everything. With any
54
+ * of them it runs in **library mode**: opening and the closes the user asks a part for are
55
+ * transitions (the Trigger shows `data-pending`, content renders from committed state,
56
+ * `showPopover()` / `hidePopover()` run when the change has committed); dismissals are the
57
+ * browser's and `openChangeAction(false)` is a notification.
58
+ */
59
+ export declare function PopoverRoot({ open, defaultOpen, openChangeAction, children }: PopoverRootProps): import("react").JSX.Element;
60
+ export declare namespace PopoverRoot {
61
+ var displayName: string;
62
+ }
63
+ //#endregion
64
+ //# sourceMappingURL=popover-root.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-root.d.mts","names":[],"sources":["../../src/popover/popover-root.tsx"],"mappings":";;;;iBAQiB,iCAAiC;;;;;;;;;WASvC,QAAQ;;iBAGF;;WAEN;;WAEA;;iBAGM;;;;;EAKf;;;;;EAKA;;;;;;;;;;;;;EAaA,mBAAmB,sBAAsB;EACzC,WAAW,WAAW,WAAW;;;;;;;;;;;;;wBAcnB,cAAc,MAAM,aAAa,kBAAkB,YAAY,mCAAgB,IAAA;yBAA/E"}
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import { resolveStateValue } from "../internal/use-render.mjs";
3
+ import { PopoverContext } from "./popover-context.mjs";
4
+ import { usePopoverRoot } from "../internal/use-popover-root.mjs";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/popover/popover-root.tsx
7
+ /**
8
+ * Owns the ids, the mode, the open state and the context. Renders no DOM, so it has no `ref`,
9
+ * `className` or `style`; `pending` is exposed through `children(state)` and the Trigger.
10
+ *
11
+ * Without `open`, `defaultOpen` and `openChangeAction` the Popover runs in **JS-free mode**: the
12
+ * Trigger is a native `command="toggle-popover"` invoker and the browser owns everything. With any
13
+ * of them it runs in **library mode**: opening and the closes the user asks a part for are
14
+ * transitions (the Trigger shows `data-pending`, content renders from committed state,
15
+ * `showPopover()` / `hidePopover()` run when the change has committed); dismissals are the
16
+ * browser's and `openChangeAction(false)` is a notification.
17
+ */
18
+ function PopoverRoot({ open, defaultOpen, openChangeAction, children }) {
19
+ const context = usePopoverRoot({
20
+ component: "popover",
21
+ part: "Popover.Root",
22
+ open,
23
+ defaultOpen,
24
+ openChangeAction
25
+ });
26
+ const state = {
27
+ open: context.optimistic,
28
+ pending: context.pending
29
+ };
30
+ return /* @__PURE__ */ jsx(PopoverContext, {
31
+ value: context,
32
+ children: resolveStateValue(children, state)
33
+ });
34
+ }
35
+ PopoverRoot.displayName = "PopoverRoot";
36
+ //#endregion
37
+ export { PopoverRoot };
38
+
39
+ //# sourceMappingURL=popover-root.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-root.mjs","names":[],"sources":["../../src/popover/popover-root.tsx"],"sourcesContent":["\"use client\";\nimport type { ReactNode } from \"react\";\nimport type { ActionDetails, ChangeAction, ChangeReason, StateValue } from \"../internal/types.js\";\nimport { usePopoverRoot } from \"../internal/use-popover-root.js\";\nimport { resolveStateValue } from \"../internal/use-render.js\";\nimport { PopoverContext } from \"./popover-context.js\";\n\n/** Details passed as the second argument of `openChangeAction`. */\nexport interface PopoverOpenChangeDetails extends ActionDetails {\n /**\n * `\"activate\"`: the user acted on a part: Trigger (open or close), Close, or a foreign invoker\n * (`details.event` is a `CommandEvent` / `ToggleEvent` then).\n * `\"dismiss\"`: the user closed the popover without a part: Escape, Android back, an assistive-\n * technology dismiss gesture, a click outside; or script / another top-layer element hid it.\n * `\"platform\"`: the popover was found open on mount (opened before hydration); `event` is\n * `undefined`.\n */\n readonly reason: ChangeReason;\n}\n\nexport interface PopoverRootState {\n /** Optimistic open state (`false` in JS-free mode). Content rendered from it must not suspend. */\n readonly open: boolean;\n /** An `openChangeAction` dispatched through this Popover is in flight (library mode only). */\n readonly pending: boolean;\n}\n\nexport interface PopoverRootProps {\n /**\n * Controlled open state. `undefined` means uncontrolled (and, with `defaultOpen` and\n * `openChangeAction` also absent, JS-free mode).\n */\n open?: boolean;\n /**\n * Initial open state in uncontrolled library mode. Opens after hydration, never in the server\n * HTML.\n */\n defaultOpen?: boolean;\n /**\n * Awaited for `true` (the popover opens when it resolves and the content has rendered) and for\n * a `false` the user asked a part for (Trigger, Close: the popover hides when it resolves, with\n * a view transition if `transition` is set; a controlled parent that keeps `open` vetoes it).\n * A notification for a dismissal (Escape, click outside: the popover is already hidden; the\n * action runs inside the Root's transition, and a controlled parent that keeps `open` gets it\n * re-opened, which is not a veto). May be a Server Function. Rejections reach the nearest\n * Error Boundary above Root.\n *\n * A `setState` placed after your own `await` is not a Transition update; wrap it in\n * `startTransition` (React limitation).\n */\n openChangeAction?: ChangeAction<boolean, PopoverOpenChangeDetails>;\n children?: StateValue<ReactNode, PopoverRootState>;\n}\n\n/**\n * Owns the ids, the mode, the open state and the context. Renders no DOM, so it has no `ref`,\n * `className` or `style`; `pending` is exposed through `children(state)` and the Trigger.\n *\n * Without `open`, `defaultOpen` and `openChangeAction` the Popover runs in **JS-free mode**: the\n * Trigger is a native `command=\"toggle-popover\"` invoker and the browser owns everything. With any\n * of them it runs in **library mode**: opening and the closes the user asks a part for are\n * transitions (the Trigger shows `data-pending`, content renders from committed state,\n * `showPopover()` / `hidePopover()` run when the change has committed); dismissals are the\n * browser's and `openChangeAction(false)` is a notification.\n */\nexport function PopoverRoot({ open, defaultOpen, openChangeAction, children }: PopoverRootProps) {\n const context = usePopoverRoot<PopoverOpenChangeDetails>({\n component: \"popover\",\n part: \"Popover.Root\",\n open,\n defaultOpen,\n openChangeAction,\n });\n\n const state: PopoverRootState = { open: context.optimistic, pending: context.pending };\n\n return <PopoverContext value={context}>{resolveStateValue(children, state)}</PopoverContext>;\n}\n\nPopoverRoot.displayName = \"PopoverRoot\";\n"],"mappings":";;;;;;;;;;;;;;;;;AAiEA,SAAgB,YAAY,EAAE,MAAM,aAAa,kBAAkB,YAA8B;CAC/F,MAAM,UAAU,eAAyC;EACvD,WAAW;EACX,MAAM;EACN;EACA;EACA;CACF,CAAC;CAED,MAAM,QAA0B;EAAE,MAAM,QAAQ;EAAY,SAAS,QAAQ;CAAQ;CAErF,OAAO,oBAAC,gBAAD;EAAgB,OAAO;EAAU,UAAA,kBAAkB,UAAU,KAAK;CAAkB,CAAA;AAC7F;AAEA,YAAY,cAAc"}
@@ -0,0 +1,23 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { PopoverPopupState } from "./popover-popup.mjs";
3
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
4
+ //#region src/popover/popover-title.d.ts
5
+ export type PopoverTitleState = PopoverPopupState;
6
+ export interface PopoverTitleProps extends Omit<ComponentPropsWithRef<"h2">, "id" | "className" | "style" | "children"> {
7
+ className?: StateValue<string | undefined, PopoverTitleState>;
8
+ style?: StateValue<CSSProperties | undefined, PopoverTitleState>;
9
+ children?: StateValue<ReactNode, PopoverTitleState>;
10
+ /** `render={<h3 />}` changes the heading level. */
11
+ render?: RenderProp<ComponentPropsWithRef<"h2">, PopoverTitleState>;
12
+ }
13
+ /**
14
+ * The popover's name: an `<h2>` whose id the Popup references with `aria-labelledby`.
15
+ *
16
+ * Owned key (conventions 1.2): `id`.
17
+ */
18
+ export declare function PopoverTitle({ className, style, children, render, ...rest }: PopoverTitleProps): ReactNode;
19
+ export declare namespace PopoverTitle {
20
+ var displayName: string;
21
+ }
22
+ //#endregion
23
+ //# sourceMappingURL=popover-title.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-title.d.mts","names":[],"sources":["../../src/popover/popover-title.tsx"],"mappings":";;;;YAOY,oBAAoB;iBAEf,0BAA0B,KACzC;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,6BAA6B;;;;;;;wBAQnC,eAAe,WAAW,OAAO,UAAU,WAAW,QAAQ,oBAAiB;yBAA/E"}
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { useRender } from "../internal/use-render.mjs";
3
+ import { usePopoverContext, usePopoverPopupState } from "./popover-context.mjs";
4
+ //#region src/popover/popover-title.tsx
5
+ /**
6
+ * The popover's name: an `<h2>` whose id the Popup references with `aria-labelledby`.
7
+ *
8
+ * Owned key (conventions 1.2): `id`.
9
+ */
10
+ function PopoverTitle({ className, style, children, render, ...rest }) {
11
+ const ctx = usePopoverContext("Popover.Title");
12
+ const state = usePopoverPopupState(ctx);
13
+ return useRender({
14
+ defaultElement: "h2",
15
+ render,
16
+ state,
17
+ className,
18
+ style,
19
+ children,
20
+ props: rest,
21
+ libraryProps: { id: ctx.ids.title }
22
+ });
23
+ }
24
+ PopoverTitle.displayName = "PopoverTitle";
25
+ //#endregion
26
+ export { PopoverTitle };
27
+
28
+ //# sourceMappingURL=popover-title.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-title.mjs","names":[],"sources":["../../src/popover/popover-title.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 { usePopoverContext, usePopoverPopupState } from \"./popover-context.js\";\nimport type { PopoverPopupState } from \"./popover-popup.js\";\n\nexport type PopoverTitleState = PopoverPopupState;\n\nexport interface PopoverTitleProps extends Omit<\n ComponentPropsWithRef<\"h2\">,\n \"id\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, PopoverTitleState>;\n style?: StateValue<CSSProperties | undefined, PopoverTitleState>;\n children?: StateValue<ReactNode, PopoverTitleState>;\n /** `render={<h3 />}` changes the heading level. */\n render?: RenderProp<ComponentPropsWithRef<\"h2\">, PopoverTitleState>;\n}\n\n/**\n * The popover's name: an `<h2>` whose id the Popup references with `aria-labelledby`.\n *\n * Owned key (conventions 1.2): `id`.\n */\nexport function PopoverTitle({ className, style, children, render, ...rest }: PopoverTitleProps) {\n const ctx = usePopoverContext(\"Popover.Title\");\n const state = usePopoverPopupState(ctx);\n return useRender<ComponentPropsWithRef<\"h2\">, PopoverTitleState>({\n defaultElement: \"h2\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: { id: ctx.ids.title },\n });\n}\n\nPopoverTitle.displayName = \"PopoverTitle\";\n"],"mappings":";;;;;;;;;AAyBA,SAAgB,aAAa,EAAE,WAAW,OAAO,UAAU,QAAQ,GAAG,QAA2B;CAC/F,MAAM,MAAM,kBAAkB,eAAe;CAC7C,MAAM,QAAQ,qBAAqB,GAAG;CACtC,OAAO,UAA0D;EAC/D,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc,EAAE,IAAI,IAAI,IAAI,MAAM;CACpC,CAAC;AACH;AAEA,aAAa,cAAc"}
@@ -0,0 +1,37 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
3
+ //#region src/popover/popover-trigger.d.ts
4
+ export interface PopoverTriggerState {
5
+ /** Optimistic open state (library mode); `false` in JS-free mode. */
6
+ readonly open: boolean;
7
+ /** The Root's transition is pending (an open, a part-initiated close or a dismissal notification). */
8
+ readonly pending: boolean;
9
+ readonly disabled: boolean;
10
+ }
11
+ export interface PopoverTriggerProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "aria-expanded" | "className" | "style" | "children"> {
12
+ /** Native `disabled`: a disabled button is not a valid invoker and never dispatches. */
13
+ disabled?: boolean;
14
+ className?: StateValue<string | undefined, PopoverTriggerState>;
15
+ style?: StateValue<CSSProperties | undefined, PopoverTriggerState>;
16
+ /** Rendered from optimistic state; must not suspend. */
17
+ children?: StateValue<ReactNode, PopoverTriggerState>;
18
+ /** Should render a `<button>`; another element works only in library mode (click handler). */
19
+ render?: RenderProp<ComponentPropsWithRef<"button">, PopoverTriggerState>;
20
+ }
21
+ /**
22
+ * The toggle: `<button type="button" commandfor command="toggle-popover" aria-expanded>`. In
23
+ * JS-free mode the browser runs the command and the Popup keeps `aria-expanded` current. In
24
+ * library mode the click is cancelled (so the command does not run) and dispatched through the
25
+ * Root's transition: an open, or a library-owned close while open. The button shows optimistic
26
+ * `data-open` / `aria-expanded` and `data-pending` until the change has landed.
27
+ *
28
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
29
+ * `command`, `aria-expanded`, `onClick` (library mode), `data-open`, `data-pending`,
30
+ * `data-disabled`. `aria-haspopup` and `aria-controls` pass through.
31
+ */
32
+ export declare function PopoverTrigger({ disabled, className, style, children, render, ...rest }: PopoverTriggerProps): ReactNode;
33
+ export declare namespace PopoverTrigger {
34
+ var displayName: string;
35
+ }
36
+ //#endregion
37
+ //# sourceMappingURL=popover-trigger.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-trigger.d.mts","names":[],"sources":["../../src/popover/popover-trigger.tsx"],"mappings":";;;iBAOiB;;WAEN;;WAEA;WACA;;iBAGM,4BAA4B,KAC3C;;EAIA;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;wBAcvC,iBACd,UACA,WACA,OACA,UACA,WACG,QACF,sBAAmB;yBAPN"}
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { useRender } from "../internal/use-render.mjs";
3
+ import { usePopoverContext } from "./popover-context.mjs";
4
+ import { usePopoverTrigger } from "../internal/use-popover-trigger.mjs";
5
+ //#region src/popover/popover-trigger.tsx
6
+ /**
7
+ * The toggle: `<button type="button" commandfor command="toggle-popover" aria-expanded>`. In
8
+ * JS-free mode the browser runs the command and the Popup keeps `aria-expanded` current. In
9
+ * library mode the click is cancelled (so the command does not run) and dispatched through the
10
+ * Root's transition: an open, or a library-owned close while open. The button shows optimistic
11
+ * `data-open` / `aria-expanded` and `data-pending` until the change has landed.
12
+ *
13
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
14
+ * `command`, `aria-expanded`, `onClick` (library mode), `data-open`, `data-pending`,
15
+ * `data-disabled`. `aria-haspopup` and `aria-controls` pass through.
16
+ */
17
+ function PopoverTrigger({ disabled = false, className, style, children, render, ...rest }) {
18
+ const ctx = usePopoverContext("Popover.Trigger");
19
+ const { state, libraryProps, ref } = usePopoverTrigger(ctx, {
20
+ part: "Popover.Trigger",
21
+ disabled,
22
+ render
23
+ });
24
+ return useRender({
25
+ defaultElement: "button",
26
+ render,
27
+ state,
28
+ className,
29
+ style,
30
+ children,
31
+ props: rest,
32
+ libraryProps,
33
+ ref
34
+ });
35
+ }
36
+ PopoverTrigger.displayName = "PopoverTrigger";
37
+ //#endregion
38
+ export { PopoverTrigger };
39
+
40
+ //# sourceMappingURL=popover-trigger.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-trigger.mjs","names":[],"sources":["../../src/popover/popover-trigger.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { usePopoverTrigger } from \"../internal/use-popover-trigger.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { usePopoverContext } from \"./popover-context.js\";\n\nexport interface PopoverTriggerState {\n /** Optimistic open state (library mode); `false` in JS-free mode. */\n readonly open: boolean;\n /** The Root's transition is pending (an open, a part-initiated close or a dismissal notification). */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface PopoverTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"aria-expanded\" | \"className\" | \"style\" | \"children\"\n> {\n /** Native `disabled`: a disabled button is not a valid invoker and never dispatches. */\n disabled?: boolean;\n className?: StateValue<string | undefined, PopoverTriggerState>;\n style?: StateValue<CSSProperties | undefined, PopoverTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, PopoverTriggerState>;\n /** Should render a `<button>`; another element works only in library mode (click handler). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, PopoverTriggerState>;\n}\n\n/**\n * The toggle: `<button type=\"button\" commandfor command=\"toggle-popover\" aria-expanded>`. In\n * JS-free mode the browser runs the command and the Popup keeps `aria-expanded` current. In\n * library mode the click is cancelled (so the command does not run) and dispatched through the\n * Root's transition: an open, or a library-owned close while open. The button shows optimistic\n * `data-open` / `aria-expanded` and `data-pending` until the change has landed.\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,\n * `command`, `aria-expanded`, `onClick` (library mode), `data-open`, `data-pending`,\n * `data-disabled`. `aria-haspopup` and `aria-controls` pass through.\n */\nexport function PopoverTrigger({\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: PopoverTriggerProps) {\n const ctx = usePopoverContext(\"Popover.Trigger\");\n const { state, libraryProps, ref } = usePopoverTrigger(ctx, {\n part: \"Popover.Trigger\",\n disabled,\n render,\n });\n\n return useRender<ComponentPropsWithRef<\"button\">, PopoverTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref,\n });\n}\n\nPopoverTrigger.displayName = \"PopoverTrigger\";\n"],"mappings":";;;;;;;;;;;;;;;;AAwCA,SAAgB,eAAe,EAC7B,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACmB;CACtB,MAAM,MAAM,kBAAkB,iBAAiB;CAC/C,MAAM,EAAE,OAAO,cAAc,QAAQ,kBAAkB,KAAK;EAC1D,MAAM;EACN;EACA;CACF,CAAC;CAED,OAAO,UAAgE;EACrE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;CACF,CAAC;AACH;AAEA,eAAe,cAAc"}
@@ -0,0 +1,20 @@
1
+ import "../internal/platform-attributes.mjs";
2
+ import { RadioGroupItem, RadioGroupItemProps, RadioGroupItemState } from "./radio-group-item.mjs";
3
+ import { RadioGroupRoot, RadioGroupRootProps, RadioGroupRootState, RadioGroupValueChangeDetails } from "./radio-group-root.mjs";
4
+ import { RadioGroupLabel, RadioGroupLabelProps } from "./radio-group-label.mjs";
5
+ //#region src/radio-group/index.d.ts
6
+ /**
7
+ * RadioGroup (WAI-ARIA APG Radio Group pattern, native HTML radio variant): `Root`
8
+ * (`fieldset[role=radiogroup]`), an optional `Label` (`legend`, first child) and one `Item`
9
+ * (`input[type=radio]`) per option. The keyboard is entirely native. Each Item's DOM `checked` is
10
+ * the optimistic value; the Root and the checked Item carry `data-pending` while
11
+ * `valueChangeAction` is in flight.
12
+ */
13
+ export declare const RadioGroup: {
14
+ readonly Root: typeof RadioGroupRoot;
15
+ readonly Label: typeof RadioGroupLabel;
16
+ readonly Item: typeof RadioGroupItem;
17
+ };
18
+ //#endregion
19
+ export type { RadioGroupItemProps, RadioGroupItemState, RadioGroupLabelProps, RadioGroupRootProps, RadioGroupRootState, RadioGroupValueChangeDetails };
20
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/radio-group/index.ts"],"mappings":";;;;;;;;;;;;qBAca;WACX,aAAI;WACJ,cAAK;WACL,aAAI"}
@@ -0,0 +1,20 @@
1
+ import { RadioGroupItem } from "./radio-group-item.mjs";
2
+ import { RadioGroupLabel } from "./radio-group-label.mjs";
3
+ import { RadioGroupRoot } from "./radio-group-root.mjs";
4
+ //#region src/radio-group/index.ts
5
+ /**
6
+ * RadioGroup (WAI-ARIA APG Radio Group pattern, native HTML radio variant): `Root`
7
+ * (`fieldset[role=radiogroup]`), an optional `Label` (`legend`, first child) and one `Item`
8
+ * (`input[type=radio]`) per option. The keyboard is entirely native. Each Item's DOM `checked` is
9
+ * the optimistic value; the Root and the checked Item carry `data-pending` while
10
+ * `valueChangeAction` is in flight.
11
+ */
12
+ const RadioGroup = {
13
+ Root: RadioGroupRoot,
14
+ Label: RadioGroupLabel,
15
+ Item: RadioGroupItem
16
+ };
17
+ //#endregion
18
+ export { RadioGroup };
19
+
20
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/radio-group/index.ts"],"sourcesContent":["// Ships the platform attribute typings with this subpath (conventions 7.4). Type-only: the\n// built JS has no import of it.\nimport \"../internal/platform-attributes.js\";\nimport { RadioGroupItem } from \"./radio-group-item.js\";\nimport { RadioGroupLabel } from \"./radio-group-label.js\";\nimport { RadioGroupRoot } from \"./radio-group-root.js\";\n\n/**\n * RadioGroup (WAI-ARIA APG Radio Group pattern, native HTML radio variant): `Root`\n * (`fieldset[role=radiogroup]`), an optional `Label` (`legend`, first child) and one `Item`\n * (`input[type=radio]`) per option. The keyboard is entirely native. Each Item's DOM `checked` is\n * the optimistic value; the Root and the checked Item carry `data-pending` while\n * `valueChangeAction` is in flight.\n */\nexport const RadioGroup = {\n Root: RadioGroupRoot,\n Label: RadioGroupLabel,\n Item: RadioGroupItem,\n} as const;\n\nexport type {\n RadioGroupRootProps,\n RadioGroupRootState,\n RadioGroupValueChangeDetails,\n} from \"./radio-group-root.js\";\nexport type { RadioGroupLabelProps } from \"./radio-group-label.js\";\nexport type { RadioGroupItemProps, RadioGroupItemState } from \"./radio-group-item.js\";\n"],"mappings":";;;;;;;;;;;AAcA,MAAa,aAAa;CACxB,MAAM;CACN,OAAO;CACP,MAAM;AACR"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { createContext, use } from "react";
3
+ //#region src/radio-group/radio-group-context.ts
4
+ const RadioGroupContext = createContext(null);
5
+ function useRadioGroupContext(part) {
6
+ const context = use(RadioGroupContext);
7
+ if (context === null) throw new Error(`${part} must be rendered inside a RadioGroup.Root.`);
8
+ return context;
9
+ }
10
+ //#endregion
11
+ export { RadioGroupContext, useRadioGroupContext };
12
+
13
+ //# sourceMappingURL=radio-group-context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group-context.mjs","names":[],"sources":["../../src/radio-group/radio-group-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\n\nexport interface RadioGroupContextValue {\n /** The `name` shared by every radio of the group (prop or `useId()`). */\n readonly name: string;\n readonly form: string | undefined;\n readonly required: boolean;\n /** Optimistic value: Items render `checked` from it. */\n readonly optimistic: string | null;\n readonly pending: boolean;\n /** `Root disabled` (reaches the radios natively through `<fieldset disabled>`). */\n readonly disabled: boolean;\n /**\n * Uncontrolled mode: the latest `defaultValue` (`null` when omitted), mirrored by each Item into\n * `el.defaultChecked` so that a form reset returns to it. `undefined` in controlled mode, where\n * React's mount-time value stays the reset target (conventions 3.8 rule 6).\n */\n readonly defaultValue: string | null | undefined;\n /**\n * Dispatches a user check. No-op when `value` is already the optimistic value. Checks neither\n * `disabled` (a disabled radio fires no click) nor `defaultPrevented` (the Item's\n * `guardCheckableChange` does).\n */\n readonly select: (value: string, event: Event) => void;\n /**\n * Called by each Item from its mount layout effect. An Item that mounts after the Root (under a\n * Suspense boundary, selective hydration) asks the Root to reconcile the group again, so a click\n * made before that Item hydrated is reported once (deduped by the Root's hook). Receives the\n * Item's element, which the Root uses for the dev-only partial-hydration warning.\n */\n readonly onItemMounted: (element: HTMLInputElement | null) => void;\n}\n\nexport const RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n\nexport function useRadioGroupContext(part: string): RadioGroupContextValue {\n const context = use(RadioGroupContext);\n if (context === null) {\n throw new Error(`${part} must be rendered inside a RadioGroup.Root.`);\n }\n return context;\n}\n"],"mappings":";;;AAkCA,MAAa,oBAAoB,cAA6C,IAAI;AAElF,SAAgB,qBAAqB,MAAsC;CACzE,MAAM,UAAU,IAAI,iBAAiB;CACrC,IAAI,YAAY,MACd,MAAM,IAAI,MAAM,GAAG,KAAK,4CAA4C;CAEtE,OAAO;AACT"}
@@ -0,0 +1,54 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ViewTransitionClass } from "react";
3
+ //#region src/radio-group/radio-group-item.d.ts
4
+ export interface RadioGroupItemState {
5
+ readonly value: string;
6
+ /** Optimistic: true as soon as the user checks this radio, before the action settles. */
7
+ readonly checked: boolean;
8
+ /** The Root is pending and this radio is the optimistic target. */
9
+ readonly pending: boolean;
10
+ /** Disabled by its own prop or by `Root disabled`. */
11
+ readonly disabled: boolean;
12
+ }
13
+ export interface RadioGroupItemProps extends Omit<ComponentPropsWithRef<"input">, "type" | "name" | "value" | "checked" | "defaultChecked" | "defaultValue" | "form" | "required" | "onChange" | "className" | "style" | "children"> {
14
+ /** The value this radio checks. Must be unique within the Root. Submitted as the form value. */
15
+ value: string;
16
+ /** Native `disabled`: unfocusable, skipped by arrow keys, never dispatches. */
17
+ disabled?: boolean;
18
+ /**
19
+ * Forwarded to the Item's `<ViewTransition default>`. Default: no boundary. Fires only on the commit
20
+ * that settles the action (or rolls it back), never on the optimistic check; animate the check
21
+ * itself with CSS on `:checked`.
22
+ *
23
+ * Static: without `transition` the part renders no `<ViewTransition>`; changing it between
24
+ * `undefined` and a value remounts the element. Any value, `"none"` included, makes a mount or
25
+ * `<Activity>` reveal of this part inside a transition start a document view transition: the
26
+ * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).
27
+ */
28
+ transition?: ViewTransitionClass;
29
+ className?: StateValue<string | undefined, RadioGroupItemState>;
30
+ style?: StateValue<CSSProperties | undefined, RadioGroupItemState>;
31
+ /** Replace the rendered element. Must keep an `<input>`; the library sets `type="radio"`. */
32
+ render?: RenderProp<ComponentPropsWithRef<"input">, RadioGroupItemState>;
33
+ }
34
+ /**
35
+ * One `<input type="radio">` of the group. Its DOM `checked` is the optimistic value
36
+ * (`checked={optimistic === value}`): react-dom restores a controlled input to its props after
37
+ * every event, and only the sync-lane optimistic value survives that restore.
38
+ *
39
+ * Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,
40
+ * `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`,
41
+ * `data-checked`, `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own
42
+ * handler runs first, then the library's.
43
+ *
44
+ * Form reset in controlled mode: React sets an input's `defaultChecked` once, from its initial
45
+ * `checked`. An Item added on the client while the Root's `value` equals its value gets
46
+ * `defaultChecked` too, so two radios may carry it and a reset does not necessarily return to
47
+ * the group's mount-time value (see `RadioGroup.Root` `value`).
48
+ */
49
+ export declare function RadioGroupItem({ value, disabled: disabledProp, transition, className, style, render, ...rest }: RadioGroupItemProps): import("react").ReactNode;
50
+ export declare namespace RadioGroupItem {
51
+ var displayName: string;
52
+ }
53
+ //#endregion
54
+ //# sourceMappingURL=radio-group-item.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group-item.d.mts","names":[],"sources":["../../src/radio-group/radio-group-item.tsx"],"mappings":";;;iBAUiB;WACN;;WAEA;;WAEA;;WAEA;;iBAGM,4BAA4B,KAC3C;;EAeA;;EAEA;;;;;;;;;;;EAWA,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;;EAE9C,SAAS,WAAW,gCAAgC;;;;;;;;;;;;;;;;;wBAkBtC,iBACd,OACA,UAAU,cACV,YACA,WACA,OACA,WACG,QACF,sCAAmB;yBARN"}
@@ -0,0 +1,83 @@
1
+ "use client";
2
+ import { useTransitionBoundary } from "../internal/transition-boundary.mjs";
3
+ import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { useRender } from "../internal/use-render.mjs";
5
+ import { guardCheckableChange, useNativeChecked } from "../internal/use-native-checked.mjs";
6
+ import { syncPresence } from "../internal/sync-presence.mjs";
7
+ import { useRadioGroupContext } from "./radio-group-context.mjs";
8
+ //#region src/radio-group/radio-group-item.tsx
9
+ /**
10
+ * One `<input type="radio">` of the group. Its DOM `checked` is the optimistic value
11
+ * (`checked={optimistic === value}`): react-dom restores a controlled input to its props after
12
+ * every event, and only the sync-lane optimistic value survives that restore.
13
+ *
14
+ * Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,
15
+ * `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`,
16
+ * `data-checked`, `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own
17
+ * handler runs first, then the library's.
18
+ *
19
+ * Form reset in controlled mode: React sets an input's `defaultChecked` once, from its initial
20
+ * `checked`. An Item added on the client while the Root's `value` equals its value gets
21
+ * `defaultChecked` too, so two radios may carry it and a reset does not necessarily return to
22
+ * the group's mount-time value (see `RadioGroup.Root` `value`).
23
+ */
24
+ function RadioGroupItem({ value, disabled: disabledProp = false, transition, className, style, render, ...rest }) {
25
+ const ctx = useRadioGroupContext("RadioGroup.Item");
26
+ const checked = ctx.optimistic === value;
27
+ const pending = ctx.pending && checked;
28
+ const disabled = ctx.disabled || disabledProp;
29
+ const inputRef = useNativeChecked({
30
+ type: "radio",
31
+ component: "RadioGroup.Item",
32
+ checked,
33
+ group: true,
34
+ onItemMounted: (el) => {
35
+ if (el !== null) {
36
+ syncPresence(el, "data-checked", checked);
37
+ syncPresence(el, "data-pending", pending);
38
+ syncPresence(el, "data-disabled", disabled);
39
+ }
40
+ ctx.onItemMounted(el);
41
+ },
42
+ defaultChecked: ctx.defaultValue === void 0 ? void 0 : ctx.defaultValue === value
43
+ });
44
+ const element = useRender({
45
+ defaultElement: "input",
46
+ render,
47
+ state: {
48
+ value,
49
+ checked,
50
+ pending,
51
+ disabled
52
+ },
53
+ className,
54
+ style,
55
+ children: void 0,
56
+ ref: inputRef,
57
+ props: rest,
58
+ libraryProps: {
59
+ type: "radio",
60
+ name: ctx.name,
61
+ value,
62
+ checked,
63
+ defaultChecked: void 0,
64
+ disabled: disabledProp,
65
+ form: ctx.form,
66
+ required: ctx.required,
67
+ "data-checked": dataAttr(checked),
68
+ "data-pending": dataAttr(pending),
69
+ "data-disabled": dataAttr(disabled),
70
+ onChange: (event) => {
71
+ if (disabled) return;
72
+ const nativeEvent = event.nativeEvent;
73
+ guardCheckableChange(nativeEvent, () => ctx.select(value, nativeEvent), "RadioGroup.Item");
74
+ }
75
+ }
76
+ });
77
+ return useTransitionBoundary("RadioGroup.Item", transition, element);
78
+ }
79
+ RadioGroupItem.displayName = "RadioGroupItem";
80
+ //#endregion
81
+ export { RadioGroupItem };
82
+
83
+ //# sourceMappingURL=radio-group-item.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radio-group-item.mjs","names":[],"sources":["../../src/radio-group/radio-group-item.tsx"],"sourcesContent":["\"use client\";\nimport type { ChangeEvent, ComponentPropsWithRef, CSSProperties, ViewTransitionClass } from \"react\";\nimport { useTransitionBoundary } from \"../internal/transition-boundary.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { syncPresence } from \"../internal/sync-presence.js\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { guardCheckableChange, useNativeChecked } from \"../internal/use-native-checked.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useRadioGroupContext } from \"./radio-group-context.js\";\n\nexport interface RadioGroupItemState {\n readonly value: string;\n /** Optimistic: true as soon as the user checks this radio, before the action settles. */\n readonly checked: boolean;\n /** The Root is pending and this radio is the optimistic target. */\n readonly pending: boolean;\n /** Disabled by its own prop or by `Root disabled`. */\n readonly disabled: boolean;\n}\n\nexport interface RadioGroupItemProps extends Omit<\n ComponentPropsWithRef<\"input\">,\n | \"type\"\n | \"name\"\n | \"value\"\n | \"checked\"\n | \"defaultChecked\"\n | \"defaultValue\"\n | \"form\"\n | \"required\"\n | \"onChange\"\n | \"className\"\n | \"style\"\n | \"children\"\n> {\n /** The value this radio checks. Must be unique within the Root. Submitted as the form value. */\n value: string;\n /** Native `disabled`: unfocusable, skipped by arrow keys, never dispatches. */\n disabled?: boolean;\n /**\n * Forwarded to the Item's `<ViewTransition default>`. Default: no boundary. Fires only on the commit\n * that settles the action (or rolls it back), never on the optimistic check; animate the check\n * itself with CSS on `:checked`.\n *\n * Static: without `transition` the part renders no `<ViewTransition>`; changing it between\n * `undefined` and a value remounts the element. Any value, `\"none\"` included, makes a mount or\n * `<Activity>` reveal of this part inside a transition start a document view transition: the\n * page cross-fades for about 250 ms and the next transition commit waits for it (issue #35).\n */\n transition?: ViewTransitionClass;\n className?: StateValue<string | undefined, RadioGroupItemState>;\n style?: StateValue<CSSProperties | undefined, RadioGroupItemState>;\n /** Replace the rendered element. Must keep an `<input>`; the library sets `type=\"radio\"`. */\n render?: RenderProp<ComponentPropsWithRef<\"input\">, RadioGroupItemState>;\n}\n\n/**\n * One `<input type=\"radio\">` of the group. Its DOM `checked` is the optimistic value\n * (`checked={optimistic === value}`): react-dom restores a controlled input to its props after\n * every event, and only the sync-lane optimistic value survives that restore.\n *\n * Owned keys (conventions 1.2; a `render` element's value is overridden): `type`, `name`,\n * `value`, `checked`, `defaultChecked` (never rendered), `disabled`, `form`, `required`,\n * `data-checked`, `data-pending`, `data-disabled`. `onChange` is merged: a `render` element's own\n * handler runs first, then the library's.\n *\n * Form reset in controlled mode: React sets an input's `defaultChecked` once, from its initial\n * `checked`. An Item added on the client while the Root's `value` equals its value gets\n * `defaultChecked` too, so two radios may carry it and a reset does not necessarily return to\n * the group's mount-time value (see `RadioGroup.Root` `value`).\n */\nexport function RadioGroupItem({\n value,\n disabled: disabledProp = false,\n transition,\n className,\n style,\n render,\n ...rest\n}: RadioGroupItemProps) {\n const ctx = useRadioGroupContext(\"RadioGroup.Item\");\n const checked = ctx.optimistic === value;\n const pending = ctx.pending && checked;\n const disabled = ctx.disabled || disabledProp;\n\n // Group mode: element check and re-apply only; the Root reports the residual paths once. The\n // hook calls `onItemMounted` at mount so that an Item mounting after its Root (a Suspense\n // boundary that hydrates later) still gets the group reconciled.\n const inputRef = useNativeChecked({\n type: \"radio\",\n component: \"RadioGroup.Item\",\n checked,\n group: true,\n onItemMounted: (el) => {\n // Hydration keeps server attributes that differ from the client render (React only warns).\n // An Item hydrating after its Root (partial hydration, Root JSDoc) can render a different\n // `checked` than the server did, e.g. after a click on an already hydrated radio, and a\n // stale `data-checked` would then stay until the prop changes again.\n if (el !== null) {\n syncPresence(el, \"data-checked\", checked);\n syncPresence(el, \"data-pending\", pending);\n syncPresence(el, \"data-disabled\", disabled);\n }\n ctx.onItemMounted(el);\n },\n defaultChecked: ctx.defaultValue === undefined ? undefined : ctx.defaultValue === value,\n });\n\n const state: RadioGroupItemState = { value, checked, pending, disabled };\n\n const element = useRender<ComponentPropsWithRef<\"input\">, RadioGroupItemState>({\n defaultElement: \"input\",\n render,\n state,\n className,\n style,\n children: undefined,\n ref: inputRef,\n // Pass-through layer: a `render` element's own props win over these.\n props: rest,\n libraryProps: {\n type: \"radio\",\n name: ctx.name,\n value,\n checked,\n defaultChecked: undefined,\n // Owned (Switch precedent) so that native disabledness, `data-disabled` and the click guard\n // agree. Only the Item's own prop: `Root disabled` reaches the radio through the fieldset.\n disabled: disabledProp,\n form: ctx.form,\n required: ctx.required,\n \"data-checked\": dataAttr(checked),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n // A natively disabled radio fires no click; this covers `render` elements that do not\n // honour `disabled`.\n if (disabled) return;\n const nativeEvent = event.nativeEvent;\n guardCheckableChange(nativeEvent, () => ctx.select(value, nativeEvent), \"RadioGroup.Item\");\n },\n },\n });\n\n return useTransitionBoundary(\"RadioGroup.Item\", transition, element);\n}\n\nRadioGroupItem.displayName = \"RadioGroupItem\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuEA,SAAgB,eAAe,EAC7B,OACA,UAAU,eAAe,OACzB,YACA,WACA,OACA,QACA,GAAG,QACmB;CACtB,MAAM,MAAM,qBAAqB,iBAAiB;CAClD,MAAM,UAAU,IAAI,eAAe;CACnC,MAAM,UAAU,IAAI,WAAW;CAC/B,MAAM,WAAW,IAAI,YAAY;CAKjC,MAAM,WAAW,iBAAiB;EAChC,MAAM;EACN,WAAW;EACX;EACA,OAAO;EACP,gBAAgB,OAAO;GAKrB,IAAI,OAAO,MAAM;IACf,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,gBAAgB,OAAO;IACxC,aAAa,IAAI,iBAAiB,QAAQ;GAC5C;GACA,IAAI,cAAc,EAAE;EACtB;EACA,gBAAgB,IAAI,iBAAiB,KAAA,IAAY,KAAA,IAAY,IAAI,iBAAiB;CACpF,CAAC;CAID,MAAM,UAAU,UAA+D;EAC7E,gBAAgB;EAChB;EACA,OAAA;GALmC;GAAO;GAAS;GAAS;EAKxD;EACJ;EACA;EACA,UAAU,KAAA;EACV,KAAK;EAEL,OAAO;EACP,cAAc;GACZ,MAAM;GACN,MAAM,IAAI;GACV;GACA;GACA,gBAAgB,KAAA;GAGhB,UAAU;GACV,MAAM,IAAI;GACV,UAAU,IAAI;GACd,gBAAgB,SAAS,OAAO;GAChC,gBAAgB,SAAS,OAAO;GAChC,iBAAiB,SAAS,QAAQ;GAClC,WAAW,UAAyC;IAGlD,IAAI,UAAU;IACd,MAAM,cAAc,MAAM;IAC1B,qBAAqB,mBAAmB,IAAI,OAAO,OAAO,WAAW,GAAG,iBAAiB;GAC3F;EACF;CACF,CAAC;CAED,OAAO,sBAAsB,mBAAmB,YAAY,OAAO;AACrE;AAEA,eAAe,cAAc"}