octane 0.4.3 → 0.6.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/dist/behavior-form-submissions.d.ts +12 -0
- package/dist/behavior-form-submissions.js +228 -0
- package/dist/behavior-root-types.d.ts +93 -0
- package/dist/behavior-root-types.js +0 -0
- package/dist/behavior-root.d.ts +10 -2
- package/dist/behavior-root.js +128 -119
- package/dist/cjs/behavior-form-submissions.cjs +232 -0
- package/dist/cjs/behavior-root.cjs +129 -119
- package/dist/cjs/dom-bindings.cjs +266 -19
- package/dist/cjs/form-submission.cjs +74 -0
- package/dist/cjs/hydration/control-capture.cjs +2 -1
- package/dist/cjs/hydration/event-capture.cjs +77 -4
- package/dist/cjs/hydration/native-intent.cjs +95 -0
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/runtime.cjs +64 -8
- package/dist/cjs/runtime.server.cjs +57 -9
- package/dist/cjs/server/early-signals.cjs +20 -5
- package/dist/cjs/server/streamed-region.cjs +2 -1
- package/dist/cjs/signals/engine.cjs +91 -185
- package/dist/cjs/signals/facade.cjs +6 -4
- package/dist/cjs/signals/native-read-seeds.cjs +131 -10
- package/dist/cjs/signals/requests.cjs +16 -16
- package/dist/cjs/signals/scope-streams.cjs +170 -0
- package/dist/cjs/version.cjs +1 -1
- package/dist/compiler/compile-universal.js +98 -22
- package/dist/compiler/compile.js +151 -42
- package/dist/compiler/dom-binding-program.js +7 -5
- package/dist/compiler/dom-bindings.js +135 -21
- package/dist/compiler/hydrate-boundaries.js +36 -0
- package/dist/compiler/style-scopes.js +5 -5
- package/dist/compiler/volar.LICENSES.txt +2 -2
- package/dist/compiler/volar.js +2141 -413
- package/dist/dom-binding-program.d.ts +2 -2
- package/dist/dom-binding-signals.d.ts +2 -0
- package/dist/dom-binding-signals.js +30 -1
- package/dist/dom-bindings.d.ts +8 -0
- package/dist/dom-bindings.js +265 -19
- package/dist/form-submission.d.ts +66 -0
- package/dist/form-submission.js +43 -0
- package/dist/hydration/control-capture.d.ts +4 -2
- package/dist/hydration/control-capture.js +2 -1
- package/dist/hydration/event-capture.d.ts +6 -0
- package/dist/hydration/event-capture.js +79 -4
- package/dist/hydration/independent-island.d.ts +7 -1
- package/dist/hydration/independent-island.js +38 -13
- package/dist/hydration/native-intent.d.ts +29 -0
- package/dist/hydration/native-intent.js +68 -0
- package/dist/hydration/streamed-signals.d.ts +2 -2
- package/dist/hydration/streamed-signals.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/runtime.d.ts +9 -1
- package/dist/runtime.js +66 -8
- package/dist/runtime.server.d.ts +10 -3
- package/dist/runtime.server.js +59 -10
- package/dist/server/early-signals.d.ts +3 -1
- package/dist/server/early-signals.js +25 -5
- package/dist/server/index.d.ts +1 -1
- package/dist/server/streamed-region.d.ts +3 -0
- package/dist/server/streamed-region.js +2 -1
- package/dist/signals/engine.d.ts +12 -23
- package/dist/signals/engine.js +92 -191
- package/dist/signals/facade.js +6 -4
- package/dist/signals/native-read-seeds.d.ts +23 -4
- package/dist/signals/native-read-seeds.js +129 -10
- package/dist/signals/requests.d.ts +8 -5
- package/dist/signals/requests.js +16 -16
- package/dist/signals/scope-streams.d.ts +37 -0
- package/dist/signals/scope-streams.js +147 -0
- package/dist/tsrx-iterable.d.ts +7 -6
- package/dist/tsrx-iterable.js +3 -2
- package/dist/universal-core.d.ts +7 -1
- package/dist/universal-core.js +29 -3
- package/dist/version.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare const FORM_SUBMISSION_CAPTURE: unique symbol;
|
|
2
|
+
/** Opaque synchronous opt-in produced by captureFormSubmissions(). */
|
|
3
|
+
export interface FormSubmissionCapture {
|
|
4
|
+
readonly [FORM_SUBMISSION_CAPTURE]: true;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Explicitly connect parser-time commands to this behavior root before any
|
|
8
|
+
* registration can adopt its DOM. Unconfigured nested roots reserve their own
|
|
9
|
+
* scope and keep the ordinary two-argument native captureEvent contract.
|
|
10
|
+
*/
|
|
11
|
+
export declare function captureFormSubmissions(): FormSubmissionCapture;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FORM_SUBMISSION_ATTR,
|
|
3
|
+
getEarlyFormSubmissionMailbox,
|
|
4
|
+
isEarlyFormSubmissionCurrent,
|
|
5
|
+
isEarlyFormSubmitActivation
|
|
6
|
+
} from "./form-submission.js";
|
|
7
|
+
import {
|
|
8
|
+
HYDRATE_ID_ATTR,
|
|
9
|
+
HYDRATE_INDEPENDENT_ATTR,
|
|
10
|
+
HYDRATE_WHEN_ATTR
|
|
11
|
+
} from "./hydration-markers.js";
|
|
12
|
+
import {
|
|
13
|
+
EARLY_HYDRATION_INTENTS_KEY,
|
|
14
|
+
HYDRATE_INTERACTION_EVENTS_ATTR
|
|
15
|
+
} from "./hydration/interaction-config.js";
|
|
16
|
+
import {
|
|
17
|
+
captureNativeHydrationIntent,
|
|
18
|
+
initializeHydrationEventCapture
|
|
19
|
+
} from "./hydration/event-capture.js";
|
|
20
|
+
import {
|
|
21
|
+
getNativeHydrationCapture,
|
|
22
|
+
getNativeHydrationDocument,
|
|
23
|
+
getNativeHydrationDOM,
|
|
24
|
+
NATIVE_HYDRATION_CAPTURE_KEY
|
|
25
|
+
} from "./hydration/native-intent.js";
|
|
26
|
+
let earlySubmissionRanges;
|
|
27
|
+
let earlySubmissionRoots;
|
|
28
|
+
let controllers;
|
|
29
|
+
function captureFormSubmissions() {
|
|
30
|
+
const capture = (root, flush, fail, range, matches, canceled) => {
|
|
31
|
+
root.dom = getNativeHydrationDOM(root.document);
|
|
32
|
+
const mailbox = getEarlyFormSubmissionMailbox(root.document);
|
|
33
|
+
if (mailbox === void 0) return;
|
|
34
|
+
const services = { flush, fail, range, matches, canceled };
|
|
35
|
+
installFormSubmissionActivation(root.document, mailbox);
|
|
36
|
+
let controller = controllers?.get(root.registry);
|
|
37
|
+
if (controller === void 0) {
|
|
38
|
+
controller = createSubmissionController(root, mailbox, services);
|
|
39
|
+
(controllers ??= /* @__PURE__ */ new WeakMap()).set(root.registry, controller);
|
|
40
|
+
root.registry.capture = controller;
|
|
41
|
+
}
|
|
42
|
+
controller.enabledRoots.add(root);
|
|
43
|
+
controller.flush();
|
|
44
|
+
};
|
|
45
|
+
capture.document = getNativeHydrationDocument;
|
|
46
|
+
return capture;
|
|
47
|
+
}
|
|
48
|
+
function installFormSubmissionActivation(document, mailbox) {
|
|
49
|
+
let feature = getNativeHydrationCapture(document);
|
|
50
|
+
if (feature?.push !== void 0) return;
|
|
51
|
+
if (feature === void 0) {
|
|
52
|
+
feature = { skip: isEarlyFormSubmitActivation };
|
|
53
|
+
document[NATIVE_HYDRATION_CAPTURE_KEY] = feature;
|
|
54
|
+
}
|
|
55
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
56
|
+
const elementPrototype = formSubmissionElementPrototype(document);
|
|
57
|
+
const dom = getNativeHydrationDOM(document);
|
|
58
|
+
const queued = (packet) => {
|
|
59
|
+
const [event, form, boundary, id, when, events] = packet;
|
|
60
|
+
if (!packet[8] || seen.has(event)) return;
|
|
61
|
+
seen.add(event);
|
|
62
|
+
const record = mailbox.q.find((submission) => submission.event === event);
|
|
63
|
+
const parent = record === void 0 ? dom.parent(form) : record.parent;
|
|
64
|
+
const key = record?.key ?? elementPrototype.getAttribute.call(form, FORM_SUBMISSION_ATTR);
|
|
65
|
+
const current = () => !record?.discarded && (record?.valid?.() ?? true) && mailbox.captures(form) && event.target === form && dom.connected(form) && dom.connected(boundary) && dom.owner(form) === document && dom.owner(boundary) === document && dom.parent(form) === parent && elementPrototype.getAttribute.call(form, FORM_SUBMISSION_ATTR) === key && elementPrototype.closest.call(form, `[${HYDRATE_INDEPENDENT_ATTR}]`) === boundary && elementPrototype.getAttribute.call(boundary, HYDRATE_ID_ATTR) === id && (when === "interaction" || when === "dynamic") && elementPrototype.getAttribute.call(boundary, HYDRATE_WHEN_ATTR) === when && elementPrototype.getAttribute.call(boundary, HYDRATE_INTERACTION_EVENTS_ATTR) === events;
|
|
66
|
+
captureNativeHydrationIntent(boundary, event, current);
|
|
67
|
+
};
|
|
68
|
+
feature.push = queued;
|
|
69
|
+
initializeHydrationEventCapture(document);
|
|
70
|
+
const host = document;
|
|
71
|
+
const intents = host[EARLY_HYDRATION_INTENTS_KEY];
|
|
72
|
+
for (const packet of intents?.q.splice(0) ?? []) queued(packet);
|
|
73
|
+
for (const submission of mailbox.q) {
|
|
74
|
+
if (seen.has(submission.event) || submission.boundary === null || submission.boundaryId === null)
|
|
75
|
+
continue;
|
|
76
|
+
intents?.capture?.([
|
|
77
|
+
submission.event,
|
|
78
|
+
submission.form,
|
|
79
|
+
submission.boundary,
|
|
80
|
+
submission.boundaryId,
|
|
81
|
+
submission.boundaryWhen,
|
|
82
|
+
submission.boundaryEvents,
|
|
83
|
+
void 0,
|
|
84
|
+
void 0,
|
|
85
|
+
true,
|
|
86
|
+
submission.sequence
|
|
87
|
+
]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function createSubmissionController(root, mailbox, services) {
|
|
91
|
+
const registry = root.registry;
|
|
92
|
+
const document = root.document;
|
|
93
|
+
const enabledRoots = /* @__PURE__ */ new Set();
|
|
94
|
+
const receive = (submission) => receiveEarlyFormSubmission(document, registry, mailbox, submission, enabledRoots, services);
|
|
95
|
+
const controller = {
|
|
96
|
+
enabledRoots,
|
|
97
|
+
flush: () => mailbox.flush(),
|
|
98
|
+
skip: (owner, event) => enabledRoots.has(owner) && mailbox.has(event),
|
|
99
|
+
release: (entry) => {
|
|
100
|
+
if (enabledRoots.has(entry.root)) releaseBehaviorSubmissions(entry, services);
|
|
101
|
+
},
|
|
102
|
+
dispose: (owner) => {
|
|
103
|
+
if (registry.roots.get(owner.container) !== owner) return;
|
|
104
|
+
if (enabledRoots.has(owner)) {
|
|
105
|
+
for (const entry of owner.behaviors) releaseBehaviorSubmissions(entry, services);
|
|
106
|
+
}
|
|
107
|
+
for (const submission of [...mailbox.q]) {
|
|
108
|
+
if (containsFormSubmission(owner, submission.form) && !hasNestedSubmissionOwner(owner, submission.form))
|
|
109
|
+
mailbox.release(submission.form);
|
|
110
|
+
}
|
|
111
|
+
enabledRoots.delete(owner);
|
|
112
|
+
if (enabledRoots.size === 0) {
|
|
113
|
+
if (mailbox.receive === receive) mailbox.receive = void 0;
|
|
114
|
+
if (registry.capture === controller) registry.capture = void 0;
|
|
115
|
+
controllers?.delete(registry);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
mailbox.receive = receive;
|
|
120
|
+
return controller;
|
|
121
|
+
}
|
|
122
|
+
function formSubmissionElementPrototype(document) {
|
|
123
|
+
return (document.defaultView?.Element ?? globalThis.Element).prototype;
|
|
124
|
+
}
|
|
125
|
+
function containsFormSubmission(root, form) {
|
|
126
|
+
return getNativeHydrationDOM(root.document).contains(root.container, form);
|
|
127
|
+
}
|
|
128
|
+
function matchesFormSubmissionTarget(record, form) {
|
|
129
|
+
return typeof record.entry.target === "string" ? formSubmissionElementPrototype(record.root.document).matches.call(form, record.entry.target) : record.entry.target === form;
|
|
130
|
+
}
|
|
131
|
+
function receiveEarlyFormSubmission(document, registry, mailbox, submission, enabledRoots, services) {
|
|
132
|
+
if (submission.snapshot === void 0) return false;
|
|
133
|
+
if (!isEarlyFormSubmissionCurrent(submission, document)) return true;
|
|
134
|
+
const previousRoot = earlySubmissionRoots?.get(submission);
|
|
135
|
+
if (previousRoot !== void 0 && (previousRoot.disposed || previousRoot.controller.signal.aborted || !containsFormSubmission(previousRoot, submission.form))) {
|
|
136
|
+
submission.discarded = true;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
let rangeElement = submission.form;
|
|
140
|
+
let acceptedRange;
|
|
141
|
+
while (rangeElement !== null) {
|
|
142
|
+
acceptedRange = registry.ranges.get(rangeElement);
|
|
143
|
+
if (acceptedRange !== void 0) break;
|
|
144
|
+
rangeElement = getNativeHydrationDOM(document).parent(rangeElement);
|
|
145
|
+
}
|
|
146
|
+
const previousRange = earlySubmissionRanges?.get(submission);
|
|
147
|
+
if (previousRange !== void 0 && previousRange !== acceptedRange) {
|
|
148
|
+
submission.discarded = true;
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
if (acceptedRange !== void 0 && previousRange === void 0)
|
|
152
|
+
(earlySubmissionRanges ??= /* @__PURE__ */ new WeakMap()).set(submission, acceptedRange);
|
|
153
|
+
let ownerRoot;
|
|
154
|
+
for (const root of registry.roots.values()) {
|
|
155
|
+
if (root.disposed || !containsFormSubmission(root, submission.form)) continue;
|
|
156
|
+
if (ownerRoot === void 0 || formSubmissionElementPrototype(document).contains.call(ownerRoot.container, root.container))
|
|
157
|
+
ownerRoot = root;
|
|
158
|
+
}
|
|
159
|
+
if (ownerRoot !== void 0 && previousRoot === void 0)
|
|
160
|
+
(earlySubmissionRoots ??= /* @__PURE__ */ new WeakMap()).set(submission, ownerRoot);
|
|
161
|
+
const record = ownerRoot !== void 0 && enabledRoots.has(ownerRoot) ? ownerRoot.byId.get(submission.key) : void 0;
|
|
162
|
+
if (record === void 0 || record.controller.signal.aborted || !record.entry.events?.includes("submit") || record.entry.captureEvent === void 0 || !matchesFormSubmissionTarget(record, submission.form) || !services.matches(record, services.range(record.root, submission.form)))
|
|
163
|
+
return false;
|
|
164
|
+
const range = services.range(record.root, submission.form);
|
|
165
|
+
const queued = {
|
|
166
|
+
event: submission.event,
|
|
167
|
+
element: submission.form,
|
|
168
|
+
range,
|
|
169
|
+
payload: services.canceled,
|
|
170
|
+
valid: () => {
|
|
171
|
+
const valid = !submission.discarded && !record.controller.signal.aborted && !record.root.controller.signal.aborted && mailbox.captures(submission.form) && containsFormSubmission(record.root, submission.form) && isEarlyFormSubmissionCurrent(submission, document) && services.range(record.root, submission.form) === range;
|
|
172
|
+
if (!valid) submission.discarded = true;
|
|
173
|
+
return valid;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
submission.valid = queued.valid;
|
|
177
|
+
record.queue.push(queued);
|
|
178
|
+
if (range?.status === "pending") record.waiting.add(range);
|
|
179
|
+
record.captureDepth = (record.captureDepth ?? 0) + 1;
|
|
180
|
+
try {
|
|
181
|
+
const payload = record.entry.captureEvent(
|
|
182
|
+
submission.event,
|
|
183
|
+
submission.form,
|
|
184
|
+
submission.snapshot
|
|
185
|
+
);
|
|
186
|
+
if (!record.controller.signal.aborted && containsFormSubmission(record.root, submission.form) && matchesFormSubmissionTarget(record, submission.form) && services.range(record.root, submission.form) === range && isEarlyFormSubmissionCurrent(submission, document))
|
|
187
|
+
queued.payload = payload;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
services.fail(record, error);
|
|
190
|
+
throw error;
|
|
191
|
+
} finally {
|
|
192
|
+
record.captureDepth--;
|
|
193
|
+
}
|
|
194
|
+
submission.snapshot = void 0;
|
|
195
|
+
if (queued.payload === services.canceled) submission.discarded = true;
|
|
196
|
+
services.flush(record);
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
function hasNestedSubmissionOwner(root, form) {
|
|
200
|
+
for (const nested of root.registry.roots.values()) {
|
|
201
|
+
if (nested === root || nested.disposed || !formSubmissionElementPrototype(root.document).contains.call(
|
|
202
|
+
root.container,
|
|
203
|
+
nested.container
|
|
204
|
+
) || !containsFormSubmission(nested, form))
|
|
205
|
+
continue;
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
function releaseBehaviorSubmissions(record, services) {
|
|
211
|
+
if (record.entry.id === void 0 || !record.entry.events?.includes("submit") || record.entry.captureEvent === void 0)
|
|
212
|
+
return;
|
|
213
|
+
const mailbox = getEarlyFormSubmissionMailbox(record.root.document);
|
|
214
|
+
if (mailbox === void 0) return;
|
|
215
|
+
const elementPrototype = formSubmissionElementPrototype(record.root.document);
|
|
216
|
+
for (const form of elementPrototype.querySelectorAll.call(
|
|
217
|
+
record.root.container,
|
|
218
|
+
`form[${FORM_SUBMISSION_ATTR}]`
|
|
219
|
+
)) {
|
|
220
|
+
if (elementPrototype.getAttribute.call(form, FORM_SUBMISSION_ATTR) === record.entry.id && matchesFormSubmissionTarget(record, form) && services.matches(record, services.range(record.root, form)) && !hasNestedSubmissionOwner(record.root, form))
|
|
221
|
+
mailbox.release(form);
|
|
222
|
+
}
|
|
223
|
+
if (elementPrototype.matches.call(record.root.container, "form") && elementPrototype.getAttribute.call(record.root.container, FORM_SUBMISSION_ATTR) === record.entry.id && matchesFormSubmissionTarget(record, record.root.container) && services.matches(record, services.range(record.root, record.root.container)) && !hasNestedSubmissionOwner(record.root, record.root.container))
|
|
224
|
+
mailbox.release(record.root.container);
|
|
225
|
+
}
|
|
226
|
+
export {
|
|
227
|
+
captureFormSubmissions
|
|
228
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { BehaviorCleanup, BehaviorEntry, ExternalRange } from './behavior-root.js';
|
|
2
|
+
import type { NativeHydrationDOM } from './hydration/native-intent.js';
|
|
3
|
+
export type Readiness = {
|
|
4
|
+
promise: Promise<void>;
|
|
5
|
+
resolve: () => void;
|
|
6
|
+
reject: (reason: unknown) => void;
|
|
7
|
+
settled: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type DocumentRegistry = {
|
|
10
|
+
roots: Map<Element, RootRecord>;
|
|
11
|
+
ranges: Map<Element, RangeRecord>;
|
|
12
|
+
capture?: BehaviorCaptureHooks;
|
|
13
|
+
};
|
|
14
|
+
export type BehaviorDOM = Pick<NativeHydrationDOM, 'element' | 'parent' | 'matches' | 'query' | 'target'> & {
|
|
15
|
+
contains(container: Element, element: Element, document: Document): boolean;
|
|
16
|
+
};
|
|
17
|
+
export type RootRecord = {
|
|
18
|
+
container: Element;
|
|
19
|
+
document: Document;
|
|
20
|
+
dom: BehaviorDOM;
|
|
21
|
+
registry: DocumentRegistry;
|
|
22
|
+
controller: AbortController;
|
|
23
|
+
behaviors: Set<EntryRecord>;
|
|
24
|
+
byId: Map<string, EntryRecord>;
|
|
25
|
+
ranges: Set<RangeRecord>;
|
|
26
|
+
pending: Set<Promise<void>>;
|
|
27
|
+
listeners: Map<string, EventListener>;
|
|
28
|
+
observer: MutationObserver | null;
|
|
29
|
+
disposed: boolean;
|
|
30
|
+
unlinkSignal: (() => void) | null;
|
|
31
|
+
};
|
|
32
|
+
export type RangeRecord = {
|
|
33
|
+
root: RootRecord;
|
|
34
|
+
element: Element;
|
|
35
|
+
owner: unknown;
|
|
36
|
+
controller: AbortController;
|
|
37
|
+
ready: Readiness;
|
|
38
|
+
status: 'pending' | 'ready' | 'failed' | 'disposed';
|
|
39
|
+
unlinks: Array<() => void>;
|
|
40
|
+
publicRange: ExternalRange;
|
|
41
|
+
};
|
|
42
|
+
export type EntryRecord = {
|
|
43
|
+
root: RootRecord;
|
|
44
|
+
entry: BehaviorEntry;
|
|
45
|
+
controller: AbortController;
|
|
46
|
+
ready: Readiness;
|
|
47
|
+
status: 'pending' | 'active' | 'failed' | 'disposed';
|
|
48
|
+
adoptions: Map<Element, AdoptionRecord>;
|
|
49
|
+
pendingCount: number;
|
|
50
|
+
waiting: Set<RangeRecord>;
|
|
51
|
+
queue: Array<{
|
|
52
|
+
event: Event;
|
|
53
|
+
element: Element;
|
|
54
|
+
range: RangeRecord | undefined;
|
|
55
|
+
payload?: unknown;
|
|
56
|
+
valid?: () => boolean;
|
|
57
|
+
}>;
|
|
58
|
+
head: number;
|
|
59
|
+
flushDepth: number;
|
|
60
|
+
captureDepth?: number;
|
|
61
|
+
unlinks: Array<() => void>;
|
|
62
|
+
scanned: boolean;
|
|
63
|
+
};
|
|
64
|
+
/** @internal Optional native command ingress; implementations stay outside the core. */
|
|
65
|
+
export type BehaviorCaptureHooks = {
|
|
66
|
+
flush(): void;
|
|
67
|
+
skip(root: RootRecord, event: Event): boolean;
|
|
68
|
+
release(entry: EntryRecord): void;
|
|
69
|
+
dispose(root: RootRecord): void;
|
|
70
|
+
};
|
|
71
|
+
/** @internal Existing FIFO/readiness operations supplied only to an opted-in root. */
|
|
72
|
+
export type BehaviorCaptureServices = {
|
|
73
|
+
range(root: RootRecord, element: Element): RangeRecord | undefined;
|
|
74
|
+
matches(entry: EntryRecord, range: RangeRecord | undefined): boolean;
|
|
75
|
+
flush(entry: EntryRecord): void;
|
|
76
|
+
fail(entry: EntryRecord, error: unknown): void;
|
|
77
|
+
canceled: unknown;
|
|
78
|
+
};
|
|
79
|
+
/** @internal Callable representation of the public opaque capture configuration. */
|
|
80
|
+
export type BehaviorCaptureFactory = {
|
|
81
|
+
(root: RootRecord, flush: BehaviorCaptureServices['flush'], fail: BehaviorCaptureServices['fail'], range: BehaviorCaptureServices['range'], matches: BehaviorCaptureServices['matches'], canceled: unknown): void;
|
|
82
|
+
document(container: unknown): Document | null;
|
|
83
|
+
};
|
|
84
|
+
export type AdoptionRecord = {
|
|
85
|
+
entry: EntryRecord;
|
|
86
|
+
element: Element;
|
|
87
|
+
range: RangeRecord | undefined;
|
|
88
|
+
controller: AbortController;
|
|
89
|
+
unlinks: Array<() => void>;
|
|
90
|
+
cleanup: BehaviorCleanup | undefined;
|
|
91
|
+
pending: boolean;
|
|
92
|
+
disposed: boolean;
|
|
93
|
+
};
|
|
File without changes
|
package/dist/behavior-root.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
export { adoptBindings, mountBindings, unbound } from './dom-bindings.js';
|
|
2
2
|
export type { BindingSource, BindingOptions, BindingHandle } from './dom-bindings.js';
|
|
3
3
|
export type { BindingRange, BindingMountTarget } from './dom-binding-program.js';
|
|
4
|
+
import type { CapturedFormSubmission } from './form-submission.js';
|
|
5
|
+
import type { FormSubmissionCapture } from './behavior-form-submissions.js';
|
|
6
|
+
export type { FormSubmissionCapture } from './behavior-form-submissions.js';
|
|
7
|
+
export { captureFormSubmissions } from './behavior-form-submissions.js';
|
|
8
|
+
export type { CapturedFormSubmission } from './form-submission.js';
|
|
4
9
|
/** A behavior-only root observes existing DOM without taking reconciliation ownership. */
|
|
5
10
|
export interface BehaviorRootOptions {
|
|
6
11
|
/** Dispose this root when the enclosing page or document lifetime ends. */
|
|
7
12
|
signal?: AbortSignal;
|
|
8
13
|
/** Explicitly dispose an existing behavior root attached to this container. */
|
|
9
14
|
replace?: boolean;
|
|
15
|
+
/** Explicit synchronous parser-command ingress for this root. */
|
|
16
|
+
formSubmissions?: FormSubmissionCapture;
|
|
10
17
|
}
|
|
11
18
|
export interface BehaviorDisposeOptions {
|
|
12
19
|
/** Existing DOM is retained unless its removal is explicitly requested. */
|
|
@@ -46,10 +53,11 @@ export interface BehaviorEntry<Payload = unknown> {
|
|
|
46
53
|
/**
|
|
47
54
|
* Synchronously capture detached, immutable command arguments on the original
|
|
48
55
|
* native event, before readiness or adoption. Register eagerly; this cannot
|
|
49
|
-
* recover values
|
|
56
|
+
* recover earlier values unless the form opted into parser-time submit capture.
|
|
57
|
+
* Its third argument is the accepted snapshot for those native submissions.
|
|
50
58
|
* May preventDefault(), but must not return live DOM/state or a promise.
|
|
51
59
|
*/
|
|
52
|
-
captureEvent?(event: Event, element: Element): Payload;
|
|
60
|
+
captureEvent?(event: Event, element: Element, submission?: CapturedFormSubmission): Payload;
|
|
53
61
|
ready?: PromiseLike<unknown>;
|
|
54
62
|
dependencies?: readonly string[];
|
|
55
63
|
conflicts?: readonly string[];
|