@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.
- package/README.md +1 -1
- package/dist/checkbox-group/checkbox-group-context.mjs +24 -0
- package/dist/checkbox-group/checkbox-group-context.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts +55 -0
- package/dist/checkbox-group/checkbox-group-item.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-item.mjs +90 -0
- package/dist/checkbox-group/checkbox-group-item.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts +21 -0
- package/dist/checkbox-group/checkbox-group-label.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-label.mjs +30 -0
- package/dist/checkbox-group/checkbox-group-label.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts +68 -0
- package/dist/checkbox-group/checkbox-group-parent.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs +145 -0
- package/dist/checkbox-group/checkbox-group-parent.mjs.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts +100 -0
- package/dist/checkbox-group/checkbox-group-root.d.mts.map +1 -0
- package/dist/checkbox-group/checkbox-group-root.mjs +291 -0
- package/dist/checkbox-group/checkbox-group-root.mjs.map +1 -0
- package/dist/checkbox-group/index.d.mts +23 -0
- package/dist/checkbox-group/index.d.mts.map +1 -0
- package/dist/checkbox-group/index.mjs +23 -0
- package/dist/checkbox-group/index.mjs.map +1 -0
- package/dist/dialog/dialog-close.d.mts.map +1 -1
- package/dist/dialog/dialog-close.mjs +4 -4
- package/dist/dialog/dialog-close.mjs.map +1 -1
- package/dist/dialog/dialog-context.mjs.map +1 -1
- package/dist/dialog/dialog-popup.mjs +1 -0
- package/dist/dialog/dialog-popup.mjs.map +1 -1
- package/dist/dialog/dialog-root.mjs +9 -1
- package/dist/dialog/dialog-root.mjs.map +1 -1
- package/dist/index.d.mts +23 -1
- package/dist/index.mjs +4 -1
- package/dist/internal/anchor-position.d.mts +7 -0
- package/dist/internal/anchor-position.d.mts.map +1 -0
- package/dist/internal/anchor-position.mjs +16 -0
- package/dist/internal/anchor-position.mjs.map +1 -0
- package/dist/internal/platform-attributes.d.mts +6 -0
- package/dist/internal/platform-attributes.d.mts.map +1 -1
- package/dist/internal/sync-presence.mjs +19 -0
- package/dist/internal/sync-presence.mjs.map +1 -0
- package/dist/internal/use-action-trigger.mjs +58 -0
- package/dist/internal/use-action-trigger.mjs.map +1 -0
- package/dist/internal/use-delayed-pair.mjs +40 -0
- package/dist/internal/use-delayed-pair.mjs.map +1 -0
- package/dist/internal/use-exit-animation.mjs +55 -0
- package/dist/internal/use-exit-animation.mjs.map +1 -0
- package/dist/internal/use-native-group-reconciliation.mjs +2 -2
- package/dist/internal/use-native-group-reconciliation.mjs.map +1 -1
- package/dist/internal/use-popover-popup.mjs +274 -0
- package/dist/internal/use-popover-popup.mjs.map +1 -0
- package/dist/internal/use-popover-root.d.mts +2 -0
- package/dist/internal/use-popover-root.mjs +112 -0
- package/dist/internal/use-popover-root.mjs.map +1 -0
- package/dist/internal/use-popover-trigger.mjs +86 -0
- package/dist/internal/use-popover-trigger.mjs.map +1 -0
- package/dist/menu/index.d.mts +34 -0
- package/dist/menu/index.d.mts.map +1 -0
- package/dist/menu/index.mjs +34 -0
- package/dist/menu/index.mjs.map +1 -0
- package/dist/menu/menu-checkbox-item.d.mts +42 -0
- package/dist/menu/menu-checkbox-item.d.mts.map +1 -0
- package/dist/menu/menu-checkbox-item.mjs +71 -0
- package/dist/menu/menu-checkbox-item.mjs.map +1 -0
- package/dist/menu/menu-context.d.mts +1 -0
- package/dist/menu/menu-context.mjs +28 -0
- package/dist/menu/menu-context.mjs.map +1 -0
- package/dist/menu/menu-dom.mjs +37 -0
- package/dist/menu/menu-dom.mjs.map +1 -0
- package/dist/menu/menu-group.d.mts +48 -0
- package/dist/menu/menu-group.d.mts.map +1 -0
- package/dist/menu/menu-group.mjs +69 -0
- package/dist/menu/menu-group.mjs.map +1 -0
- package/dist/menu/menu-hover.mjs +29 -0
- package/dist/menu/menu-hover.mjs.map +1 -0
- package/dist/menu/menu-item.d.mts +45 -0
- package/dist/menu/menu-item.d.mts.map +1 -0
- package/dist/menu/menu-item.mjs +54 -0
- package/dist/menu/menu-item.mjs.map +1 -0
- package/dist/menu/menu-popup.d.mts +69 -0
- package/dist/menu/menu-popup.d.mts.map +1 -0
- package/dist/menu/menu-popup.mjs +207 -0
- package/dist/menu/menu-popup.mjs.map +1 -0
- package/dist/menu/menu-radio-group.d.mts +37 -0
- package/dist/menu/menu-radio-group.d.mts.map +1 -0
- package/dist/menu/menu-radio-group.mjs +72 -0
- package/dist/menu/menu-radio-group.mjs.map +1 -0
- package/dist/menu/menu-radio-item.d.mts +33 -0
- package/dist/menu/menu-radio-item.d.mts.map +1 -0
- package/dist/menu/menu-radio-item.mjs +62 -0
- package/dist/menu/menu-radio-item.mjs.map +1 -0
- package/dist/menu/menu-root.d.mts +54 -0
- package/dist/menu/menu-root.d.mts.map +1 -0
- package/dist/menu/menu-root.mjs +102 -0
- package/dist/menu/menu-root.mjs.map +1 -0
- package/dist/menu/menu-submenu-trigger.d.mts +31 -0
- package/dist/menu/menu-submenu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-submenu-trigger.mjs +92 -0
- package/dist/menu/menu-submenu-trigger.mjs.map +1 -0
- package/dist/menu/menu-trigger.d.mts +36 -0
- package/dist/menu/menu-trigger.d.mts.map +1 -0
- package/dist/menu/menu-trigger.mjs +81 -0
- package/dist/menu/menu-trigger.mjs.map +1 -0
- package/dist/menu/use-menu-item.mjs +54 -0
- package/dist/menu/use-menu-item.mjs.map +1 -0
- package/dist/popover/index.d.mts +28 -0
- package/dist/popover/index.d.mts.map +1 -0
- package/dist/popover/index.mjs +28 -0
- package/dist/popover/index.mjs.map +1 -0
- package/dist/popover/popover-close.d.mts +41 -0
- package/dist/popover/popover-close.d.mts.map +1 -0
- package/dist/popover/popover-close.mjs +90 -0
- package/dist/popover/popover-close.mjs.map +1 -0
- package/dist/popover/popover-context.mjs +26 -0
- package/dist/popover/popover-context.mjs.map +1 -0
- package/dist/popover/popover-description.d.mts +22 -0
- package/dist/popover/popover-description.d.mts.map +1 -0
- package/dist/popover/popover-description.mjs +28 -0
- package/dist/popover/popover-description.mjs.map +1 -0
- package/dist/popover/popover-popup.d.mts +82 -0
- package/dist/popover/popover-popup.d.mts.map +1 -0
- package/dist/popover/popover-popup.mjs +93 -0
- package/dist/popover/popover-popup.mjs.map +1 -0
- package/dist/popover/popover-root.d.mts +64 -0
- package/dist/popover/popover-root.d.mts.map +1 -0
- package/dist/popover/popover-root.mjs +39 -0
- package/dist/popover/popover-root.mjs.map +1 -0
- package/dist/popover/popover-title.d.mts +23 -0
- package/dist/popover/popover-title.d.mts.map +1 -0
- package/dist/popover/popover-title.mjs +28 -0
- package/dist/popover/popover-title.mjs.map +1 -0
- package/dist/popover/popover-trigger.d.mts +37 -0
- package/dist/popover/popover-trigger.d.mts.map +1 -0
- package/dist/popover/popover-trigger.mjs +40 -0
- package/dist/popover/popover-trigger.mjs.map +1 -0
- package/dist/radio-group/radio-group-item.d.mts.map +1 -1
- package/dist/radio-group/radio-group-item.mjs +1 -6
- package/dist/radio-group/radio-group-item.mjs.map +1 -1
- package/dist/tabs/tabs-context.mjs +2 -1
- package/dist/tabs/tabs-context.mjs.map +1 -1
- package/dist/tabs/tabs-list.d.mts +1 -1
- package/dist/tabs/tabs-list.d.mts.map +1 -1
- package/dist/tabs/tabs-list.mjs +17 -9
- package/dist/tabs/tabs-list.mjs.map +1 -1
- package/dist/tabs/tabs-tab.d.mts +1 -1
- package/dist/tabs/tabs-tab.d.mts.map +1 -1
- package/dist/tabs/tabs-tab.mjs +6 -3
- package/dist/tabs/tabs-tab.mjs.map +1 -1
- package/dist/tooltip/tooltip-popup.d.mts.map +1 -1
- package/dist/tooltip/tooltip-popup.mjs +2 -7
- package/dist/tooltip/tooltip-popup.mjs.map +1 -1
- package/dist/tooltip/use-tooltip-interaction.mjs +5 -17
- package/dist/tooltip/use-tooltip-interaction.mjs.map +1 -1
- 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"}
|