@funstack/ui 0.1.0-alpha.0 → 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 (154) 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/dialog/dialog-close.d.mts.map +1 -1
  25. package/dist/dialog/dialog-close.mjs +4 -4
  26. package/dist/dialog/dialog-close.mjs.map +1 -1
  27. package/dist/dialog/dialog-context.mjs.map +1 -1
  28. package/dist/dialog/dialog-popup.mjs +1 -0
  29. package/dist/dialog/dialog-popup.mjs.map +1 -1
  30. package/dist/dialog/dialog-root.mjs +9 -1
  31. package/dist/dialog/dialog-root.mjs.map +1 -1
  32. package/dist/index.d.mts +23 -1
  33. package/dist/index.mjs +4 -1
  34. package/dist/internal/anchor-position.d.mts +7 -0
  35. package/dist/internal/anchor-position.d.mts.map +1 -0
  36. package/dist/internal/anchor-position.mjs +16 -0
  37. package/dist/internal/anchor-position.mjs.map +1 -0
  38. package/dist/internal/platform-attributes.d.mts +6 -0
  39. package/dist/internal/platform-attributes.d.mts.map +1 -1
  40. package/dist/internal/sync-presence.mjs +19 -0
  41. package/dist/internal/sync-presence.mjs.map +1 -0
  42. package/dist/internal/use-action-trigger.mjs +58 -0
  43. package/dist/internal/use-action-trigger.mjs.map +1 -0
  44. package/dist/internal/use-delayed-pair.mjs +40 -0
  45. package/dist/internal/use-delayed-pair.mjs.map +1 -0
  46. package/dist/internal/use-exit-animation.mjs +55 -0
  47. package/dist/internal/use-exit-animation.mjs.map +1 -0
  48. package/dist/internal/use-native-group-reconciliation.mjs +2 -2
  49. package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
  50. package/dist/internal/use-popover-popup.mjs +274 -0
  51. package/dist/internal/use-popover-popup.mjs.map +1 -0
  52. package/dist/internal/use-popover-root.d.mts +2 -0
  53. package/dist/internal/use-popover-root.mjs +112 -0
  54. package/dist/internal/use-popover-root.mjs.map +1 -0
  55. package/dist/internal/use-popover-trigger.mjs +86 -0
  56. package/dist/internal/use-popover-trigger.mjs.map +1 -0
  57. package/dist/menu/index.d.mts +34 -0
  58. package/dist/menu/index.d.mts.map +1 -0
  59. package/dist/menu/index.mjs +34 -0
  60. package/dist/menu/index.mjs.map +1 -0
  61. package/dist/menu/menu-checkbox-item.d.mts +42 -0
  62. package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
  63. package/dist/menu/menu-checkbox-item.mjs +71 -0
  64. package/dist/menu/menu-checkbox-item.mjs.map +1 -0
  65. package/dist/menu/menu-context.d.mts +1 -0
  66. package/dist/menu/menu-context.mjs +28 -0
  67. package/dist/menu/menu-context.mjs.map +1 -0
  68. package/dist/menu/menu-dom.mjs +37 -0
  69. package/dist/menu/menu-dom.mjs.map +1 -0
  70. package/dist/menu/menu-group.d.mts +48 -0
  71. package/dist/menu/menu-group.d.mts.map +1 -0
  72. package/dist/menu/menu-group.mjs +69 -0
  73. package/dist/menu/menu-group.mjs.map +1 -0
  74. package/dist/menu/menu-hover.mjs +29 -0
  75. package/dist/menu/menu-hover.mjs.map +1 -0
  76. package/dist/menu/menu-item.d.mts +45 -0
  77. package/dist/menu/menu-item.d.mts.map +1 -0
  78. package/dist/menu/menu-item.mjs +54 -0
  79. package/dist/menu/menu-item.mjs.map +1 -0
  80. package/dist/menu/menu-popup.d.mts +69 -0
  81. package/dist/menu/menu-popup.d.mts.map +1 -0
  82. package/dist/menu/menu-popup.mjs +207 -0
  83. package/dist/menu/menu-popup.mjs.map +1 -0
  84. package/dist/menu/menu-radio-group.d.mts +37 -0
  85. package/dist/menu/menu-radio-group.d.mts.map +1 -0
  86. package/dist/menu/menu-radio-group.mjs +72 -0
  87. package/dist/menu/menu-radio-group.mjs.map +1 -0
  88. package/dist/menu/menu-radio-item.d.mts +33 -0
  89. package/dist/menu/menu-radio-item.d.mts.map +1 -0
  90. package/dist/menu/menu-radio-item.mjs +62 -0
  91. package/dist/menu/menu-radio-item.mjs.map +1 -0
  92. package/dist/menu/menu-root.d.mts +54 -0
  93. package/dist/menu/menu-root.d.mts.map +1 -0
  94. package/dist/menu/menu-root.mjs +102 -0
  95. package/dist/menu/menu-root.mjs.map +1 -0
  96. package/dist/menu/menu-submenu-trigger.d.mts +31 -0
  97. package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
  98. package/dist/menu/menu-submenu-trigger.mjs +92 -0
  99. package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
  100. package/dist/menu/menu-trigger.d.mts +36 -0
  101. package/dist/menu/menu-trigger.d.mts.map +1 -0
  102. package/dist/menu/menu-trigger.mjs +81 -0
  103. package/dist/menu/menu-trigger.mjs.map +1 -0
  104. package/dist/menu/use-menu-item.mjs +54 -0
  105. package/dist/menu/use-menu-item.mjs.map +1 -0
  106. package/dist/popover/index.d.mts +28 -0
  107. package/dist/popover/index.d.mts.map +1 -0
  108. package/dist/popover/index.mjs +28 -0
  109. package/dist/popover/index.mjs.map +1 -0
  110. package/dist/popover/popover-close.d.mts +41 -0
  111. package/dist/popover/popover-close.d.mts.map +1 -0
  112. package/dist/popover/popover-close.mjs +90 -0
  113. package/dist/popover/popover-close.mjs.map +1 -0
  114. package/dist/popover/popover-context.mjs +26 -0
  115. package/dist/popover/popover-context.mjs.map +1 -0
  116. package/dist/popover/popover-description.d.mts +22 -0
  117. package/dist/popover/popover-description.d.mts.map +1 -0
  118. package/dist/popover/popover-description.mjs +28 -0
  119. package/dist/popover/popover-description.mjs.map +1 -0
  120. package/dist/popover/popover-popup.d.mts +82 -0
  121. package/dist/popover/popover-popup.d.mts.map +1 -0
  122. package/dist/popover/popover-popup.mjs +93 -0
  123. package/dist/popover/popover-popup.mjs.map +1 -0
  124. package/dist/popover/popover-root.d.mts +64 -0
  125. package/dist/popover/popover-root.d.mts.map +1 -0
  126. package/dist/popover/popover-root.mjs +39 -0
  127. package/dist/popover/popover-root.mjs.map +1 -0
  128. package/dist/popover/popover-title.d.mts +23 -0
  129. package/dist/popover/popover-title.d.mts.map +1 -0
  130. package/dist/popover/popover-title.mjs +28 -0
  131. package/dist/popover/popover-title.mjs.map +1 -0
  132. package/dist/popover/popover-trigger.d.mts +37 -0
  133. package/dist/popover/popover-trigger.d.mts.map +1 -0
  134. package/dist/popover/popover-trigger.mjs +40 -0
  135. package/dist/popover/popover-trigger.mjs.map +1 -0
  136. package/dist/radio-group/radio-group-item.d.mts.map +1 -1
  137. package/dist/radio-group/radio-group-item.mjs +1 -6
  138. package/dist/radio-group/radio-group-item.mjs.map +1 -1
  139. package/dist/tabs/tabs-context.mjs +2 -1
  140. package/dist/tabs/tabs-context.mjs.map +1 -1
  141. package/dist/tabs/tabs-list.d.mts +1 -1
  142. package/dist/tabs/tabs-list.d.mts.map +1 -1
  143. package/dist/tabs/tabs-list.mjs +17 -9
  144. package/dist/tabs/tabs-list.mjs.map +1 -1
  145. package/dist/tabs/tabs-tab.d.mts +1 -1
  146. package/dist/tabs/tabs-tab.d.mts.map +1 -1
  147. package/dist/tabs/tabs-tab.mjs +6 -3
  148. package/dist/tabs/tabs-tab.mjs.map +1 -1
  149. package/dist/tooltip/tooltip-popup.d.mts.map +1 -1
  150. package/dist/tooltip/tooltip-popup.mjs +2 -7
  151. package/dist/tooltip/tooltip-popup.mjs.map +1 -1
  152. package/dist/tooltip/use-tooltip-interaction.mjs +5 -17
  153. package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -1
  154. package/package.json +4 -1
@@ -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"}
@@ -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"}