@primitiv-ui/web 0.1.53 → 0.1.55

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 (39) hide show
  1. package/README.md +69 -4
  2. package/dist/cdn/accordion.js +1 -1
  3. package/dist/cdn/chunks/chunk-EDLRMP2K.js +1 -0
  4. package/dist/cdn/chunks/chunk-HXGMU6SD.js +1 -0
  5. package/dist/cdn/chunks/chunk-PKW6AKXD.js +1 -0
  6. package/dist/cdn/chunks/chunk-QVNDDONZ.js +1 -0
  7. package/dist/cdn/collapsible.js +1 -1
  8. package/dist/cdn/modal.js +1 -0
  9. package/dist/cdn/popover.js +1 -0
  10. package/dist/cdn/tabs.js +1 -1
  11. package/dist/custom-elements.json +749 -0
  12. package/dist/define/index.d.ts +2 -0
  13. package/dist/define/index.js +2 -0
  14. package/dist/define/modal.d.ts +1 -0
  15. package/dist/define/modal.js +11 -0
  16. package/dist/define/popover.d.ts +1 -0
  17. package/dist/define/popover.js +11 -0
  18. package/dist/frameworks/events.d.ts +8 -0
  19. package/dist/frameworks/react.d.ts +25 -2
  20. package/dist/frameworks/svelte.d.ts +22 -1
  21. package/dist/frameworks/vue.d.ts +22 -1
  22. package/dist/index.d.ts +2 -0
  23. package/dist/index.js +2 -0
  24. package/dist/modal/ModalController.d.ts +58 -0
  25. package/dist/modal/ModalController.js +91 -0
  26. package/dist/modal/elements.d.ts +86 -0
  27. package/dist/modal/elements.js +235 -0
  28. package/dist/modal/index.d.ts +2 -0
  29. package/dist/modal/index.js +2 -0
  30. package/dist/popover/PopoverController.d.ts +55 -0
  31. package/dist/popover/PopoverController.js +100 -0
  32. package/dist/popover/elements.d.ts +98 -0
  33. package/dist/popover/elements.js +230 -0
  34. package/dist/popover/index.d.ts +2 -0
  35. package/dist/popover/index.js +2 -0
  36. package/dist/primitiv-web.js +1 -1
  37. package/dist/tags.d.ts +15 -0
  38. package/package.json +18 -2
  39. package/dist/cdn/chunks/chunk-WVI5UEAW.js +0 -1
