@funstack/ui 0.1.0-alpha.0 → 0.1.0-alpha.2

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 (242) hide show
  1. package/README.md +1 -1
  2. package/dist/checkbox-group/checkbox-group-context.mjs +24 -0
  3. package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -0
  4. package/dist/checkbox-group/checkbox-group-item.d.mts +55 -0
  5. package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -0
  6. package/dist/checkbox-group/checkbox-group-item.mjs +90 -0
  7. package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -0
  8. package/dist/checkbox-group/checkbox-group-label.d.mts +21 -0
  9. package/dist/checkbox-group/checkbox-group-label.d.mts.map +1 -0
  10. package/dist/checkbox-group/checkbox-group-label.mjs +30 -0
  11. package/dist/checkbox-group/checkbox-group-label.mjs.map +1 -0
  12. package/dist/checkbox-group/checkbox-group-parent.d.mts +68 -0
  13. package/dist/checkbox-group/checkbox-group-parent.d.mts.map +1 -0
  14. package/dist/checkbox-group/checkbox-group-parent.mjs +145 -0
  15. package/dist/checkbox-group/checkbox-group-parent.mjs.map +1 -0
  16. package/dist/checkbox-group/checkbox-group-root.d.mts +100 -0
  17. package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -0
  18. package/dist/checkbox-group/checkbox-group-root.mjs +291 -0
  19. package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -0
  20. package/dist/checkbox-group/index.d.mts +23 -0
  21. package/dist/checkbox-group/index.d.mts.map +1 -0
  22. package/dist/checkbox-group/index.mjs +23 -0
  23. package/dist/checkbox-group/index.mjs.map +1 -0
  24. package/dist/combobox/combobox-clear.d.mts +34 -0
  25. package/dist/combobox/combobox-clear.d.mts.map +1 -0
  26. package/dist/combobox/combobox-clear.mjs +58 -0
  27. package/dist/combobox/combobox-clear.mjs.map +1 -0
  28. package/dist/combobox/combobox-context.mjs +23 -0
  29. package/dist/combobox/combobox-context.mjs.map +1 -0
  30. package/dist/combobox/combobox-group.d.mts +72 -0
  31. package/dist/combobox/combobox-group.d.mts.map +1 -0
  32. package/dist/combobox/combobox-group.mjs +104 -0
  33. package/dist/combobox/combobox-group.mjs.map +1 -0
  34. package/dist/combobox/combobox-input.d.mts +40 -0
  35. package/dist/combobox/combobox-input.d.mts.map +1 -0
  36. package/dist/combobox/combobox-input.mjs +88 -0
  37. package/dist/combobox/combobox-input.mjs.map +1 -0
  38. package/dist/combobox/combobox-label.d.mts +22 -0
  39. package/dist/combobox/combobox-label.d.mts.map +1 -0
  40. package/dist/combobox/combobox-label.mjs +32 -0
  41. package/dist/combobox/combobox-label.mjs.map +1 -0
  42. package/dist/combobox/combobox-list.d.mts +37 -0
  43. package/dist/combobox/combobox-list.d.mts.map +1 -0
  44. package/dist/combobox/combobox-list.mjs +70 -0
  45. package/dist/combobox/combobox-list.mjs.map +1 -0
  46. package/dist/combobox/combobox-option.d.mts +45 -0
  47. package/dist/combobox/combobox-option.d.mts.map +1 -0
  48. package/dist/combobox/combobox-option.mjs +88 -0
  49. package/dist/combobox/combobox-option.mjs.map +1 -0
  50. package/dist/combobox/combobox-popup.d.mts +49 -0
  51. package/dist/combobox/combobox-popup.d.mts.map +1 -0
  52. package/dist/combobox/combobox-popup.mjs +86 -0
  53. package/dist/combobox/combobox-popup.mjs.map +1 -0
  54. package/dist/combobox/combobox-root.d.mts +135 -0
  55. package/dist/combobox/combobox-root.d.mts.map +1 -0
  56. package/dist/combobox/combobox-root.mjs +508 -0
  57. package/dist/combobox/combobox-root.mjs.map +1 -0
  58. package/dist/combobox/combobox-trigger.d.mts +36 -0
  59. package/dist/combobox/combobox-trigger.d.mts.map +1 -0
  60. package/dist/combobox/combobox-trigger.mjs +92 -0
  61. package/dist/combobox/combobox-trigger.mjs.map +1 -0
  62. package/dist/combobox/index.d.mts +36 -0
  63. package/dist/combobox/index.d.mts.map +1 -0
  64. package/dist/combobox/index.mjs +36 -0
  65. package/dist/combobox/index.mjs.map +1 -0
  66. package/dist/dialog/dialog-close.d.mts.map +1 -1
  67. package/dist/dialog/dialog-close.mjs +4 -4
  68. package/dist/dialog/dialog-close.mjs.map +1 -1
  69. package/dist/dialog/dialog-context.mjs.map +1 -1
  70. package/dist/dialog/dialog-popup.mjs +1 -0
  71. package/dist/dialog/dialog-popup.mjs.map +1 -1
  72. package/dist/dialog/dialog-root.mjs +9 -1
  73. package/dist/dialog/dialog-root.mjs.map +1 -1
  74. package/dist/index.d.mts +42 -2
  75. package/dist/index.mjs +6 -1
  76. package/dist/internal/anchor-position.d.mts +7 -0
  77. package/dist/internal/anchor-position.d.mts.map +1 -0
  78. package/dist/internal/anchor-position.mjs +16 -0
  79. package/dist/internal/anchor-position.mjs.map +1 -0
  80. package/dist/internal/platform-attributes.d.mts +18 -1
  81. package/dist/internal/platform-attributes.d.mts.map +1 -1
  82. package/dist/internal/sync-presence.mjs +19 -0
  83. package/dist/internal/sync-presence.mjs.map +1 -0
  84. package/dist/internal/types.d.mts +8 -0
  85. package/dist/internal/types.d.mts.map +1 -1
  86. package/dist/internal/use-action-trigger.mjs +58 -0
  87. package/dist/internal/use-action-trigger.mjs.map +1 -0
  88. package/dist/internal/use-controllable-action.mjs +5 -1
  89. package/dist/internal/use-controllable-action.mjs.map +1 -1
  90. package/dist/internal/use-delayed-pair.mjs +40 -0
  91. package/dist/internal/use-delayed-pair.mjs.map +1 -0
  92. package/dist/internal/use-exit-animation.mjs +55 -0
  93. package/dist/internal/use-exit-animation.mjs.map +1 -0
  94. package/dist/internal/use-form-reset.mjs +5 -1
  95. package/dist/internal/use-form-reset.mjs.map +1 -1
  96. package/dist/internal/use-hydrated-mount.mjs +21 -0
  97. package/dist/internal/use-hydrated-mount.mjs.map +1 -0
  98. package/dist/internal/use-native-group-reconciliation.mjs +2 -2
  99. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  100. package/dist/internal/use-native-select-value.mjs +182 -0
  101. package/dist/internal/use-native-select-value.mjs.map +1 -0
  102. package/dist/internal/use-popover-popup.mjs +274 -0
  103. package/dist/internal/use-popover-popup.mjs.map +1 -0
  104. package/dist/internal/use-popover-root.d.mts +2 -0
  105. package/dist/internal/use-popover-root.mjs +112 -0
  106. package/dist/internal/use-popover-root.mjs.map +1 -0
  107. package/dist/internal/use-popover-trigger.mjs +86 -0
  108. package/dist/internal/use-popover-trigger.mjs.map +1 -0
  109. package/dist/menu/index.d.mts +34 -0
  110. package/dist/menu/index.d.mts.map +1 -0
  111. package/dist/menu/index.mjs +34 -0
  112. package/dist/menu/index.mjs.map +1 -0
  113. package/dist/menu/menu-checkbox-item.d.mts +42 -0
  114. package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
  115. package/dist/menu/menu-checkbox-item.mjs +71 -0
  116. package/dist/menu/menu-checkbox-item.mjs.map +1 -0
  117. package/dist/menu/menu-context.d.mts +1 -0
  118. package/dist/menu/menu-context.mjs +28 -0
  119. package/dist/menu/menu-context.mjs.map +1 -0
  120. package/dist/menu/menu-dom.mjs +37 -0
  121. package/dist/menu/menu-dom.mjs.map +1 -0
  122. package/dist/menu/menu-group.d.mts +48 -0
  123. package/dist/menu/menu-group.d.mts.map +1 -0
  124. package/dist/menu/menu-group.mjs +69 -0
  125. package/dist/menu/menu-group.mjs.map +1 -0
  126. package/dist/menu/menu-hover.mjs +29 -0
  127. package/dist/menu/menu-hover.mjs.map +1 -0
  128. package/dist/menu/menu-item.d.mts +45 -0
  129. package/dist/menu/menu-item.d.mts.map +1 -0
  130. package/dist/menu/menu-item.mjs +54 -0
  131. package/dist/menu/menu-item.mjs.map +1 -0
  132. package/dist/menu/menu-popup.d.mts +69 -0
  133. package/dist/menu/menu-popup.d.mts.map +1 -0
  134. package/dist/menu/menu-popup.mjs +207 -0
  135. package/dist/menu/menu-popup.mjs.map +1 -0
  136. package/dist/menu/menu-radio-group.d.mts +37 -0
  137. package/dist/menu/menu-radio-group.d.mts.map +1 -0
  138. package/dist/menu/menu-radio-group.mjs +72 -0
  139. package/dist/menu/menu-radio-group.mjs.map +1 -0
  140. package/dist/menu/menu-radio-item.d.mts +33 -0
  141. package/dist/menu/menu-radio-item.d.mts.map +1 -0
  142. package/dist/menu/menu-radio-item.mjs +62 -0
  143. package/dist/menu/menu-radio-item.mjs.map +1 -0
  144. package/dist/menu/menu-root.d.mts +54 -0
  145. package/dist/menu/menu-root.d.mts.map +1 -0
  146. package/dist/menu/menu-root.mjs +102 -0
  147. package/dist/menu/menu-root.mjs.map +1 -0
  148. package/dist/menu/menu-submenu-trigger.d.mts +31 -0
  149. package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
  150. package/dist/menu/menu-submenu-trigger.mjs +92 -0
  151. package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
  152. package/dist/menu/menu-trigger.d.mts +36 -0
  153. package/dist/menu/menu-trigger.d.mts.map +1 -0
  154. package/dist/menu/menu-trigger.mjs +81 -0
  155. package/dist/menu/menu-trigger.mjs.map +1 -0
  156. package/dist/menu/use-menu-item.mjs +54 -0
  157. package/dist/menu/use-menu-item.mjs.map +1 -0
  158. package/dist/popover/index.d.mts +28 -0
  159. package/dist/popover/index.d.mts.map +1 -0
  160. package/dist/popover/index.mjs +28 -0
  161. package/dist/popover/index.mjs.map +1 -0
  162. package/dist/popover/popover-close.d.mts +41 -0
  163. package/dist/popover/popover-close.d.mts.map +1 -0
  164. package/dist/popover/popover-close.mjs +90 -0
  165. package/dist/popover/popover-close.mjs.map +1 -0
  166. package/dist/popover/popover-context.mjs +26 -0
  167. package/dist/popover/popover-context.mjs.map +1 -0
  168. package/dist/popover/popover-description.d.mts +22 -0
  169. package/dist/popover/popover-description.d.mts.map +1 -0
  170. package/dist/popover/popover-description.mjs +28 -0
  171. package/dist/popover/popover-description.mjs.map +1 -0
  172. package/dist/popover/popover-popup.d.mts +82 -0
  173. package/dist/popover/popover-popup.d.mts.map +1 -0
  174. package/dist/popover/popover-popup.mjs +93 -0
  175. package/dist/popover/popover-popup.mjs.map +1 -0
  176. package/dist/popover/popover-root.d.mts +64 -0
  177. package/dist/popover/popover-root.d.mts.map +1 -0
  178. package/dist/popover/popover-root.mjs +39 -0
  179. package/dist/popover/popover-root.mjs.map +1 -0
  180. package/dist/popover/popover-title.d.mts +23 -0
  181. package/dist/popover/popover-title.d.mts.map +1 -0
  182. package/dist/popover/popover-title.mjs +28 -0
  183. package/dist/popover/popover-title.mjs.map +1 -0
  184. package/dist/popover/popover-trigger.d.mts +37 -0
  185. package/dist/popover/popover-trigger.d.mts.map +1 -0
  186. package/dist/popover/popover-trigger.mjs +40 -0
  187. package/dist/popover/popover-trigger.mjs.map +1 -0
  188. package/dist/radio-group/radio-group-item.d.mts.map +1 -1
  189. package/dist/radio-group/radio-group-item.mjs +1 -6
  190. package/dist/radio-group/radio-group-item.mjs.map +1 -1
  191. package/dist/select/index.d.mts +30 -0
  192. package/dist/select/index.d.mts.map +1 -0
  193. package/dist/select/index.mjs +30 -0
  194. package/dist/select/index.mjs.map +1 -0
  195. package/dist/select/select-context.mjs +13 -0
  196. package/dist/select/select-context.mjs.map +1 -0
  197. package/dist/select/select-dom.mjs +44 -0
  198. package/dist/select/select-dom.mjs.map +1 -0
  199. package/dist/select/select-group-label.d.mts +22 -0
  200. package/dist/select/select-group-label.d.mts.map +1 -0
  201. package/dist/select/select-group-label.mjs +39 -0
  202. package/dist/select/select-group-label.mjs.map +1 -0
  203. package/dist/select/select-group.d.mts +28 -0
  204. package/dist/select/select-group.d.mts.map +1 -0
  205. package/dist/select/select-group.mjs +45 -0
  206. package/dist/select/select-group.mjs.map +1 -0
  207. package/dist/select/select-option.d.mts +42 -0
  208. package/dist/select/select-option.d.mts.map +1 -0
  209. package/dist/select/select-option.mjs +65 -0
  210. package/dist/select/select-option.mjs.map +1 -0
  211. package/dist/select/select-root.d.mts +66 -0
  212. package/dist/select/select-root.d.mts.map +1 -0
  213. package/dist/select/select-root.mjs +94 -0
  214. package/dist/select/select-root.mjs.map +1 -0
  215. package/dist/select/select-separator.d.mts +20 -0
  216. package/dist/select/select-separator.d.mts.map +1 -0
  217. package/dist/select/select-separator.mjs +30 -0
  218. package/dist/select/select-separator.mjs.map +1 -0
  219. package/dist/select/select-trigger.d.mts +29 -0
  220. package/dist/select/select-trigger.d.mts.map +1 -0
  221. package/dist/select/select-trigger.mjs +48 -0
  222. package/dist/select/select-trigger.mjs.map +1 -0
  223. package/dist/select/select-value.d.mts +31 -0
  224. package/dist/select/select-value.d.mts.map +1 -0
  225. package/dist/select/select-value.mjs +101 -0
  226. package/dist/select/select-value.mjs.map +1 -0
  227. package/dist/tabs/tabs-context.mjs +2 -1
  228. package/dist/tabs/tabs-context.mjs.map +1 -1
  229. package/dist/tabs/tabs-list.d.mts +1 -1
  230. package/dist/tabs/tabs-list.d.mts.map +1 -1
  231. package/dist/tabs/tabs-list.mjs +17 -9
  232. package/dist/tabs/tabs-list.mjs.map +1 -1
  233. package/dist/tabs/tabs-tab.d.mts +1 -1
  234. package/dist/tabs/tabs-tab.d.mts.map +1 -1
  235. package/dist/tabs/tabs-tab.mjs +6 -3
  236. package/dist/tabs/tabs-tab.mjs.map +1 -1
  237. package/dist/tooltip/tooltip-popup.d.mts.map +1 -1
  238. package/dist/tooltip/tooltip-popup.mjs +2 -7
  239. package/dist/tooltip/tooltip-popup.mjs.map +1 -1
  240. package/dist/tooltip/use-tooltip-interaction.mjs +5 -17
  241. package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -1
  242. package/package.json +6 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-trigger.mjs","names":[],"sources":["../../src/menu/menu-trigger.tsx"],"sourcesContent":["\"use client\";\nimport type { ComponentPropsWithRef, CSSProperties, KeyboardEvent, ReactNode } from \"react\";\nimport type { RenderProp, StateValue } from \"../internal/types.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport { usePopoverTrigger } from \"../internal/use-popover-trigger.js\";\nimport { useRender } from \"../internal/use-render.js\";\nimport { useMenuContext } from \"./menu-context.js\";\nimport type { MenuContextValue } from \"./menu-context.js\";\nimport { edgeItem, focusItem, hasModifier } from \"./menu-dom.js\";\n\nexport interface MenuTriggerState {\n /** Optimistic open state. */\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 MenuTriggerProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"onKeyDown\" | \"aria-expanded\" | \"aria-haspopup\" | \"className\" | \"style\" | \"children\"\n> {\n /** Native `disabled`: the menu cannot be opened from this button. */\n disabled?: boolean;\n className?: StateValue<string | undefined, MenuTriggerState>;\n style?: StateValue<CSSProperties | undefined, MenuTriggerState>;\n /** Rendered from optimistic state; must not suspend. */\n children?: StateValue<ReactNode, MenuTriggerState>;\n /** Should render a `<button>` (the command path before hydration). */\n render?: RenderProp<ComponentPropsWithRef<\"button\">, MenuTriggerState>;\n}\n\n/**\n * Opens with the first (`\"first\"`) or last (`\"last\"`) item focused, or focuses that item when the\n * menu is already open (a pre-hydration open, walkthrough 10). Shared with SubmenuTrigger.\n */\nexport function openMenuWithFocus(\n menu: MenuContextValue,\n event: Event,\n which: \"first\" | \"last\",\n): void {\n const { popover } = menu;\n if (popover.intended()) {\n const popup = popover.popupRef.current;\n if (popup !== null && popup.matches(\":popover-open\")) {\n const item = edgeItem(popup, which);\n if (item !== null) focusItem(item);\n }\n return;\n }\n menu.setOpenCause(which, isPointerClick(event));\n popover.requestOpen(event, \"activate\");\n}\n\n/** A click from a pointing device (`detail` counts clicks; keyboard and `click()` give 0). */\nexport function isPointerClick(event: Event): boolean {\n return event.type === \"click\" && (event as MouseEvent).detail > 0;\n}\n\n/**\n * The menu button: `<button type=\"button\" commandfor command=\"toggle-popover\"\n * aria-haspopup=\"menu\" aria-expanded>`. A click (Enter, Space) toggles the menu through the\n * Root's transition; ArrowDown / ArrowUp open it with the first / last item focused.\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `id`, `disabled`, `commandfor`,\n * `command`, `aria-haspopup`, `aria-expanded`, `onClick`, `onKeyDown`, `data-open`,\n * `data-pending`, `data-disabled`.\n */\nexport function MenuTrigger({\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: MenuTriggerProps) {\n const menu = useMenuContext(\"Menu.Trigger\");\n useDevWarning(\n menu.submenu,\n \"Menu.Trigger: rendered in a submenu. Use Menu.SubmenuTrigger, which is also an item of the \" +\n \"parent menu.\",\n );\n\n const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (disabled || hasModifier(event)) return;\n if (event.key !== \"ArrowDown\" && event.key !== \"ArrowUp\") return;\n // No page scroll; Enter and Space stay the native click.\n event.preventDefault();\n openMenuWithFocus(menu, event.nativeEvent, event.key === \"ArrowDown\" ? \"first\" : \"last\");\n };\n\n const { state, libraryProps, ref } = usePopoverTrigger(menu.popover, {\n part: \"Menu.Trigger\",\n disabled,\n render,\n handlers: { onKeyDown },\n activate: (event) => {\n const native = event.nativeEvent;\n if (menu.popover.intended()) {\n menu.popover.requestClose(native, \"activate\");\n } else {\n menu.setOpenCause(\"first\", isPointerClick(native));\n menu.popover.requestOpen(native, \"activate\");\n }\n },\n });\n\n return useRender<ComponentPropsWithRef<\"button\">, MenuTriggerState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: {\n ...libraryProps,\n id: menu.triggerId,\n \"aria-haspopup\": \"menu\",\n },\n ref,\n });\n}\n\nMenuTrigger.displayName = \"MenuTrigger\";\n"],"mappings":";;;;;;;;;;;AAoCA,SAAgB,kBACd,MACA,OACA,OACM;CACN,MAAM,EAAE,YAAY;CACpB,IAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,QAAQ,QAAQ,SAAS;EAC/B,IAAI,UAAU,QAAQ,MAAM,QAAQ,eAAe,GAAG;GACpD,MAAM,OAAO,SAAS,OAAO,KAAK;GAClC,IAAI,SAAS,MAAM,UAAU,IAAI;EACnC;EACA;CACF;CACA,KAAK,aAAa,OAAO,eAAe,KAAK,CAAC;CAC9C,QAAQ,YAAY,OAAO,UAAU;AACvC;;AAGA,SAAgB,eAAe,OAAuB;CACpD,OAAO,MAAM,SAAS,WAAY,MAAqB,SAAS;AAClE;;;;;;;;;;AAWA,SAAgB,YAAY,EAC1B,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACgB;CACnB,MAAM,OAAO,eAAe,cAAc;CAC1C,cACE,KAAK,SACL,yGAEF;CAEA,MAAM,aAAa,UAA4C;EAC7D,IAAI,YAAY,YAAY,KAAK,GAAG;EACpC,IAAI,MAAM,QAAQ,eAAe,MAAM,QAAQ,WAAW;EAE1D,MAAM,eAAe;EACrB,kBAAkB,MAAM,MAAM,aAAa,MAAM,QAAQ,cAAc,UAAU,MAAM;CACzF;CAEA,MAAM,EAAE,OAAO,cAAc,QAAQ,kBAAkB,KAAK,SAAS;EACnE,MAAM;EACN;EACA;EACA,UAAU,EAAE,UAAU;EACtB,WAAW,UAAU;GACnB,MAAM,SAAS,MAAM;GACrB,IAAI,KAAK,QAAQ,SAAS,GACxB,KAAK,QAAQ,aAAa,QAAQ,UAAU;QACvC;IACL,KAAK,aAAa,SAAS,eAAe,MAAM,CAAC;IACjD,KAAK,QAAQ,YAAY,QAAQ,UAAU;GAC7C;EACF;CACF,CAAC;CAED,OAAO,UAA6D;EAClE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc;GACZ,GAAG;GACH,IAAI,KAAK;GACT,iBAAiB;EACnB;EACA;CACF,CAAC;AACH;AAEA,YAAY,cAAc"}
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { dataAttr } from "../internal/data-attr.mjs";
3
+ import { useDevWarning } from "../internal/use-dev-warning.mjs";
4
+ import { MenuListContext } from "./menu-context.mjs";
5
+ import { hasModifier } from "./menu-dom.mjs";
6
+ import { use } from "react";
7
+ //#region src/menu/use-menu-item.ts
8
+ /**
9
+ * The parts every menu item shares: role, roving `tabindex` (none on the native `focusgroup`
10
+ * path), `aria-disabled`, activation by click / Enter / Space (Space is a typeahead character
11
+ * while a buffer is active), and the current item following the pointer (design 6.2).
12
+ */
13
+ function useMenuItem(options) {
14
+ const { part, role, disabled, label, activate } = options;
15
+ const list = use(MenuListContext);
16
+ useDevWarning(list === null, `${part}: rendered outside a Menu.Popup.`);
17
+ const onClick = (event) => {
18
+ if (disabled) {
19
+ event.preventDefault();
20
+ return;
21
+ }
22
+ activate(event.nativeEvent);
23
+ };
24
+ const onKeyDown = (event) => {
25
+ if (event.defaultPrevented || hasModifier(event)) return;
26
+ if (event.key !== "Enter" && event.key !== " ") return;
27
+ if (event.key === " " && list?.typingAhead()) return;
28
+ event.preventDefault();
29
+ if (disabled) return;
30
+ event.currentTarget.click();
31
+ };
32
+ const onPointerMove = (event) => {
33
+ const element = event.currentTarget;
34
+ if (element.ownerDocument.activeElement !== element) element.focus();
35
+ };
36
+ return {
37
+ list,
38
+ libraryProps: {
39
+ role,
40
+ tabIndex: list?.nativeFocusgroup === true ? void 0 : -1,
41
+ "aria-disabled": disabled ? true : void 0,
42
+ disabled: void 0,
43
+ "data-disabled": dataAttr(disabled),
44
+ "data-typeahead": label,
45
+ onClick,
46
+ onKeyDown,
47
+ onPointerMove
48
+ }
49
+ };
50
+ }
51
+ //#endregion
52
+ export { useMenuItem };
53
+
54
+ //# sourceMappingURL=use-menu-item.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-menu-item.mjs","names":[],"sources":["../../src/menu/use-menu-item.ts"],"sourcesContent":["\"use client\";\nimport { use } from \"react\";\nimport type { KeyboardEvent, MouseEvent, PointerEvent } from \"react\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport { useDevWarning } from \"../internal/use-dev-warning.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { MenuListContext } from \"./menu-context.js\";\nimport type { MenuListContextValue } from \"./menu-context.js\";\nimport { hasModifier } from \"./menu-dom.js\";\n\nexport interface MenuItemBaseOptions {\n /** Public name of the part for development warnings. */\n readonly part: string;\n readonly role: \"menuitem\" | \"menuitemcheckbox\" | \"menuitemradio\";\n readonly disabled: boolean;\n readonly label: string | undefined;\n /** Runs for a click, Enter or Space on an enabled item (never for a disabled one). */\n readonly activate: (event: Event) => void;\n}\n\nexport interface MenuItemBase {\n readonly list: MenuListContextValue | null;\n /** Owned props shared by every item kind (design 3.4). */\n readonly libraryProps: {\n role: string;\n tabIndex: number | undefined;\n \"aria-disabled\": true | undefined;\n disabled: undefined;\n onClick: (event: MouseEvent<HTMLElement>) => void;\n onKeyDown: (event: KeyboardEvent<HTMLElement>) => void;\n onPointerMove: (event: PointerEvent<HTMLElement>) => void;\n } & DataAttributes;\n}\n\n/**\n * The parts every menu item shares: role, roving `tabindex` (none on the native `focusgroup`\n * path), `aria-disabled`, activation by click / Enter / Space (Space is a typeahead character\n * while a buffer is active), and the current item following the pointer (design 6.2).\n */\nexport function useMenuItem(options: MenuItemBaseOptions): MenuItemBase {\n const { part, role, disabled, label, activate } = options;\n const list = use(MenuListContext);\n useDevWarning(list === null, `${part}: rendered outside a Menu.Popup.`);\n\n const onClick = (event: MouseEvent<HTMLElement>) => {\n if (disabled) {\n // A disabled link must not navigate either.\n event.preventDefault();\n return;\n }\n activate(event.nativeEvent);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.defaultPrevented || hasModifier(event)) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n if (event.key === \" \" && list?.typingAhead()) return;\n // No page scroll for Space, no second native click.\n event.preventDefault();\n if (disabled) return;\n // Activation is always the element's click: it runs `onClick` (and so `activate`) and the\n // element's own activation behaviour, which a link (navigation) and an item composed with\n // another trigger (`Dialog.Trigger render={<Menu.Item />}`: its command) depend on.\n event.currentTarget.click();\n };\n\n const onPointerMove = (event: PointerEvent<HTMLElement>) => {\n const element = event.currentTarget;\n if (element.ownerDocument.activeElement !== element) element.focus();\n };\n\n return {\n list,\n libraryProps: {\n role,\n tabIndex: list?.nativeFocusgroup === true ? undefined : -1,\n \"aria-disabled\": disabled ? true : undefined,\n // Never the native attribute: disabled items stay focusable (APG), and Chromium's\n // focusgroup skips natively disabled buttons.\n disabled: undefined,\n \"data-disabled\": dataAttr(disabled),\n \"data-typeahead\": label,\n onClick,\n onKeyDown,\n onPointerMove,\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;AAuCA,SAAgB,YAAY,SAA4C;CACtE,MAAM,EAAE,MAAM,MAAM,UAAU,OAAO,aAAa;CAClD,MAAM,OAAO,IAAI,eAAe;CAChC,cAAc,SAAS,MAAM,GAAG,KAAK,iCAAiC;CAEtE,MAAM,WAAW,UAAmC;EAClD,IAAI,UAAU;GAEZ,MAAM,eAAe;GACrB;EACF;EACA,SAAS,MAAM,WAAW;CAC5B;CAEA,MAAM,aAAa,UAAsC;EACvD,IAAI,MAAM,oBAAoB,YAAY,KAAK,GAAG;EAClD,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;EAChD,IAAI,MAAM,QAAQ,OAAO,MAAM,YAAY,GAAG;EAE9C,MAAM,eAAe;EACrB,IAAI,UAAU;EAId,MAAM,cAAc,MAAM;CAC5B;CAEA,MAAM,iBAAiB,UAAqC;EAC1D,MAAM,UAAU,MAAM;EACtB,IAAI,QAAQ,cAAc,kBAAkB,SAAS,QAAQ,MAAM;CACrE;CAEA,OAAO;EACL;EACA,cAAc;GACZ;GACA,UAAU,MAAM,qBAAqB,OAAO,KAAA,IAAY;GACxD,iBAAiB,WAAW,OAAO,KAAA;GAGnC,UAAU,KAAA;GACV,iBAAiB,SAAS,QAAQ;GAClC,kBAAkB;GAClB;GACA;GACA;EACF;CACF;AACF"}
@@ -0,0 +1,28 @@
1
+ import "../internal/platform-attributes.mjs";
2
+ import { PopoverClose, PopoverCloseProps, PopoverCloseState } from "./popover-close.mjs";
3
+ import { PopoverAlign, PopoverPopup, PopoverPopupProps, PopoverPopupState, PopoverSide } from "./popover-popup.mjs";
4
+ import { PopoverDescription, PopoverDescriptionProps, PopoverDescriptionState } from "./popover-description.mjs";
5
+ import { PopoverOpenChangeDetails, PopoverRoot, PopoverRootProps, PopoverRootState } from "./popover-root.mjs";
6
+ import { PopoverTitle, PopoverTitleProps, PopoverTitleState } from "./popover-title.mjs";
7
+ import { PopoverTrigger, PopoverTriggerProps, PopoverTriggerState } from "./popover-trigger.mjs";
8
+ //#region src/popover/index.d.ts
9
+ /**
10
+ * Popover built on `popover="auto"` and Invoker Commands: `Root` (no DOM) > `Trigger`
11
+ * (`button[command=toggle-popover]`) + `Popup` (`dialog[popover=auto][aria-modal=false]`) >
12
+ * `Title`, `Description`, `Close`. The platform gives the top layer, light dismiss, Escape,
13
+ * nesting, the implicit anchor and focus return. JS-free when the Root has none of `open` /
14
+ * `defaultOpen` / `openChangeAction`; otherwise opening and the closes a part asks for are
15
+ * transitions (pending Trigger, content from committed state), and dismissals are notified
16
+ * through `openChangeAction(false)`.
17
+ */
18
+ export declare const Popover: {
19
+ readonly Root: typeof PopoverRoot;
20
+ readonly Trigger: typeof PopoverTrigger;
21
+ readonly Popup: typeof PopoverPopup;
22
+ readonly Close: typeof PopoverClose;
23
+ readonly Title: typeof PopoverTitle;
24
+ readonly Description: typeof PopoverDescription;
25
+ };
26
+ //#endregion
27
+ export type { PopoverAlign, PopoverCloseProps, PopoverCloseState, PopoverDescriptionProps, PopoverDescriptionState, PopoverOpenChangeDetails, PopoverPopupProps, PopoverPopupState, PopoverRootProps, PopoverRootState, PopoverSide, PopoverTitleProps, PopoverTitleState, PopoverTriggerProps, PopoverTriggerState };
28
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/popover/index.ts"],"mappings":";;;;;;;;;;;;;;;;;qBAmBa;WACX,aAAI;WACJ,gBAAO;WACP,cAAK;WACL,cAAK;WACL,cAAK;WACL,oBAAW"}
@@ -0,0 +1,28 @@
1
+ import { PopoverClose } from "./popover-close.mjs";
2
+ import { PopoverDescription } from "./popover-description.mjs";
3
+ import { PopoverPopup } from "./popover-popup.mjs";
4
+ import { PopoverRoot } from "./popover-root.mjs";
5
+ import { PopoverTitle } from "./popover-title.mjs";
6
+ import { PopoverTrigger } from "./popover-trigger.mjs";
7
+ //#region src/popover/index.ts
8
+ /**
9
+ * Popover built on `popover="auto"` and Invoker Commands: `Root` (no DOM) > `Trigger`
10
+ * (`button[command=toggle-popover]`) + `Popup` (`dialog[popover=auto][aria-modal=false]`) >
11
+ * `Title`, `Description`, `Close`. The platform gives the top layer, light dismiss, Escape,
12
+ * nesting, the implicit anchor and focus return. JS-free when the Root has none of `open` /
13
+ * `defaultOpen` / `openChangeAction`; otherwise opening and the closes a part asks for are
14
+ * transitions (pending Trigger, content from committed state), and dismissals are notified
15
+ * through `openChangeAction(false)`.
16
+ */
17
+ const Popover = {
18
+ Root: PopoverRoot,
19
+ Trigger: PopoverTrigger,
20
+ Popup: PopoverPopup,
21
+ Close: PopoverClose,
22
+ Title: PopoverTitle,
23
+ Description: PopoverDescription
24
+ };
25
+ //#endregion
26
+ export { Popover };
27
+
28
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/popover/index.ts"],"sourcesContent":["// Ships the platform attribute typings (`command`, `commandfor`) with this subpath\n// (conventions 7.4). Type-only: the built JS has no import of it.\nimport \"../internal/platform-attributes.js\";\nimport { PopoverClose } from \"./popover-close.js\";\nimport { PopoverDescription } from \"./popover-description.js\";\nimport { PopoverPopup } from \"./popover-popup.js\";\nimport { PopoverRoot } from \"./popover-root.js\";\nimport { PopoverTitle } from \"./popover-title.js\";\nimport { PopoverTrigger } from \"./popover-trigger.js\";\n\n/**\n * Popover built on `popover=\"auto\"` and Invoker Commands: `Root` (no DOM) > `Trigger`\n * (`button[command=toggle-popover]`) + `Popup` (`dialog[popover=auto][aria-modal=false]`) >\n * `Title`, `Description`, `Close`. The platform gives the top layer, light dismiss, Escape,\n * nesting, the implicit anchor and focus return. JS-free when the Root has none of `open` /\n * `defaultOpen` / `openChangeAction`; otherwise opening and the closes a part asks for are\n * transitions (pending Trigger, content from committed state), and dismissals are notified\n * through `openChangeAction(false)`.\n */\nexport const Popover = {\n Root: PopoverRoot,\n Trigger: PopoverTrigger,\n Popup: PopoverPopup,\n Close: PopoverClose,\n Title: PopoverTitle,\n Description: PopoverDescription,\n} as const;\n\nexport type {\n PopoverRootProps,\n PopoverRootState,\n PopoverOpenChangeDetails,\n} from \"./popover-root.js\";\nexport type { PopoverTriggerProps, PopoverTriggerState } from \"./popover-trigger.js\";\nexport type {\n PopoverPopupProps,\n PopoverPopupState,\n PopoverSide,\n PopoverAlign,\n} from \"./popover-popup.js\";\nexport type { PopoverCloseProps, PopoverCloseState } from \"./popover-close.js\";\nexport type { PopoverTitleProps, PopoverTitleState } from \"./popover-title.js\";\nexport type { PopoverDescriptionProps, PopoverDescriptionState } from \"./popover-description.js\";\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,MAAa,UAAU;CACrB,MAAM;CACN,SAAS;CACT,OAAO;CACP,OAAO;CACP,OAAO;CACP,aAAa;AACf"}
@@ -0,0 +1,41 @@
1
+ import { Action, ActionDetails, RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode } from "react";
3
+ //#region src/popover/popover-close.d.ts
4
+ export interface PopoverCloseState {
5
+ /** The `action` is in flight. */
6
+ readonly pending: boolean;
7
+ readonly disabled: boolean;
8
+ }
9
+ export interface PopoverCloseProps extends Omit<ComponentPropsWithRef<"button">, "onClick" | "className" | "style" | "children"> {
10
+ /**
11
+ * Runs inside this part's own transition (`data-pending` on the button), then closes the
12
+ * popover: in library mode through the Root (`openChangeAction(false)` awaited, view
13
+ * transition if set), in JS-free mode with `hidePopover()`. A rejection reaches the nearest
14
+ * Error Boundary above the Close part and leaves the popover open. If the popover was
15
+ * dismissed and opened again while the action ran, the close is dropped. Without `action` in JS-free
16
+ * mode the button is a native `command="hide-popover"` invoker.
17
+ */
18
+ action?: Action<[details: ActionDetails]>;
19
+ /** Native `disabled`; owned, so a `render` element cannot re-enable the button. */
20
+ disabled?: boolean;
21
+ className?: StateValue<string | undefined, PopoverCloseState>;
22
+ style?: StateValue<CSSProperties | undefined, PopoverCloseState>;
23
+ children?: StateValue<ReactNode, PopoverCloseState>;
24
+ render?: RenderProp<ComponentPropsWithRef<"button">, PopoverCloseState>;
25
+ }
26
+ /**
27
+ * A close button: `<button type="button" commandfor command="hide-popover">`. In JS-free mode
28
+ * without `action` the browser hides the popover. In library mode the click is always cancelled
29
+ * and the close goes through the Root (`openChangeAction(false)` awaited, `hidePopover()` in the
30
+ * commit). With `action` the action runs first in this part's own transition (`data-pending` on
31
+ * the button); a rejection leaves the popover open.
32
+ *
33
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
34
+ * `command`, `onClick` (library mode, or with `action`), `data-pending`, `data-disabled`.
35
+ */
36
+ export declare function PopoverClose({ action, disabled, className, style, children, render, ...rest }: PopoverCloseProps): ReactNode;
37
+ export declare namespace PopoverClose {
38
+ var displayName: string;
39
+ }
40
+ //#endregion
41
+ //# sourceMappingURL=popover-close.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-close.d.mts","names":[],"sources":["../../src/popover/popover-close.tsx"],"mappings":";;;iBAWiB;;WAEN;WACA;;iBAGM,0BAA0B,KACzC;;;;;;;;;EAWA,SAAS,QAAQ,SAAS;;EAE1B;EACA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;wBAuBvC,eACd,QACA,UACA,WACA,OACA,UACA,WACG,QACF,oBAAiB;yBARJ"}
@@ -0,0 +1,90 @@
1
+ "use client";
2
+ import { createActionDetails } from "../internal/action-details.mjs";
3
+ import { dataAttr } from "../internal/data-attr.mjs";
4
+ import { rendersButton, useRender } from "../internal/use-render.mjs";
5
+ import { useActionTrigger } from "../internal/use-action-trigger.mjs";
6
+ import { usePopoverContext } from "./popover-context.mjs";
7
+ import { useCallback } from "react";
8
+ //#region src/popover/popover-close.tsx
9
+ const isDev = process.env.NODE_ENV !== "production";
10
+ function isPopoverOpen(element) {
11
+ try {
12
+ return element.matches(":popover-open");
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+ /**
18
+ * A close button: `<button type="button" commandfor command="hide-popover">`. In JS-free mode
19
+ * without `action` the browser hides the popover. In library mode the click is always cancelled
20
+ * and the close goes through the Root (`openChangeAction(false)` awaited, `hidePopover()` in the
21
+ * commit). With `action` the action runs first in this part's own transition (`data-pending` on
22
+ * the button); a rejection leaves the popover open.
23
+ *
24
+ * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,
25
+ * `command`, `onClick` (library mode, or with `action`), `data-pending`, `data-disabled`.
26
+ */
27
+ function PopoverClose({ action, disabled = false, className, style, children, render, ...rest }) {
28
+ const ctx = usePopoverContext("Popover.Close");
29
+ const { ids, popupRef, recordCloseIntent, openGeneration } = ctx;
30
+ const { pending, run } = useActionTrigger(openGeneration);
31
+ const isLibrary = ctx.mode === "library";
32
+ const installClick = isLibrary || action !== void 0;
33
+ const state = {
34
+ pending,
35
+ disabled
36
+ };
37
+ const devRef = useCallback((element) => {
38
+ if (isDev && !installClick && element.tagName !== "BUTTON") console.error(`Popover.Close: rendered a <${element.tagName.toLowerCase()}> in JS-free mode without \`action\`. Only a <button> runs \`command="hide-popover"\`; this element will not close the popover.`);
39
+ return () => {};
40
+ }, [installClick]);
41
+ const close = (event) => {
42
+ if (isLibrary) {
43
+ ctx.requestClose(event, "activate");
44
+ return;
45
+ }
46
+ const popup = popupRef.current;
47
+ if (popup === null || !popup.isConnected || !isPopoverOpen(popup)) return;
48
+ recordCloseIntent({
49
+ reason: "activate",
50
+ event
51
+ });
52
+ popup.hidePopover();
53
+ };
54
+ const onClick = (event) => {
55
+ event.preventDefault();
56
+ if (disabled) return;
57
+ const native = event.nativeEvent;
58
+ if (action === void 0) {
59
+ close(native);
60
+ return;
61
+ }
62
+ const details = createActionDetails(native, {});
63
+ run(() => action(details), () => close(native));
64
+ };
65
+ const libraryProps = {
66
+ ...rendersButton(render) && { type: "button" },
67
+ disabled,
68
+ commandfor: ids.popup,
69
+ command: "hide-popover",
70
+ ...installClick && { onClick },
71
+ "data-pending": dataAttr(pending),
72
+ "data-disabled": dataAttr(disabled)
73
+ };
74
+ return useRender({
75
+ defaultElement: "button",
76
+ render,
77
+ state,
78
+ className,
79
+ style,
80
+ children,
81
+ props: rest,
82
+ libraryProps,
83
+ ref: devRef
84
+ });
85
+ }
86
+ PopoverClose.displayName = "PopoverClose";
87
+ //#endregion
88
+ export { PopoverClose };
89
+
90
+ //# sourceMappingURL=popover-close.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-close.mjs","names":[],"sources":["../../src/popover/popover-close.tsx"],"sourcesContent":["\"use client\";\nimport { useCallback } from \"react\";\nimport type { ComponentPropsWithRef, CSSProperties, MouseEvent, ReactNode } from \"react\";\nimport { createActionDetails } from \"../internal/action-details.js\";\nimport { dataAttr } from \"../internal/data-attr.js\";\nimport type { Action, ActionDetails, RenderProp, StateValue } from \"../internal/types.js\";\nimport { useActionTrigger } from \"../internal/use-action-trigger.js\";\nimport { rendersButton, useRender } from \"../internal/use-render.js\";\nimport type { DataAttributes } from \"../internal/use-render.js\";\nimport { usePopoverContext } from \"./popover-context.js\";\n\nexport interface PopoverCloseState {\n /** The `action` is in flight. */\n readonly pending: boolean;\n readonly disabled: boolean;\n}\n\nexport interface PopoverCloseProps extends Omit<\n ComponentPropsWithRef<\"button\">,\n \"onClick\" | \"className\" | \"style\" | \"children\"\n> {\n /**\n * Runs inside this part's own transition (`data-pending` on the button), then closes the\n * popover: in library mode through the Root (`openChangeAction(false)` awaited, view\n * transition if set), in JS-free mode with `hidePopover()`. A rejection reaches the nearest\n * Error Boundary above the Close part and leaves the popover open. If the popover was\n * dismissed and opened again while the action ran, the close is dropped. Without `action` in JS-free\n * mode the button is a native `command=\"hide-popover\"` invoker.\n */\n action?: Action<[details: ActionDetails]>;\n /** Native `disabled`; owned, so a `render` element cannot re-enable the button. */\n disabled?: boolean;\n className?: StateValue<string | undefined, PopoverCloseState>;\n style?: StateValue<CSSProperties | undefined, PopoverCloseState>;\n children?: StateValue<ReactNode, PopoverCloseState>;\n render?: RenderProp<ComponentPropsWithRef<\"button\">, PopoverCloseState>;\n}\n\nconst isDev = process.env.NODE_ENV !== \"production\";\n\nfunction isPopoverOpen(element: Element): boolean {\n try {\n return element.matches(\":popover-open\");\n } catch {\n return false;\n }\n}\n\n/**\n * A close button: `<button type=\"button\" commandfor command=\"hide-popover\">`. In JS-free mode\n * without `action` the browser hides the popover. In library mode the click is always cancelled\n * and the close goes through the Root (`openChangeAction(false)` awaited, `hidePopover()` in the\n * commit). With `action` the action runs first in this part's own transition (`data-pending` on\n * the button); a rejection leaves the popover open.\n *\n * Owned keys (conventions 1.2): `type` (on a `<button>` only), `disabled`, `commandfor`,\n * `command`, `onClick` (library mode, or with `action`), `data-pending`, `data-disabled`.\n */\nexport function PopoverClose({\n action,\n disabled = false,\n className,\n style,\n children,\n render,\n ...rest\n}: PopoverCloseProps) {\n const ctx = usePopoverContext(\"Popover.Close\");\n const { ids, popupRef, recordCloseIntent, openGeneration } = ctx;\n const { pending, run } = useActionTrigger(openGeneration);\n const isLibrary = ctx.mode === \"library\";\n const hasAction = action !== undefined;\n const installClick = isLibrary || hasAction;\n\n const state: PopoverCloseState = { pending, disabled };\n\n const devRef = useCallback(\n (element: HTMLElement) => {\n if (isDev && !installClick && element.tagName !== \"BUTTON\") {\n console.error(\n `Popover.Close: rendered a <${element.tagName.toLowerCase()}> in JS-free mode without ` +\n '`action`. Only a <button> runs `command=\"hide-popover\"`; this element will not ' +\n \"close the popover.\",\n );\n }\n // A cleanup, so the merged ref never calls back with `null`.\n return () => {};\n },\n [installClick],\n );\n\n const close = (event: Event): void => {\n if (isLibrary) {\n // A library-owned close (design 2.3): awaited, then hidden in the commit.\n ctx.requestClose(event, \"activate\");\n return;\n }\n // JS-free mode with `action`: a browser-owned close; there is no Root state to notify.\n const popup = popupRef.current;\n if (popup === null || !popup.isConnected || !isPopoverOpen(popup)) return;\n recordCloseIntent({ reason: \"activate\", event });\n popup.hidePopover();\n };\n\n const onClick = (event: MouseEvent<HTMLElement>) => {\n // Cancelling the click cancels the command.\n event.preventDefault();\n if (disabled) return;\n const native = event.nativeEvent;\n if (action === undefined) {\n close(native);\n return;\n }\n const details = createActionDetails(native, {});\n // Repeated clicks re-run the action; the first close wins (design 3.4). A close whose open\n // was superseded by a newer one (dismissed and re-opened meanwhile) is dropped by the hook.\n run(\n () => action(details),\n () => close(native),\n );\n };\n\n const libraryProps: ComponentPropsWithRef<\"button\"> & DataAttributes = {\n ...(rendersButton(render) && { type: \"button\" as const }),\n // Owned: a render element must not re-enable a disabled Close.\n disabled,\n commandfor: ids.popup,\n command: \"hide-popover\",\n ...(installClick && { onClick }),\n \"data-pending\": dataAttr(pending),\n \"data-disabled\": dataAttr(disabled),\n };\n\n return useRender<ComponentPropsWithRef<\"button\">, PopoverCloseState>({\n defaultElement: \"button\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps,\n ref: devRef,\n });\n}\n\nPopoverClose.displayName = \"PopoverClose\";\n"],"mappings":";;;;;;;;AAsCA,MAAM,QAAQ,QAAQ,IAAI,aAAa;AAEvC,SAAS,cAAc,SAA2B;CAChD,IAAI;EACF,OAAO,QAAQ,QAAQ,eAAe;CACxC,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;AAYA,SAAgB,aAAa,EAC3B,QACA,WAAW,OACX,WACA,OACA,UACA,QACA,GAAG,QACiB;CACpB,MAAM,MAAM,kBAAkB,eAAe;CAC7C,MAAM,EAAE,KAAK,UAAU,mBAAmB,mBAAmB;CAC7D,MAAM,EAAE,SAAS,QAAQ,iBAAiB,cAAc;CACxD,MAAM,YAAY,IAAI,SAAS;CAE/B,MAAM,eAAe,aADH,WAAW,KAAA;CAG7B,MAAM,QAA2B;EAAE;EAAS;CAAS;CAErD,MAAM,SAAS,aACZ,YAAyB;EACxB,IAAI,SAAS,CAAC,gBAAgB,QAAQ,YAAY,UAChD,QAAQ,MACN,8BAA8B,QAAQ,QAAQ,YAAY,EAAE,gIAG9D;EAGF,aAAa,CAAC;CAChB,GACA,CAAC,YAAY,CACf;CAEA,MAAM,SAAS,UAAuB;EACpC,IAAI,WAAW;GAEb,IAAI,aAAa,OAAO,UAAU;GAClC;EACF;EAEA,MAAM,QAAQ,SAAS;EACvB,IAAI,UAAU,QAAQ,CAAC,MAAM,eAAe,CAAC,cAAc,KAAK,GAAG;EACnE,kBAAkB;GAAE,QAAQ;GAAY;EAAM,CAAC;EAC/C,MAAM,YAAY;CACpB;CAEA,MAAM,WAAW,UAAmC;EAElD,MAAM,eAAe;EACrB,IAAI,UAAU;EACd,MAAM,SAAS,MAAM;EACrB,IAAI,WAAW,KAAA,GAAW;GACxB,MAAM,MAAM;GACZ;EACF;EACA,MAAM,UAAU,oBAAoB,QAAQ,CAAC,CAAC;EAG9C,UACQ,OAAO,OAAO,SACd,MAAM,MAAM,CACpB;CACF;CAEA,MAAM,eAAiE;EACrE,GAAI,cAAc,MAAM,KAAK,EAAE,MAAM,SAAkB;EAEvD;EACA,YAAY,IAAI;EAChB,SAAS;EACT,GAAI,gBAAgB,EAAE,QAAQ;EAC9B,gBAAgB,SAAS,OAAO;EAChC,iBAAiB,SAAS,QAAQ;CACpC;CAEA,OAAO,UAA8D;EACnE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA,KAAK;CACP,CAAC;AACH;AAEA,aAAa,cAAc"}
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { createContext, use } from "react";
3
+ //#region src/popover/popover-context.ts
4
+ const PopoverContext = createContext(null);
5
+ function usePopoverContext(part) {
6
+ const context = use(PopoverContext);
7
+ if (context === null) throw new Error(`${part} must be rendered inside a Popover.Root.`);
8
+ return context;
9
+ }
10
+ /** The Popup's state, for Title and Description rendered inside it. */
11
+ const PopoverPopupContext = createContext(null);
12
+ /**
13
+ * The state Title and Description receive: the enclosing Popup's, or (outside a Popup, which
14
+ * `aria-labelledby` allows) the Root's committed open state with the default placement.
15
+ */
16
+ function usePopoverPopupState(ctx) {
17
+ return use(PopoverPopupContext) ?? {
18
+ open: ctx.committed,
19
+ side: "bottom",
20
+ align: "center"
21
+ };
22
+ }
23
+ //#endregion
24
+ export { PopoverContext, PopoverPopupContext, usePopoverContext, usePopoverPopupState };
25
+
26
+ //# sourceMappingURL=popover-context.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-context.mjs","names":[],"sources":["../../src/popover/popover-context.ts"],"sourcesContent":["\"use client\";\nimport { createContext, use } from \"react\";\nimport type { PopoverRootValue } from \"../internal/use-popover-root.js\";\nimport type { PopoverPopupState } from \"./popover-popup.js\";\n\nexport type PopoverContextValue = PopoverRootValue;\n\nexport const PopoverContext = createContext<PopoverContextValue | null>(null);\n\nexport function usePopoverContext(part: string): PopoverContextValue {\n const context = use(PopoverContext);\n if (context === null) {\n throw new Error(`${part} must be rendered inside a Popover.Root.`);\n }\n return context;\n}\n\n/** The Popup's state, for Title and Description rendered inside it. */\nexport const PopoverPopupContext = createContext<PopoverPopupState | null>(null);\n\n/**\n * The state Title and Description receive: the enclosing Popup's, or (outside a Popup, which\n * `aria-labelledby` allows) the Root's committed open state with the default placement.\n */\nexport function usePopoverPopupState(ctx: PopoverContextValue): PopoverPopupState {\n return use(PopoverPopupContext) ?? { open: ctx.committed, side: \"bottom\", align: \"center\" };\n}\n"],"mappings":";;;AAOA,MAAa,iBAAiB,cAA0C,IAAI;AAE5E,SAAgB,kBAAkB,MAAmC;CACnE,MAAM,UAAU,IAAI,cAAc;CAClC,IAAI,YAAY,MACd,MAAM,IAAI,MAAM,GAAG,KAAK,yCAAyC;CAEnE,OAAO;AACT;;AAGA,MAAa,sBAAsB,cAAwC,IAAI;;;;;AAM/E,SAAgB,qBAAqB,KAA6C;CAChF,OAAO,IAAI,mBAAmB,KAAK;EAAE,MAAM,IAAI;EAAW,MAAM;EAAU,OAAO;CAAS;AAC5F"}
@@ -0,0 +1,22 @@
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-description.d.ts
5
+ export type PopoverDescriptionState = PopoverPopupState;
6
+ export interface PopoverDescriptionProps extends Omit<ComponentPropsWithRef<"p">, "id" | "className" | "style" | "children"> {
7
+ className?: StateValue<string | undefined, PopoverDescriptionState>;
8
+ style?: StateValue<CSSProperties | undefined, PopoverDescriptionState>;
9
+ children?: StateValue<ReactNode, PopoverDescriptionState>;
10
+ render?: RenderProp<ComponentPropsWithRef<"p">, PopoverDescriptionState>;
11
+ }
12
+ /**
13
+ * The popover's description: a `<p>` whose id the Popup references with `aria-describedby`.
14
+ *
15
+ * Owned key (conventions 1.2): `id`.
16
+ */
17
+ export declare function PopoverDescription({ className, style, children, render, ...rest }: PopoverDescriptionProps): ReactNode;
18
+ export declare namespace PopoverDescription {
19
+ var displayName: string;
20
+ }
21
+ //#endregion
22
+ //# sourceMappingURL=popover-description.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-description.d.mts","names":[],"sources":["../../src/popover/popover-description.tsx"],"mappings":";;;;YAOY,0BAA0B;iBAErB,gCAAgC,KAC/C;EAGA,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;EACjC,SAAS,WAAW,4BAA4B;;;;;;;wBAQlC,qBACd,WACA,OACA,UACA,WACG,QACF,0BAAuB;yBANV"}
@@ -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-description.tsx
5
+ /**
6
+ * The popover's description: a `<p>` whose id the Popup references with `aria-describedby`.
7
+ *
8
+ * Owned key (conventions 1.2): `id`.
9
+ */
10
+ function PopoverDescription({ className, style, children, render, ...rest }) {
11
+ const ctx = usePopoverContext("Popover.Description");
12
+ const state = usePopoverPopupState(ctx);
13
+ return useRender({
14
+ defaultElement: "p",
15
+ render,
16
+ state,
17
+ className,
18
+ style,
19
+ children,
20
+ props: rest,
21
+ libraryProps: { id: ctx.ids.description }
22
+ });
23
+ }
24
+ PopoverDescription.displayName = "PopoverDescription";
25
+ //#endregion
26
+ export { PopoverDescription };
27
+
28
+ //# sourceMappingURL=popover-description.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-description.mjs","names":[],"sources":["../../src/popover/popover-description.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 PopoverDescriptionState = PopoverPopupState;\n\nexport interface PopoverDescriptionProps extends Omit<\n ComponentPropsWithRef<\"p\">,\n \"id\" | \"className\" | \"style\" | \"children\"\n> {\n className?: StateValue<string | undefined, PopoverDescriptionState>;\n style?: StateValue<CSSProperties | undefined, PopoverDescriptionState>;\n children?: StateValue<ReactNode, PopoverDescriptionState>;\n render?: RenderProp<ComponentPropsWithRef<\"p\">, PopoverDescriptionState>;\n}\n\n/**\n * The popover's description: a `<p>` whose id the Popup references with `aria-describedby`.\n *\n * Owned key (conventions 1.2): `id`.\n */\nexport function PopoverDescription({\n className,\n style,\n children,\n render,\n ...rest\n}: PopoverDescriptionProps) {\n const ctx = usePopoverContext(\"Popover.Description\");\n const state = usePopoverPopupState(ctx);\n return useRender<ComponentPropsWithRef<\"p\">, PopoverDescriptionState>({\n defaultElement: \"p\",\n render,\n state,\n className,\n style,\n children,\n props: rest,\n libraryProps: { id: ctx.ids.description },\n });\n}\n\nPopoverDescription.displayName = \"PopoverDescription\";\n"],"mappings":";;;;;;;;;AAwBA,SAAgB,mBAAmB,EACjC,WACA,OACA,UACA,QACA,GAAG,QACuB;CAC1B,MAAM,MAAM,kBAAkB,qBAAqB;CACnD,MAAM,QAAQ,qBAAqB,GAAG;CACtC,OAAO,UAA+D;EACpE,gBAAgB;EAChB;EACA;EACA;EACA;EACA;EACA,OAAO;EACP,cAAc,EAAE,IAAI,IAAI,IAAI,YAAY;CAC1C,CAAC;AACH;AAEA,mBAAmB,cAAc"}
@@ -0,0 +1,82 @@
1
+ import { RenderProp, StateValue } from "../internal/types.mjs";
2
+ import { CSSProperties, ComponentPropsWithRef, ReactNode, RefObject, ViewTransitionClass } from "react";
3
+ //#region src/popover/popover-popup.d.ts
4
+ export type PopoverSide = "top" | "bottom" | "left" | "right";
5
+ export type PopoverAlign = "start" | "center" | "end";
6
+ export interface PopoverPopupState {
7
+ /** Committed open state (library mode); `false` in JS-free mode. Read `:popover-open` for the DOM truth. */
8
+ readonly open: boolean;
9
+ readonly side: PopoverSide | null;
10
+ readonly align: PopoverAlign;
11
+ }
12
+ export interface PopoverPopupProps extends Omit<ComponentPropsWithRef<"dialog">, "id" | "popover" | "open" | "aria-modal" | "onToggle" | "onBeforeToggle" | "className" | "style" | "children"> {
13
+ /**
14
+ * Placement relative to the Trigger through inline `position-area`, with
15
+ * `position-try-fallbacks` flipping it when it does not fit. Default `"bottom"`. `null` emits
16
+ * no inline positioning (and no `data-side` / `data-align`), so a stylesheet owns placement.
17
+ */
18
+ side?: PopoverSide | null;
19
+ /** Alignment along the side. Default `"center"`. Ignored when `side` is `null`. */
20
+ align?: PopoverAlign;
21
+ /**
22
+ * Library mode: what happens to the children while the popover is closed.
23
+ * - `false` (default): not rendered. Mounting them is part of the opening transition, so
24
+ * content that suspends holds the open until it is ready. Unmount waits for the popover's
25
+ * exit animation (CSS), or happens in the close commit when `transition` is set.
26
+ * - `true`: rendered inside `<Activity mode="hidden">`: DOM and state preserved, effects
27
+ * stopped, pre-rendered at low priority. Not in the server HTML.
28
+ *
29
+ * Ignored in JS-free mode (always mounted).
30
+ */
31
+ keepMounted?: boolean;
32
+ /**
33
+ * Element to focus when the popover opens: a ref, or a selector resolved inside the popup.
34
+ * The library writes `autofocus` on it right before `showPopover()` and the platform focuses
35
+ * it. Default: the platform's choice for a `<dialog>` (first focusable descendant; the popup
36
+ * itself if none); for `render={<div />}` focus stays on the Trigger.
37
+ *
38
+ * In JS-free mode the browser opens the popover itself, so the attribute is written after
39
+ * hydration and kept while mounted; before hydration only `autoFocus` in the markup works.
40
+ */
41
+ initialFocus?: RefObject<HTMLElement | null> | string;
42
+ /**
43
+ * Library mode only. Forwarded to the `<ViewTransition default>` around the popover element
44
+ * itself. Animates the opening commit, content changes while open, and every library-driven
45
+ * close (Trigger, Close, controlled `open={false}`), in all engines; dismissals (Escape,
46
+ * click outside) are the browser's and animate with CSS only. Ignored (dev warning) in JS-free
47
+ * mode.
48
+ *
49
+ * Static: without `transition` the part renders no `<ViewTransition>`; changing it between
50
+ * `undefined` and a value remounts the element. A Root inserted by a transition with
51
+ * `transition` set on its Popup pays the page cross-fade (issue #35); a plain open does not,
52
+ * because the children mount under the already-mounted popover element.
53
+ */
54
+ transition?: ViewTransitionClass;
55
+ className?: StateValue<string | undefined, PopoverPopupState>;
56
+ style?: StateValue<CSSProperties | undefined, PopoverPopupState>;
57
+ children?: StateValue<ReactNode, PopoverPopupState>;
58
+ /** A `<dialog>` (default) or a `<div>` (focus stays on the Trigger). */
59
+ render?: RenderProp<ComponentPropsWithRef<"dialog">, PopoverPopupState>;
60
+ }
61
+ /**
62
+ * The popover itself: a `<dialog popover="auto" aria-modal="false" role="dialog">` with the id
63
+ * the Trigger's `commandfor` names, placed against the Trigger with CSS Anchor Positioning and
64
+ * wired to Title and Description through `aria-labelledby` / `aria-describedby`. Style it with
65
+ * `:popover-open`; it emits `data-side` / `data-align` but no `data-open`.
66
+ *
67
+ * In library mode the children render from committed state, so content that suspends keeps the
68
+ * popover closed (and the Trigger pending) until it is ready; `showPopover({ source: trigger })`
69
+ * runs in the layout effect of the commit that mounted them, and a library-driven close runs
70
+ * `hidePopover()` in the commit that ends it. Dismissals are the browser's: the native `toggle`
71
+ * event becomes `openChangeAction(false, { reason: "dismiss" })`.
72
+ *
73
+ * Owned keys (conventions 1.2): `id`, `popover`, `open`, `aria-modal`, `aria-labelledby` and
74
+ * `aria-describedby` (token-merged), and `data-side` / `data-align` unless `side` is `null`.
75
+ * `role` is a default (`"dialog"`) the consumer may override.
76
+ */
77
+ export declare function PopoverPopup({ side, align, keepMounted, initialFocus, transition, className, style, children, render, ...rest }: PopoverPopupProps): ReactNode;
78
+ export declare namespace PopoverPopup {
79
+ var displayName: string;
80
+ }
81
+ //#endregion
82
+ //# sourceMappingURL=popover-popup.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-popup.d.mts","names":[],"sources":["../../src/popover/popover-popup.tsx"],"mappings":";;;YAkBY;YACA;iBAEK;;WAEN;WACA,MAAM;WACN,OAAO;;iBAGD,0BAA0B,KACzC;;;;;;EAgBA,OAAO;;EAEP,QAAQ;;;;;;;;;;;EAWR;;;;;;;;;;EAUA,eAAe,UAAU;;;;;;;;;;;;;EAazB,aAAa;EACb,YAAY,+BAA+B;EAC3C,QAAQ,WAAW,2BAA2B;EAC9C,WAAW,WAAW,WAAW;;EAEjC,SAAS,WAAW,iCAAiC;;;;;;;;;;;;;;;;;;wBAmBvC,eACd,MACA,OACA,aACA,cACA,YACA,WACA,OACA,UACA,WACG,QACF,oBAAiB;yBAXJ"}
@@ -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"}