@menapo/machine 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +135 -2
- package/dist/chart-BWjU2VF4.js +395 -0
- package/dist/compiled.d.ts +58 -0
- package/dist/compiled.js +43 -0
- package/dist/component-DDXOyYUI.d.ts +147 -0
- package/dist/dev-BAz6e3W-.js +79 -0
- package/dist/dom.d.ts +187 -0
- package/dist/dom.js +659 -0
- package/dist/glue/preact.d.ts +4 -0
- package/dist/glue/preact.js +54 -0
- package/dist/glue/react.d.ts +4 -0
- package/dist/glue/react.js +50 -0
- package/dist/glue/solid.d.ts +4 -0
- package/dist/glue/solid.js +42 -0
- package/dist/glue/svelte.svelte.d.ts +4 -0
- package/dist/glue/svelte.svelte.js +57 -0
- package/dist/glue/vanilla.d.ts +4 -0
- package/dist/glue/vanilla.js +83 -0
- package/dist/glue/vue.d.ts +4 -0
- package/dist/glue/vue.js +41 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +582 -0
- package/dist/inspect-BmyLUhcy.js +74 -0
- package/dist/inspect-C3qosuCm.d.ts +22 -0
- package/dist/instance-BM2UqeXW.js +418 -0
- package/dist/machine-BstWHtWL.d.ts +335 -0
- package/dist/naming-Csj5186j.js +492 -0
- package/dist/records-7FFepzo9.js +10 -0
- package/dist/source-DdFTPjID.js +15 -0
- package/dist/test.d.ts +63 -0
- package/dist/test.js +262 -0
- package/dist/types-Bk8svtO6.d.ts +580 -0
- package/dist/vicss.d.ts +19 -0
- package/dist/vicss.js +51 -0
- package/dist/vite.d.ts +27 -0
- package/dist/vite.js +4281 -0
- package/package.json +87 -3
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { n as Tables, o as Interpreter, t as State } from "./machine-BstWHtWL.js";
|
|
2
|
+
//#region src/parts/compile.d.ts
|
|
3
|
+
/** A framework's attribute name for a part key: React keeps `onClick`, Svelte writes `onclick`. */
|
|
4
|
+
type Naming = (key: string) => string;
|
|
5
|
+
/** An attribute function or a handler as the instance calls it. */
|
|
6
|
+
type AttrFn = (view: never) => unknown;
|
|
7
|
+
type HandlerFn = (view: never, event: unknown) => void;
|
|
8
|
+
interface Part {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
/** Static attributes, renamed, in the order written. */
|
|
11
|
+
readonly statics: readonly (readonly [string, unknown])[];
|
|
12
|
+
/** Attribute functions' names, renamed, and the functions. */
|
|
13
|
+
readonly keys: readonly string[];
|
|
14
|
+
readonly fns: readonly AttrFn[];
|
|
15
|
+
/** Handlers: the renamed key, and an event name or a function of `(view, domEvent)`. */
|
|
16
|
+
readonly on: readonly (readonly [string, string | HandlerFn])[];
|
|
17
|
+
/** Where its attribute values start in an instance's values array. */
|
|
18
|
+
readonly at: number;
|
|
19
|
+
/**
|
|
20
|
+
* Its props object with every key in place, values to come: an
|
|
21
|
+
* instance's first object is a copy, so every instance's has one shape.
|
|
22
|
+
*/
|
|
23
|
+
readonly template: Readonly<Record<string, unknown>>;
|
|
24
|
+
}
|
|
25
|
+
interface Compiled {
|
|
26
|
+
readonly parts: readonly Part[];
|
|
27
|
+
/** `api.parts` with every part's key in place: each view's is a copy. */
|
|
28
|
+
readonly record: Readonly<Record<string, undefined>>;
|
|
29
|
+
/** Attribute functions over every part: an instance's values array is this long. */
|
|
30
|
+
readonly size: number;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/parts/component.d.ts
|
|
34
|
+
type Owner = Readonly<Record<string, unknown>>;
|
|
35
|
+
type Props = Record<string, unknown>;
|
|
36
|
+
/** What tells a vanilla view of visible changes and stops it (the vanilla adapter), else the view itself. */
|
|
37
|
+
interface Listen {
|
|
38
|
+
subscribe(listener: () => void): () => void;
|
|
39
|
+
stop(): void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* What `useMachine` returns: `state`, `is`, `send`, `context`, `parts`, and
|
|
43
|
+
* a getter for each value `expose` returns (a class per machine adds them).
|
|
44
|
+
* Every getter reads the component's current snapshot, after the
|
|
45
|
+
* framework's tracker (`t`: Vue, Svelte and Solid record the read; React
|
|
46
|
+
* and Preact have none). React and Preact get a new one per view version,
|
|
47
|
+
* since they compare by identity (React's Compiler too); the others keep
|
|
48
|
+
* one for the component's life. Reading `state`, `is` or `context` marks
|
|
49
|
+
* them watched, so a change to them renders even when no part shows it.
|
|
50
|
+
*/
|
|
51
|
+
declare class View {
|
|
52
|
+
readonly $: Component;
|
|
53
|
+
readonly t: (() => unknown) | undefined;
|
|
54
|
+
readonly u: Listen | undefined;
|
|
55
|
+
constructor(component: Component, track?: () => unknown, listen?: Listen);
|
|
56
|
+
get parts(): Readonly<Record<string, Readonly<Props>>>;
|
|
57
|
+
get state(): string;
|
|
58
|
+
get is(): (state: string) => boolean;
|
|
59
|
+
get context(): object;
|
|
60
|
+
get send(): Interpreter["send"];
|
|
61
|
+
setProps(props: object): void;
|
|
62
|
+
/**
|
|
63
|
+
* Stops the instance as an unmount does: its effects and timers, and in
|
|
64
|
+
* plain code its listeners. A framework's glue does it when the component
|
|
65
|
+
* goes; plain code calls it when the element goes.
|
|
66
|
+
*/
|
|
67
|
+
stop(): void;
|
|
68
|
+
/** Calls `listener` after each visible change. */
|
|
69
|
+
subscribe(listener: () => void): () => void;
|
|
70
|
+
}
|
|
71
|
+
/** What a component keeps once rendered. */
|
|
72
|
+
interface Rendered {
|
|
73
|
+
readonly pc: Compiled;
|
|
74
|
+
/** Per part: its props object and the bits its attribute functions read. */
|
|
75
|
+
readonly po: Props[];
|
|
76
|
+
readonly pr: number[];
|
|
77
|
+
/** Every part's attribute values, from each part's `at`. */
|
|
78
|
+
readonly pa: unknown[];
|
|
79
|
+
/** `api.parts` for {@link rv}, the version it was made at. */
|
|
80
|
+
rec: Readonly<Record<string, Readonly<Props>>> | undefined;
|
|
81
|
+
rv: number;
|
|
82
|
+
/** The view for {@link vv}, the version it was made at (React, Preact). */
|
|
83
|
+
vo: View | undefined;
|
|
84
|
+
vv: number;
|
|
85
|
+
}
|
|
86
|
+
declare class Component extends Interpreter {
|
|
87
|
+
/** The instance id: the framework's (`useId`), or the owner's `id`. */
|
|
88
|
+
readonly id: string;
|
|
89
|
+
/** The framework's attribute names. */
|
|
90
|
+
readonly nm: Naming;
|
|
91
|
+
/** Bits changed since the last snapshot. */
|
|
92
|
+
cc: number;
|
|
93
|
+
/** Bits the component read through its view (`state`, `is`, `context`). */
|
|
94
|
+
wa: number;
|
|
95
|
+
/** The view version. */
|
|
96
|
+
pv: number;
|
|
97
|
+
/** 1 while mounted: effects may start. */
|
|
98
|
+
y: number;
|
|
99
|
+
/** 1 when effects wait for a commit, which a render must bring. */
|
|
100
|
+
fx: number;
|
|
101
|
+
/** Effects deferred until the next commit. */
|
|
102
|
+
w: State[] | undefined;
|
|
103
|
+
/** Parts, once rendered. */
|
|
104
|
+
rd: Rendered | undefined;
|
|
105
|
+
/** `expose`'s last result and the bits it read. */
|
|
106
|
+
xo: Props | undefined;
|
|
107
|
+
xr: number;
|
|
108
|
+
ir: Owner | undefined;
|
|
109
|
+
er: object | undefined;
|
|
110
|
+
constructor(machine: Tables, owner: Owner | undefined, id: string, naming: Naming);
|
|
111
|
+
/** `data-scope`: the machine's name. */
|
|
112
|
+
get scope(): string;
|
|
113
|
+
/** `ids.<part>`: `<name>:<id>:<part>`, stable for the instance and the same on server and client. */
|
|
114
|
+
get ids(): Owner;
|
|
115
|
+
/** `el.<part>`: the part's element, found by its id when read. */
|
|
116
|
+
get el(): object;
|
|
117
|
+
activate(states: readonly State[]): void;
|
|
118
|
+
exit(at: State): void;
|
|
119
|
+
/**
|
|
120
|
+
* Starts what `states` run as one step (D3): what an effect sends waits
|
|
121
|
+
* until every effect has started, then runs to completion and is told,
|
|
122
|
+
* as when the core starts them. Inside a listener (the vanilla glue
|
|
123
|
+
* commits there) the event being handled does that.
|
|
124
|
+
*/
|
|
125
|
+
begin(states: readonly State[]): void;
|
|
126
|
+
/** After the first commit (and again after StrictMode's remount): starts what the active states run. */
|
|
127
|
+
mount(): void;
|
|
128
|
+
unmount(): void;
|
|
129
|
+
/** After a commit: starts the timers and effects of states entered since, that are still active. */
|
|
130
|
+
commit(): void;
|
|
131
|
+
/**
|
|
132
|
+
* The view version: brings parts and `expose` up to date, and moves only
|
|
133
|
+
* when something shown changed. Before the first render it does nothing,
|
|
134
|
+
* so creating a component builds no parts.
|
|
135
|
+
*/
|
|
136
|
+
snapshot(): number;
|
|
137
|
+
/** Renders every part the first time: each from its compiled template, then the instance's values. */
|
|
138
|
+
render(): Rendered;
|
|
139
|
+
/** What `expose` returns, computed again when `again` or not yet. */
|
|
140
|
+
exposed(again?: boolean): Props | undefined;
|
|
141
|
+
/** Every part's props object, by part: the same record until one changes. */
|
|
142
|
+
record(): Readonly<Record<string, Readonly<Props>>>;
|
|
143
|
+
/** The view for the current version, for frameworks that compare by identity: a new one only when something shown changed. */
|
|
144
|
+
view(): View;
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
export { View as t };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
//#region src/core/dev.ts
|
|
2
|
+
/**
|
|
3
|
+
* Dev errors and warnings (PLAN §4.11): each names the machine, what went
|
|
4
|
+
* wrong and the fix, behind a code. Every caller sits behind `if (DEV)`, so
|
|
5
|
+
* none of this reaches a production bundle.
|
|
6
|
+
*/
|
|
7
|
+
/** `[machine:CODE] name: message`. */
|
|
8
|
+
const message = (code, machine, text) => `[machine:${code}] ${machine}: ${text}`;
|
|
9
|
+
function fail(code, machine, text) {
|
|
10
|
+
throw new Error(message(code, machine, text));
|
|
11
|
+
}
|
|
12
|
+
const warned = /* @__PURE__ */ new Set();
|
|
13
|
+
/** Warns once per distinct message, so a send in a loop does not flood the console. */
|
|
14
|
+
function warnOnce(code, machine, text) {
|
|
15
|
+
const line = message(code, machine, text);
|
|
16
|
+
if (warned.has(line)) return;
|
|
17
|
+
warned.add(line);
|
|
18
|
+
console.warn(line);
|
|
19
|
+
}
|
|
20
|
+
/** Edit distance, for "did you mean". */
|
|
21
|
+
function distance(a, b) {
|
|
22
|
+
let row = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
23
|
+
for (let i = 1; i <= a.length; i++) {
|
|
24
|
+
const next = [i];
|
|
25
|
+
for (let j = 1; j <= b.length; j++) next[j] = Math.min(row[j] + 1, next[j - 1] + 1, row[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
26
|
+
row = next;
|
|
27
|
+
}
|
|
28
|
+
return row[b.length];
|
|
29
|
+
}
|
|
30
|
+
/** `; did you mean "closed"?` for the nearest of `options`, or "" when none is close. */
|
|
31
|
+
function suggest(name, options) {
|
|
32
|
+
let best = "";
|
|
33
|
+
let score = Math.max(2, Math.floor(name.length / 3)) + 1;
|
|
34
|
+
for (const option of options) {
|
|
35
|
+
const d = distance(name.toLowerCase(), option.toLowerCase());
|
|
36
|
+
if (d < score) [best, score] = [option, d];
|
|
37
|
+
}
|
|
38
|
+
return best ? `; did you mean "${best}"?` : "";
|
|
39
|
+
}
|
|
40
|
+
/** Keys users bring from XState and Zag, with what they are called here. */
|
|
41
|
+
const RENAMED = {
|
|
42
|
+
target: "to",
|
|
43
|
+
guard: "if",
|
|
44
|
+
cond: "if",
|
|
45
|
+
actions: "do",
|
|
46
|
+
effects: "effect",
|
|
47
|
+
onEntry: "entry",
|
|
48
|
+
onExit: "exit"
|
|
49
|
+
};
|
|
50
|
+
/** Fails on a key `config` should not have, naming the right one. */
|
|
51
|
+
function checkKeys(config, allowed, machine, where) {
|
|
52
|
+
for (const key of Object.keys(config)) {
|
|
53
|
+
if (allowed.includes(key)) continue;
|
|
54
|
+
fail("UNKNOWN_KEY", machine, `${where} has an unknown key "${key}"${RENAMED[key] ? `; use "${RENAMED[key]}".` : suggest(key, allowed) || "."} Allowed: ${allowed.join(", ")}.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** The DOM's spellings a part may not use, and React's, which every glue maps to its framework's. */
|
|
58
|
+
const SPELLED = {
|
|
59
|
+
class: "className",
|
|
60
|
+
for: "htmlFor"
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Dev only: each part's handlers send an event some state handles, or are
|
|
64
|
+
* functions; its keys are spelled as React spells them (`@menapo/glue/naming`).
|
|
65
|
+
* Checked by the normaliser, so the plugin's compilation fails the build on
|
|
66
|
+
* them, and when a compiled machine loads in development.
|
|
67
|
+
*/
|
|
68
|
+
function checkParts(config, name, handled) {
|
|
69
|
+
const parts = config.parts ?? {};
|
|
70
|
+
for (const part of Object.keys(parts)) for (const key of Object.keys(parts[part])) {
|
|
71
|
+
const value = parts[part][key];
|
|
72
|
+
if (/^on[A-Z]/.test(key)) {
|
|
73
|
+
if (typeof value !== "string" && typeof value !== "function") fail("BAD_HANDLER", name, `part "${part}" has ${key}: ${String(value)}; an on* key takes an event name or a function of (view, event).`);
|
|
74
|
+
if (typeof value === "string" && !handled.has(value)) fail("UNKNOWN_EVENT", name, `part "${part}" sends "${value}" from ${key}, which no state handles${suggest(value, handled) || "."} Handle it in a state's \`on\`, or send another event.`);
|
|
75
|
+
} else if (key in SPELLED || /^on[a-z]/.test(key)) fail("PART_KEY", name, `part "${part}" has "${key}"; parts use React's spellings, which each framework's glue maps to its own, so write "${SPELLED[key] ?? `on${key[2].toUpperCase()}${key.slice(3)}`}"${key in SPELLED ? "" : " with the event's words capitalised (onKeyDown, onDoubleClick)"}.`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { warnOnce as a, suggest as i, checkParts as n, fail as r, checkKeys as t };
|
package/dist/dom.d.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
//#region src/dom/dismiss.d.ts
|
|
2
|
+
interface DismissOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Escape, a platform close request (Android's back gesture), or a
|
|
5
|
+
* `<dialog>` that closed without the machine (`<form method="dialog">`,
|
|
6
|
+
* a close request the page may not cancel).
|
|
7
|
+
*/
|
|
8
|
+
onEscape?: () => void;
|
|
9
|
+
/** A pointer press, or focus, outside the element. */
|
|
10
|
+
onOutside?: () => void;
|
|
11
|
+
/** Presses and focus here are not outside: the trigger, so its own click toggles. */
|
|
12
|
+
exclude?: Element | null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Reports Escape and interaction outside `element` to the machine instead
|
|
16
|
+
* of closing anything itself, so a controlled overlay can refuse (PLAN D9).
|
|
17
|
+
* Layers stack: Escape goes to the top layer with `onEscape`, and a press
|
|
18
|
+
* or focus outside to the top layer with `onOutside`, so Escape in a nested
|
|
19
|
+
* menu or dialog closes the inner one alone. A layer above is part of the
|
|
20
|
+
* one below: a press in a menu opened from a dialog is not outside the
|
|
21
|
+
* dialog. Escape that no layer handles is left to the page and the browser.
|
|
22
|
+
*
|
|
23
|
+
* On a modal `<dialog>`, a press on the `::backdrop` counts as outside, and
|
|
24
|
+
* Escape is reported without the browser closing the dialog behind the
|
|
25
|
+
* machine's back (`closedby` is not Baseline). When it closes all the same,
|
|
26
|
+
* `onEscape` hears it, and a machine that stays open gets it shown again.
|
|
27
|
+
*/
|
|
28
|
+
export declare function dismiss(element: Element, options: DismissOptions): () => void;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/dom/focus-trap.d.ts
|
|
31
|
+
/**
|
|
32
|
+
* Keeps keyboard focus inside `container`, a modal overlay that is not a
|
|
33
|
+
* `<dialog>` (PLAN §4.5, §11): focus moves in (`[autofocus]`, else the first
|
|
34
|
+
* tabbable element, else the container), Tab and Shift+Tab wrap at the ends
|
|
35
|
+
* and are otherwise the browser's, focus that leaves is brought back (to
|
|
36
|
+
* the next element when Tab took it out, else to where it was), and the
|
|
37
|
+
* cleanup returns focus to where it was, or to `<body>` when that element
|
|
38
|
+
* is gone.
|
|
39
|
+
*
|
|
40
|
+
* Focus may sit in a layer opened above it with `dismiss` or another
|
|
41
|
+
* `focusTrap` (a menu, wherever it is rendered). A container with nothing
|
|
42
|
+
* to focus gets `tabindex="-1"` while the trap lasts.
|
|
43
|
+
*
|
|
44
|
+
* A modal `<dialog>` opened with `showModal()` needs none of this: the
|
|
45
|
+
* browser moves focus in, makes the page inert and restores focus on
|
|
46
|
+
* `close()`, and lets Tab reach its own UI, as it intends for every page.
|
|
47
|
+
*/
|
|
48
|
+
export declare function focusTrap(container: HTMLElement): () => void;
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/dom/hide-others.d.ts
|
|
51
|
+
/**
|
|
52
|
+
* Makes everything outside `keep` inert: out of the accessibility tree,
|
|
53
|
+
* unfocusable and deaf to the pointer, with no `aria-hidden` walk or focus
|
|
54
|
+
* trap to keep in step (PLAN D15, S5). For a modal overlay that is not a
|
|
55
|
+
* `<dialog>`; `showModal()` does the same for a `<dialog>`. An overlay in a
|
|
56
|
+
* shadow root keeps its hosts, and the rest of its shadow tree is hidden.
|
|
57
|
+
*
|
|
58
|
+
* Live regions with nothing focusable inside stay outside it, so
|
|
59
|
+
* announcements keep reaching screen readers, and elements the page made
|
|
60
|
+
* inert itself are left as they are. A layer opened above while it lasts
|
|
61
|
+
* (`dismiss` or `focusTrap`: a menu from the overlay, rendered elsewhere)
|
|
62
|
+
* is kept too, until that layer goes.
|
|
63
|
+
*/
|
|
64
|
+
export declare function hideOthers(...keep: Element[]): () => void;
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/dom/live-region.d.ts
|
|
67
|
+
/**
|
|
68
|
+
* Announces `message` to screen readers while the effect runs: politely
|
|
69
|
+
* (`status`), or interrupting (`alert`) when `assertive`. The cleanup
|
|
70
|
+
* withdraws it if it is still showing.
|
|
71
|
+
*
|
|
72
|
+
* The region lives in the topmost modal `<dialog>` open when the message
|
|
73
|
+
* lands, since everything outside a modal dialog is inert and silent, else
|
|
74
|
+
* in `<body>`;
|
|
75
|
+
* `hideOthers` leaves live regions out. It is created once and kept: a
|
|
76
|
+
* screen reader only follows regions that existed before their text changed.
|
|
77
|
+
*/
|
|
78
|
+
export declare function liveRegion(message: string, options?: {
|
|
79
|
+
assertive?: boolean;
|
|
80
|
+
}): () => void;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/dom/place.d.ts
|
|
83
|
+
/**
|
|
84
|
+
* Where a floating element goes next to its anchor: the arithmetic behind
|
|
85
|
+
* `popper`, with no DOM, so it is tested on plain numbers. Coordinates are
|
|
86
|
+
* the viewport's, as `getBoundingClientRect()` gives them.
|
|
87
|
+
*/
|
|
88
|
+
type Side = "top" | "right" | "bottom" | "left";
|
|
89
|
+
/** A side, aligned to the anchor's centre, or to its start or end edge. */
|
|
90
|
+
type Placement = Side | `${Side}-start` | `${Side}-end`;
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/dom/popper.d.ts
|
|
93
|
+
interface PopperOptions {
|
|
94
|
+
/** Default `"bottom"`. */
|
|
95
|
+
placement?: Placement;
|
|
96
|
+
/** Gap from the anchor in pixels; default 8. */
|
|
97
|
+
offset?: number;
|
|
98
|
+
/** Space kept from the viewport's edges; default 8. */
|
|
99
|
+
padding?: number;
|
|
100
|
+
/** Move to the opposite side when this one lacks room; default true. */
|
|
101
|
+
flip?: boolean;
|
|
102
|
+
/** Slide along the anchor to stay in the viewport; default true. */
|
|
103
|
+
shift?: boolean;
|
|
104
|
+
/** An element inside the floating one, moved to point at the anchor's centre. */
|
|
105
|
+
arrow?: HTMLElement | null;
|
|
106
|
+
/** Give the floating element the anchor's width (a listbox under its input). */
|
|
107
|
+
sameWidth?: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Keeps `floating` next to `anchor` while it is shown: placed, flipped and
|
|
111
|
+
* shifted inside the viewport, and moved again when either resizes, the
|
|
112
|
+
* window resizes or anything scrolls, once per animation frame
|
|
113
|
+
* (PLAN §4.5; no `popover` or anchor positioning while they are not Baseline
|
|
114
|
+
* widely available, D16).
|
|
115
|
+
*
|
|
116
|
+
* `floating` is positioned `fixed`, so its containing block must be the
|
|
117
|
+
* viewport: render it outside transformed, filtered or `contain`ed
|
|
118
|
+
* ancestors (a portal). The placement taken is set as `data-placement`
|
|
119
|
+
* for styles that depend on the side, the arrow's among them.
|
|
120
|
+
*/
|
|
121
|
+
export declare function popper(anchor: Element, floating: HTMLElement, options?: PopperOptions): () => void;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/dom/presence.d.ts
|
|
124
|
+
/**
|
|
125
|
+
* Calls `onDone` once `element`'s CSS animations and transitions have
|
|
126
|
+
* finished, its `::before`, `::after` and `::backdrop`'s included, so a closing state can leave the element mounted until its exit
|
|
127
|
+
* animation ends (PLAN §4.5). Called after the state change that starts the
|
|
128
|
+
* animation: reading the element's animations applies its new styles first.
|
|
129
|
+
*
|
|
130
|
+
* Done on the next microtask when nothing runs, when the user prefers
|
|
131
|
+
* reduced motion, or when an animation is cancelled; infinite animations
|
|
132
|
+
* (a spinner inside the styles) are not waited for. The cleanup stops a
|
|
133
|
+
* pending call, for a state left before the animation ended.
|
|
134
|
+
*
|
|
135
|
+
* A `<dialog>` animates out only while it is open: `close()` it after
|
|
136
|
+
* `onDone`, in the cleanup of a state that holds both `open` and `closing`.
|
|
137
|
+
*/
|
|
138
|
+
export declare function presence(element: Element, onDone: () => void): () => void;
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/dom/scroll-lock.d.ts
|
|
141
|
+
/**
|
|
142
|
+
* Stops the page from scrolling under a modal overlay; the platform has no
|
|
143
|
+
* such lock (S5). Nested locks count: the page scrolls again when the last
|
|
144
|
+
* one is cleaned up.
|
|
145
|
+
*
|
|
146
|
+
* Hiding the root's overflow removes a classic scrollbar, so its width is
|
|
147
|
+
* added to the root's padding on the scrollbar's side and exposed as
|
|
148
|
+
* `--scrollbar-width` for fixed elements that must not shift either;
|
|
149
|
+
* under `scrollbar-gutter: stable` the space stays, and both are 0.
|
|
150
|
+
*/
|
|
151
|
+
export declare function scrollLock(): () => void;
|
|
152
|
+
//#endregion
|
|
153
|
+
//#region src/dom/spread.d.ts
|
|
154
|
+
/**
|
|
155
|
+
* `spread(element, part)`: a part's props on an element without a framework
|
|
156
|
+
* (PLAN §4.4, §5.5's vanilla row), as `{...part}` does in JSX. Only what
|
|
157
|
+
* changed since the last spread onto the element is written; handlers are
|
|
158
|
+
* one listener per event type, which calls the part's current handler.
|
|
159
|
+
*
|
|
160
|
+
* - `on<event>`: the handler for `<event>`.
|
|
161
|
+
* - `aria-*` and `data-*`: the value as text, `false` included.
|
|
162
|
+
* - `value`, `checked`, `selected` and `indeterminate`: the element's
|
|
163
|
+
* property, as frameworks set them (the attribute is only the default).
|
|
164
|
+
* - Others: `true` is the attribute present and empty; `false`, `null` and
|
|
165
|
+
* `undefined` remove it.
|
|
166
|
+
*/
|
|
167
|
+
export declare function spread(element: Element, part: object): void;
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/dom/typeahead.d.ts
|
|
170
|
+
/**
|
|
171
|
+
* Typeahead for a part's `onKeyDown`: the item in `container` whose text
|
|
172
|
+
* starts with what was typed within the last second, or undefined. Items
|
|
173
|
+
* are the container's options, menu items and tree items that are not
|
|
174
|
+
* `aria-disabled` or hidden; the current one is the key's target, or the
|
|
175
|
+
* element its `aria-activedescendant` names. A key it uses has its default
|
|
176
|
+
* prevented, so a Space inside a query does not activate the item.
|
|
177
|
+
*
|
|
178
|
+
* ```ts
|
|
179
|
+
* onKeyDown: ({ el, send }, event) => {
|
|
180
|
+
* const item = typeahead(event, el.content);
|
|
181
|
+
* if (item) send("HIGHLIGHT", { id: item.id });
|
|
182
|
+
* },
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
export declare function typeahead(event: KeyboardEvent, container: Element): HTMLElement | undefined;
|
|
186
|
+
//#endregion
|
|
187
|
+
export type { DismissOptions, Placement, PopperOptions };
|