@@ -0,0 +1,235 @@
1
+ import { defineElements, ElementBase, reportOnce, write } from "../internal/element.js";
2
+ import { PrimitivRootElement } from "../internal/RootElement.js";
3
+ import { ModalController } from "./ModalController.js";
4
+ // Stryker disable StringLiteral: static — evaluated once at import, so runtime mutant switching never reaches them; the names are pinned by the defineModal registry test instead.
5
+ const ROOT = "primitiv-modal";
6
+ const TRIGGER = "primitiv-modal-trigger";
7
+ const CONTENT = "primitiv-modal-content";
8
+ const TITLE = "primitiv-modal-title";
9
+ const DESCRIPTION = "primitiv-modal-description";
10
+ const CLOSE = "primitiv-modal-close";
11
+ // Stryker restore StringLiteral
12
+ /**
13
+ * The one element child `part` decorates — the `<button>`, `<dialog>` or
14
+ * heading the consumer writes — or `null`, reported once, when it has anything
15
+ * but exactly one (RFC 0033 D24). `what` names the child in the report.
16
+ */
17
+ function decoratable(part, what) {
18
+ if (part.childElementCount === 1)
19
+ return part.firstElementChild;
20
+ reportOnce(part, `<${part.localName}> needs exactly one element child (${what}) to decorate.`);
21
+ return null;
22
+ }
23
+ /** The `<dialog>` a content part decorates, or `null`, reported once, without exactly one. */
24
+ function decoratableDialog(content) {
25
+ const child = content.firstElementChild;
26
+ if (content.childElementCount === 1 && child instanceof HTMLDialogElement)
27
+ return child;
28
+ reportOnce(content, `<${CONTENT}> needs exactly one <dialog> child to decorate.`);
29
+ return null;
30
+ }
31
+ /**
32
+ * `<primitiv-modal>` — the state owner of a modal dialog, built on the native
33
+ * `<dialog>` and its `showModal()`: the browser makes the page behind it inert,
34
+ * paints the `::backdrop` and owns the top layer, and the element adds the
35
+ * rest of the WAI-ARIA Modal Dialog pattern — Tab wraps inside the dialog,
36
+ * Escape and a press on the backdrop close it, and closing hands focus back to
37
+ * the button that opened it.
38
+ *
39
+ * The root finds its own parts, so a modal nested in a dialog keeps its own,
40
+ * and reconciles their ARIA from its reflected state whenever a part arrives,
41
+ * leaves, or changes an attribute the root reads (the lifecycle is
42
+ * `PrimitivRootElement`'s). Leave `open` off the `<dialog>` itself: the root
43
+ * opens it, modally.
44
+ *
45
+ * @customElement primitiv-modal
46
+ * @summary The state owner of a modal dialog on the native `<dialog>`.
47
+ * @attr {boolean} open - Whether the dialog is open. Reflected: it changes as the user opens and dismisses the dialog, so a server re-render or a history snapshot sees the live state. Set it (or the `open` property) to open or close the dialog from script.
48
+ * @fires {CustomEvent<{ open: boolean }>} primitiv-modal-change - Bubbles, cancelable, fired before a user-driven change is applied — a trigger or close click, Escape, a press on the backdrop, or the dialog closing natively — with the open state afterwards. Call `preventDefault()` to veto it, e.g. to keep a form with unsaved changes open.
49
+ */
50
+ export class PrimitivModalElement extends PrimitivRootElement {
51
+ /** The dialog the root currently decorates, and the controller over it. */
52
+ #dialog = null;
53
+ #modal = null;
54
+ /** The decorated trigger and close buttons, as of the last reconcile. */
55
+ // Stryker disable next-line ArrayDeclaration: equivalent — the first reconcile runs as the root connects, before any click can reach it, and replaces both.
56
+ #openers = [];
57
+ // Stryker disable next-line ArrayDeclaration: equivalent — as above.
58
+ #closers = [];
59
+ /** The root's own click listener, while connected. */
60
+ #listening = null;
61
+ controller = {
62
+ connect: () => this.#connect(),
63
+ disconnect: () => this.#disconnect(),
64
+ };
65
+ reconcileOn = ["open"];
66
+ /** Whether the dialog is open, reflected as the boolean `open` attribute. */
67
+ get open() {
68
+ return this.hasAttribute("open");
69
+ }
70
+ set open(next) {
71
+ this.toggleAttribute("open", next);
72
+ }
73
+ /** The controller's view of this element: state lives in the reflected attribute. */
74
+ #host() {
75
+ return {
76
+ state: () => ({ open: this.open }),
77
+ change: (open) => this.#change(open),
78
+ };
79
+ }
80
+ /** A change the user asked for: announced first, so a listener can veto it. */
81
+ #change(open) {
82
+ if (open === this.open)
83
+ return;
84
+ if (this.announce("primitiv-modal-change", { open }))
85
+ this.open = open;
86
+ // A veto can leave the dialog out of step — it already closed natively —
87
+ // so put it back where the state says.
88
+ else
89
+ this.#modal?.sync();
90
+ }
91
+ #connect() {
92
+ this.#listening = new AbortController();
93
+ this.addEventListener("click", (event) => this.#click(event), {
94
+ signal: this.#listening.signal,
95
+ });
96
+ this.#modal?.connect();
97
+ }
98
+ #disconnect() {
99
+ // A root disconnects only after it connected, so it is listening.
100
+ this.#listening.abort();
101
+ this.#listening = null;
102
+ this.#modal?.disconnect();
103
+ // Leaving the document drops the dialog from the top layer but leaves it
104
+ // `open`, so a move would bring it back non-modally. Drop the attribute
105
+ // rather than calling close(): close() queues a close event that a move's
106
+ // reconnect would hear as the user dismissing it. The state is kept, and
107
+ // the next connect reopens the dialog modally.
108
+ if (this.#dialog)
109
+ write(this.#dialog, "open", null);
110
+ }
111
+ #click(event) {
112
+ const target = event.target;
113
+ if (this.#openers.some((button) => button.contains(target)))
114
+ this.#change(true);
115
+ else if (this.#closers.some((button) => button.contains(target)))
116
+ this.#change(false);
117
+ }
118
+ /**
119
+ * Decorate `dialog` from now on: the controller follows it. Only a reconcile
120
+ * calls this, and a root reconciles only while connected, so the new
121
+ * controller listens at once.
122
+ */
123
+ #use(dialog) {
124
+ // Stryker disable next-line ConditionalExpression: equivalent — rebuilding the controller over the same dialog swaps one listener set for an identical one.
125
+ if (dialog === this.#dialog)
126
+ return;
127
+ this.#modal?.disconnect();
128
+ // A dialog that arrives already `open` — a history snapshot, taken while it
129
+ // was showing — is open non-modally, and `showModal()` would leave it so.
130
+ // Drop the attribute (that fires no close event), and the sync below
131
+ // reopens it modally if the root says it is open.
132
+ if (dialog)
133
+ write(dialog, "open", null);
134
+ this.#dialog = dialog;
135
+ this.#modal = dialog ? new ModalController(dialog, this.#host()) : null;
136
+ this.#modal?.connect();
137
+ }
138
+ reconcile() {
139
+ const open = this.open;
140
+ const state = open ? "open" : "closed";
141
+ const rootId = this.rootId();
142
+ write(this, "data-state", state);
143
+ const [content] = this.parts(CONTENT);
144
+ const dialog = content ? decoratableDialog(content) : null;
145
+ const [titlePart] = this.parts(TITLE);
146
+ const title = titlePart ? decoratable(titlePart, "a heading") : null;
147
+ const [descriptionPart] = this.parts(DESCRIPTION);
148
+ const description = descriptionPart ? decoratable(descriptionPart, "a <p>") : null;
149
+ if (title && !title.id)
150
+ title.id = `${rootId}-title`;
151
+ if (description && !description.id)
152
+ description.id = `${rootId}-description`;
153
+ if (dialog) {
154
+ if (!dialog.id)
155
+ dialog.id = `${rootId}-content`;
156
+ write(dialog, "data-state", state);
157
+ write(dialog, "aria-labelledby", title ? title.id : null);
158
+ write(dialog, "aria-describedby", description ? description.id : null);
159
+ }
160
+ this.#openers = this.#buttons(TRIGGER);
161
+ for (const button of this.#openers) {
162
+ write(button, "aria-haspopup", "dialog");
163
+ write(button, "aria-expanded", String(open));
164
+ write(button, "aria-controls", dialog ? dialog.id : null);
165
+ }
166
+ this.#closers = this.#buttons(CLOSE);
167
+ this.#use(dialog);
168
+ this.#modal?.sync();
169
+ }
170
+ /** The buttons this root's `selector` parts decorate. */
171
+ #buttons(selector) {
172
+ return this.parts(selector).flatMap((part) => decoratable(part, "a <button>") ?? []);
173
+ }
174
+ }
175
+ /**
176
+ * `<primitiv-modal-trigger>` — an interactive part. It decorates exactly one
177
+ * child the consumer writes, a `<button>`, which opens the dialog and receives
178
+ * `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`, so the
179
+ * rendered DOM matches React's (RFC 0033 D24). A modal may have several.
180
+ *
181
+ * @customElement primitiv-modal-trigger
182
+ */
183
+ export class PrimitivModalTriggerElement extends ElementBase {
184
+ }
185
+ /**
186
+ * `<primitiv-modal-content>` — decorates exactly one native `<dialog>` the
187
+ * consumer writes, which the root opens with `showModal()`, closes, and gives
188
+ * an id, `data-state`, and `aria-labelledby` / `aria-describedby` pointing at
189
+ * the title and description. The dialog keeps its implicit `dialog` role.
190
+ *
191
+ * @customElement primitiv-modal-content
192
+ */
193
+ export class PrimitivModalContentElement extends ElementBase {
194
+ }
195
+ /**
196
+ * `<primitiv-modal-title>` — decorates exactly one heading the consumer writes
197
+ * (an `<h2>`, usually), whose id becomes the dialog's `aria-labelledby`, so it
198
+ * is the name a screen reader announces as the dialog opens.
199
+ *
200
+ * @customElement primitiv-modal-title
201
+ */
202
+ export class PrimitivModalTitleElement extends ElementBase {
203
+ }
204
+ /**
205
+ * `<primitiv-modal-description>` — decorates exactly one element the consumer
206
+ * writes (a `<p>`, usually), whose id becomes the dialog's `aria-describedby`.
207
+ *
208
+ * @customElement primitiv-modal-description
209
+ */
210
+ export class PrimitivModalDescriptionElement extends ElementBase {
211
+ }
212
+ /**
213
+ * `<primitiv-modal-close>` — an interactive part. It decorates exactly one
214
+ * `<button>` the consumer writes, which closes the dialog. A modal may have
215
+ * several: the header's icon button and the footer's Cancel.
216
+ *
217
+ * @customElement primitiv-modal-close
218
+ */
219
+ export class PrimitivModalCloseElement extends ElementBase {
220
+ }
221
+ /**
222
+ * Define the six Modal elements on `registry` (the global `customElements` by
223
+ * default). Safe to call more than once, and a no-op where there is no
224
+ * registry (a server render).
225
+ */
226
+ export function defineModal(registry = globalThis.customElements) {
227
+ defineElements(registry, [
228
+ [ROOT, PrimitivModalElement],
229
+ [TRIGGER, PrimitivModalTriggerElement],
230
+ [CONTENT, PrimitivModalContentElement],
231
+ [TITLE, PrimitivModalTitleElement],
232
+ [DESCRIPTION, PrimitivModalDescriptionElement],
233
+ [CLOSE, PrimitivModalCloseElement],
234
+ ]);
235
+ }
@@ -0,0 +1,2 @@
1
+ export { ModalController, type ModalControllerHost } from "./ModalController.js";
2
+ export { defineModal, PrimitivModalCloseElement, PrimitivModalContentElement, PrimitivModalDescriptionElement, PrimitivModalElement, PrimitivModalTitleElement, PrimitivModalTriggerElement, } from "./elements.js";
@@ -0,0 +1,2 @@
1
+ export { ModalController } from "./ModalController.js";
2
+ export { defineModal, PrimitivModalCloseElement, PrimitivModalContentElement, PrimitivModalDescriptionElement, PrimitivModalElement, PrimitivModalTitleElement, PrimitivModalTriggerElement, } from "./elements.js";
@@ -0,0 +1,55 @@
1
+ /**
2
+ * What a {@link PopoverController} asks of whoever hosts it. The controller
3
+ * owns behaviour and never owns state (RFC 0033 D28): the custom elements keep
4
+ * the open state in a reflected `open` attribute, the React adapter keeps it in
5
+ * React, and each answers these calls from wherever it keeps it.
6
+ */
7
+ export type PopoverControllerHost = {
8
+ /** The state the controller cannot see for itself. */
9
+ state(): {
10
+ /** Whether the popover is open. */
11
+ open: boolean;
12
+ };
13
+ /** Apply a change the user asked for: `open` is the state afterwards. */
14
+ change(open: boolean): void;
15
+ /** The trigger: Escape hands focus back to it, and a press on it is not an outside press. */
16
+ trigger(): HTMLElement | null;
17
+ /**
18
+ * The element to hand `showPopover({ source })`, which makes it the panel's
19
+ * implicit anchor for CSS anchor positioning. Optional: without it the panel
20
+ * is shown with no source, and positioning is the consumer's to wire.
21
+ */
22
+ source?(): HTMLElement | null;
23
+ };
24
+ /**
25
+ * The DOM behaviour of a popover, over a `popover="auto"` panel: the browser
26
+ * owns the top layer and light dismiss, and this adds the rest of the WAI-ARIA
27
+ * non-modal dialog pattern:
28
+ *
29
+ * - **Sync** — {@link PopoverController.sync | `sync()`} shows or hides the
30
+ * panel to match the host's state, moving focus into it as it opens (its
31
+ * first focusable, or the panel itself). A host calls it whenever that state
32
+ * may have changed.
33
+ * - **Dismissal** — the browser light-dismissing the panel is reported, Escape
34
+ * inside it closes it and hands focus back to the trigger, and where the
35
+ * browser has no Popover API a press outside closes it.
36
+ *
37
+ * Opening from the trigger is the host's, as a plain click.
38
+ */
39
+ export declare class PopoverController {
40
+ #private;
41
+ constructor(content: HTMLElement, host: PopoverControllerHost);
42
+ /**
43
+ * Start listening. Connecting again while connected does nothing, so a host
44
+ * whose lifecycle runs twice never stacks handlers.
45
+ */
46
+ connect(): void;
47
+ /**
48
+ * Stop listening, and forget the panel was showing: a host disconnects when
49
+ * it leaves the document, which hides a popover with no event, so the next
50
+ * sync shows it again.
51
+ */
52
+ disconnect(): void;
53
+ /** Show or hide the panel to match the host's state. */
54
+ sync(): void;
55
+ }
@@ -0,0 +1,100 @@
1
+ import { FOCUSABLE_SELECTOR, popoverKeydown, popoverPressDismisses } from "@primitiv-ui/core";
2
+ /**
3
+ * The DOM behaviour of a popover, over a `popover="auto"` panel: the browser
4
+ * owns the top layer and light dismiss, and this adds the rest of the WAI-ARIA
5
+ * non-modal dialog pattern:
6
+ *
7
+ * - **Sync** — {@link PopoverController.sync | `sync()`} shows or hides the
8
+ * panel to match the host's state, moving focus into it as it opens (its
9
+ * first focusable, or the panel itself). A host calls it whenever that state
10
+ * may have changed.
11
+ * - **Dismissal** — the browser light-dismissing the panel is reported, Escape
12
+ * inside it closes it and hands focus back to the trigger, and where the
13
+ * browser has no Popover API a press outside closes it.
14
+ *
15
+ * Opening from the trigger is the host's, as a plain click.
16
+ */
17
+ export class PopoverController {
18
+ #content;
19
+ #host;
20
+ #connection = null;
21
+ /** Whether this controller showed the panel and has not hidden it since. */
22
+ #shown = false;
23
+ constructor(content, host) {
24
+ this.#content = content;
25
+ this.#host = host;
26
+ }
27
+ /**
28
+ * Start listening. Connecting again while connected does nothing, so a host
29
+ * whose lifecycle runs twice never stacks handlers.
30
+ */
31
+ connect() {
32
+ if (this.#connection)
33
+ return;
34
+ this.#connection = new AbortController();
35
+ const { signal } = this.#connection;
36
+ this.#content.addEventListener("toggle", (event) => this.#toggle(event), { signal });
37
+ this.#content.addEventListener("keydown", (event) => this.#keydown(event), { signal });
38
+ document.addEventListener("click", (event) => this.#press(event), { signal });
39
+ }
40
+ /**
41
+ * Stop listening, and forget the panel was showing: a host disconnects when
42
+ * it leaves the document, which hides a popover with no event, so the next
43
+ * sync shows it again.
44
+ */
45
+ disconnect() {
46
+ this.#connection?.abort();
47
+ this.#connection = null;
48
+ this.#shown = false;
49
+ }
50
+ /** Show or hide the panel to match the host's state. */
51
+ sync() {
52
+ const { open } = this.#host.state();
53
+ if (open && !this.#shown) {
54
+ this.#shown = true;
55
+ const source = this.#host.source?.();
56
+ if (source)
57
+ this.#content.showPopover({ source });
58
+ else
59
+ this.#content.showPopover();
60
+ // Move focus into the panel (WAI-ARIA non-modal dialog): the first
61
+ // focusable, or the panel itself, which carries tabindex="-1".
62
+ (this.#content.querySelector(FOCUSABLE_SELECTOR) ?? this.#content).focus();
63
+ }
64
+ else if (!open && this.#shown) {
65
+ this.#shown = false;
66
+ try {
67
+ this.#content.hidePopover();
68
+ }
69
+ catch {
70
+ // Already hidden: the browser light-dismissed it first.
71
+ }
72
+ }
73
+ }
74
+ #toggle(event) {
75
+ if (event.newState !== "closed")
76
+ return;
77
+ this.#shown = false;
78
+ this.#host.change(false);
79
+ }
80
+ #keydown(event) {
81
+ // A popover nested in this panel handles its own Escape first, as the
82
+ // event bubbles out of it; leave that one alone, or both would close.
83
+ if (event.defaultPrevented || !popoverKeydown(event.key))
84
+ return;
85
+ event.preventDefault();
86
+ this.#host.change(false);
87
+ this.#host.trigger()?.focus();
88
+ }
89
+ #press(event) {
90
+ const target = event.target;
91
+ const dismisses = popoverPressDismisses({
92
+ open: this.#host.state().open,
93
+ nativeLightDismiss: "popover" in HTMLElement.prototype,
94
+ inTrigger: this.#host.trigger()?.contains(target) ?? false,
95
+ inPopover: target.closest("[popover]") !== null,
96
+ });
97
+ if (dismisses)
98
+ this.#host.change(false);
99
+ }
100
+ }
@@ -0,0 +1,98 @@
1
+ import { ElementBase, type ElementRegistry } from "../internal/element.js";
2
+ import { PrimitivRootElement } from "../internal/RootElement.js";
3
+ export type { ElementRegistry };
4
+ /**
5
+ * `<primitiv-popover>` — the state owner of a non-modal popover: a trigger
6
+ * that opens a floating panel, built on the native Popover API. The browser
7
+ * puts the panel in the top layer and light-dismisses it; the element adds the
8
+ * rest of the WAI-ARIA non-modal dialog pattern — focus moves into the panel
9
+ * as it opens, Escape closes it and hands focus back to the trigger, and the
10
+ * trigger's `aria-expanded` follows it.
11
+ *
12
+ * The panel is shown with its trigger (or the anchor) as its source, which
13
+ * makes that element the panel's implicit anchor, so CSS anchor positioning
14
+ * (`position-area`) places it with no `anchor-name` to wire.
15
+ *
16
+ * The root finds its own parts, so a popover nested in a panel keeps its own,
17
+ * and reconciles their ARIA from its reflected state whenever a part arrives,
18
+ * leaves, or changes an attribute the root reads (the lifecycle is
19
+ * `PrimitivRootElement`'s).
20
+ *
21
+ * @customElement primitiv-popover
22
+ * @summary The state owner of a non-modal popover on the native Popover API.
23
+ * @attr {boolean} open - Whether the panel is open. Reflected: it changes as the user opens and dismisses it, so a server re-render or a history snapshot sees the live state. Set it (or the `open` property) to open or close the panel from script.
24
+ * @fires {CustomEvent<{ open: boolean }>} primitiv-popover-change - Bubbles, cancelable, fired before a user-driven change is applied — a trigger or close click, Escape, or a light dismiss — with the open state afterwards. Call `preventDefault()` to veto it.
25
+ */
26
+ export declare class PrimitivPopoverElement extends PrimitivRootElement {
27
+ #private;
28
+ protected readonly controller: {
29
+ connect(): void;
30
+ disconnect(): void;
31
+ };
32
+ protected readonly reconcileOn: readonly string[];
33
+ /** Whether the panel is open, reflected as the boolean `open` attribute. */
34
+ get open(): boolean;
35
+ set open(next: boolean);
36
+ protected reconcile(): void;
37
+ }
38
+ /**
39
+ * `<primitiv-popover-trigger>` — an interactive part. It decorates exactly one
40
+ * child the consumer writes, a `<button>`, which toggles the panel and receives
41
+ * `aria-haspopup="dialog"`, `aria-expanded` and `aria-controls`, so the
42
+ * rendered DOM matches React's (RFC 0033 D24).
43
+ *
44
+ * @customElement primitiv-popover-trigger
45
+ */
46
+ export declare class PrimitivPopoverTriggerElement extends ElementBase {
47
+ }
48
+ /**
49
+ * `<primitiv-popover-anchor>` — optional. It decorates exactly one element the
50
+ * consumer writes, which the panel is anchored to in place of the trigger: a
51
+ * field, say, whose trigger is an icon inside it.
52
+ *
53
+ * @customElement primitiv-popover-anchor
54
+ */
55
+ export declare class PrimitivPopoverAnchorElement extends ElementBase {
56
+ }
57
+ /**
58
+ * `<primitiv-popover-content>` — the panel. Structural: the root gives it an
59
+ * id, `role="dialog"`, `popover="auto"` (write it in your markup too, so the
60
+ * panel is hidden before the script loads), `tabindex="-1"`, `data-state`, and
61
+ * `aria-labelledby` / `aria-describedby` pointing at the title and description.
62
+ *
63
+ * @customElement primitiv-popover-content
64
+ */
65
+ export declare class PrimitivPopoverContentElement extends ElementBase {
66
+ }
67
+ /**
68
+ * `<primitiv-popover-title>` — decorates exactly one heading the consumer
69
+ * writes, whose id becomes the panel's `aria-labelledby`.
70
+ *
71
+ * @customElement primitiv-popover-title
72
+ */
73
+ export declare class PrimitivPopoverTitleElement extends ElementBase {
74
+ }
75
+ /**
76
+ * `<primitiv-popover-description>` — decorates exactly one element the
77
+ * consumer writes (a `<p>`, usually), whose id becomes the panel's
78
+ * `aria-describedby`.
79
+ *
80
+ * @customElement primitiv-popover-description
81
+ */
82
+ export declare class PrimitivPopoverDescriptionElement extends ElementBase {
83
+ }
84
+ /**
85
+ * `<primitiv-popover-close>` — an interactive part. It decorates exactly one
86
+ * `<button>` the consumer writes, which closes the panel. A popover may have
87
+ * several.
88
+ *
89
+ * @customElement primitiv-popover-close
90
+ */
91
+ export declare class PrimitivPopoverCloseElement extends ElementBase {
92
+ }
93
+ /**
94
+ * Define the seven Popover elements on `registry` (the global `customElements`
95
+ * by default). Safe to call more than once, and a no-op where there is no
96
+ * registry (a server render).
97
+ */
98
+ export declare function definePopover(registry?: ElementRegistry | undefined): void;