@gyral/core 0.2.0 → 0.3.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/CHANGELOG.md +87 -0
- package/README.md +7 -5
- package/dist/children.d.ts +5 -2
- package/dist/children.js +8 -3
- package/dist/children.js.map +1 -1
- package/dist/command.js +6 -0
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +21 -0
- package/dist/compiler/ast.js +145 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +38 -0
- package/dist/compiler/compile.js +129 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/hooks.d.ts +18 -0
- package/dist/compiler/hooks.js +186 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +55 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/scan.d.ts +31 -0
- package/dist/compiler/scan.js +152 -0
- package/dist/compiler/scan.js.map +1 -0
- package/dist/compiler/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.js +35 -327
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +5 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +1 -0
- package/dist/devtools.js +3 -2
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-types.d.ts +5 -3
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/eslint/imports.d.ts +24 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.js +15 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +5 -0
- package/dist/eslint/template-rule.js +66 -0
- package/dist/eslint/template-rule.js.map +1 -0
- package/dist/features.d.ts +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +7 -12
- package/dist/focus.js +13 -10
- package/dist/focus.js.map +1 -1
- package/dist/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/hooks/labelled-by.d.ts +13 -0
- package/dist/hooks/labelled-by.js +51 -0
- package/dist/hooks/labelled-by.js.map +1 -0
- package/dist/host-model.d.ts +48 -0
- package/dist/host-model.js +155 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- package/dist/hydration.d.ts +13 -19
- package/dist/hydration.js +45 -45
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +9 -17
- package/dist/index.js +9 -18
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +31 -8
- package/dist/intent.js +82 -27
- package/dist/intent.js.map +1 -1
- package/dist/internal/interpreter.d.ts +7 -1
- package/dist/internal/interpreter.js +11 -4
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +3 -52
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +66 -0
- package/dist/prop.js +22 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +52 -21
- package/dist/props.js +150 -34
- package/dist/props.js.map +1 -1
- package/dist/scheduler.d.ts +39 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +102 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +50 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +10 -0
- package/dist/settled.js +40 -0
- package/dist/settled.js.map +1 -0
- package/dist/states.d.ts +3 -3
- package/dist/states.js +4 -7
- package/dist/states.js.map +1 -1
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +5 -6
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +6 -7
- package/dist/store-scope.js +11 -26
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +9 -2
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.js.map +1 -1
- package/dist/transitions.d.ts +5 -6
- package/dist/transitions.js +11 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +19 -23
- package/dist/types.js.map +1 -1
- package/dist/view/attributes.d.ts +6 -0
- package/dist/view/attributes.js +10 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +21 -0
- package/dist/view/index.js +21 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/normalize/check.d.ts +20 -0
- package/dist/view/normalize/check.js +78 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +13 -0
- package/dist/view/normalize/emit.js +136 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +7 -0
- package/dist/view/normalize/id.js +48 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +15 -0
- package/dist/view/normalize/normalize.js +36 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +30 -0
- package/dist/view/normalize/rules.js +90 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- package/dist/view/normalize/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +51 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +59 -0
- package/dist/view/normalize/tree.js +190 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +126 -0
- package/dist/view/normalize/types.js +26 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/{template-whitespace.js → view/normalize/whitespace.js} +24 -34
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +8 -0
- package/dist/view/prepare.js +57 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +63 -0
- package/dist/view/registry.js +19 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +77 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +269 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +61 -0
- package/dist/view/render/attr-parts.js +229 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +170 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -0
- package/dist/view/render/hook-part.js +20 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hooks.d.ts +40 -0
- package/dist/view/render/hooks.js +46 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- package/dist/view/render/list.d.ts +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +53 -0
- package/dist/view/render/mismatch.js.map +1 -0
- package/dist/view/render/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +18 -0
- package/dist/view/render/raw.js +68 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +12 -0
- package/dist/view/render/render.js +60 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- package/dist/view/render/values.d.ts +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +69 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +9 -0
- package/dist/view/server/component.js +42 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +28 -0
- package/dist/view/server/index.js +72 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +57 -0
- package/dist/view/server/tags.js +121 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +16 -0
- package/dist/view/server/values.js +86 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +16 -0
- package/dist/view/server/writer.js +155 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +3 -0
- package/dist/view/template-element.js +25 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +21 -0
- package/dist/view/template.js +30 -0
- package/dist/view/template.js.map +1 -0
- package/dist/vite.d.ts +45 -6
- package/dist/vite.js +150 -25
- package/dist/vite.js.map +1 -1
- package/package.json +39 -4
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/lit-html-check.d.ts +0 -6
- package/dist/lit-html-check.js +0 -48
- package/dist/lit-html-check.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.js.map +0 -1
- package/dist/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/template-whitespace.d.ts +0 -7
- package/dist/template-whitespace.js.map +0 -1
- package/dist/templates.d.ts +0 -5
- package/dist/templates.js +0 -15
- package/dist/templates.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// Module text helpers for the template compiler: offsets to line/column, code frames for build
|
|
2
|
+
// errors, and string splicing with a source map (no magic-string: @gyral/core has no runtime
|
|
3
|
+
// dependencies, and Vite doesn't expose one to plugins).
|
|
4
|
+
export class Lines {
|
|
5
|
+
constructor(code) {
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.starts = [0];
|
|
8
|
+
for (let k = code.indexOf('\n'); k !== -1; k = code.indexOf('\n', k + 1)) {
|
|
9
|
+
this.starts.push(k + 1);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
position(offset) {
|
|
13
|
+
let lo = 0;
|
|
14
|
+
let hi = this.starts.length - 1;
|
|
15
|
+
while (lo < hi) {
|
|
16
|
+
const mid = (lo + hi + 1) >> 1;
|
|
17
|
+
if ((this.starts[mid] ?? 0) <= offset)
|
|
18
|
+
lo = mid;
|
|
19
|
+
else
|
|
20
|
+
hi = mid - 1;
|
|
21
|
+
}
|
|
22
|
+
return { line: lo + 1, column: offset - (this.starts[lo] ?? 0) };
|
|
23
|
+
}
|
|
24
|
+
/** Two lines of context around `offset`, with a caret under it (Vite prints it). */
|
|
25
|
+
frame(offset, end = offset + 1) {
|
|
26
|
+
const { line, column } = this.position(offset);
|
|
27
|
+
const lines = this.code.split('\n');
|
|
28
|
+
const first = Math.max(1, line - 2);
|
|
29
|
+
const last = Math.min(lines.length, line + 2);
|
|
30
|
+
const width = String(last).length;
|
|
31
|
+
const out = [];
|
|
32
|
+
for (let n = first; n <= last; n++) {
|
|
33
|
+
const text = lines[n - 1] ?? '';
|
|
34
|
+
out.push(`${n === line ? '>' : ' '} ${String(n).padStart(width)} | ${text}`);
|
|
35
|
+
if (n === line) {
|
|
36
|
+
const span = Math.max(1, Math.min(end - offset, text.length - column));
|
|
37
|
+
out.push(` ${' '.repeat(width)} | ${' '.repeat(column)}${'^'.repeat(span)}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return out.join('\n');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
44
|
+
function vlq(value) {
|
|
45
|
+
let v = value < 0 ? (-value << 1) | 1 : value << 1;
|
|
46
|
+
let out = '';
|
|
47
|
+
do {
|
|
48
|
+
let digit = v & 31;
|
|
49
|
+
v >>>= 5;
|
|
50
|
+
if (v > 0)
|
|
51
|
+
digit |= 32;
|
|
52
|
+
out += B64[digit] ?? '';
|
|
53
|
+
} while (v > 0);
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Applies non-overlapping `edits` to `lines.code` and maps the result back to it: a segment at
|
|
58
|
+
* the start of every output line and at every edit boundary (line-level precision, like
|
|
59
|
+
* magic-string without `hires`).
|
|
60
|
+
*/
|
|
61
|
+
export function splice(lines, edits, file) {
|
|
62
|
+
const { code } = lines;
|
|
63
|
+
const sorted = [...edits].sort((a, b) => a.start - b.start);
|
|
64
|
+
let out = '';
|
|
65
|
+
const mapLines = [[]];
|
|
66
|
+
let genCol = 0;
|
|
67
|
+
let prev = { line: 0, column: 0 };
|
|
68
|
+
let prevGenCol = 0;
|
|
69
|
+
const mark = (offset) => {
|
|
70
|
+
const { line, column } = lines.position(offset);
|
|
71
|
+
const at = { line: line - 1, column };
|
|
72
|
+
const row = mapLines.at(-1);
|
|
73
|
+
if (row === undefined)
|
|
74
|
+
return;
|
|
75
|
+
if (row.length === 0)
|
|
76
|
+
prevGenCol = 0;
|
|
77
|
+
row.push(vlq(genCol - prevGenCol) + 'A' + vlq(at.line - prev.line) + vlq(at.column - prev.column));
|
|
78
|
+
prevGenCol = genCol;
|
|
79
|
+
prev = at;
|
|
80
|
+
};
|
|
81
|
+
const write = (text, origin, original) => {
|
|
82
|
+
let from = 0;
|
|
83
|
+
mark(origin);
|
|
84
|
+
for (let nl = text.indexOf('\n'); nl !== -1; nl = text.indexOf('\n', from)) {
|
|
85
|
+
out += text.slice(from, nl + 1);
|
|
86
|
+
from = nl + 1;
|
|
87
|
+
mapLines.push([]);
|
|
88
|
+
genCol = 0;
|
|
89
|
+
mark(original ? origin + from : origin);
|
|
90
|
+
}
|
|
91
|
+
out += text.slice(from);
|
|
92
|
+
genCol += text.length - from;
|
|
93
|
+
};
|
|
94
|
+
let pos = 0;
|
|
95
|
+
for (const edit of sorted) {
|
|
96
|
+
if (edit.start > pos)
|
|
97
|
+
write(code.slice(pos, edit.start), pos, true);
|
|
98
|
+
if (edit.text !== '')
|
|
99
|
+
write(edit.text, edit.start, false);
|
|
100
|
+
pos = Math.max(pos, edit.end);
|
|
101
|
+
}
|
|
102
|
+
if (pos < code.length)
|
|
103
|
+
write(code.slice(pos), pos, true);
|
|
104
|
+
return {
|
|
105
|
+
code: out,
|
|
106
|
+
map: {
|
|
107
|
+
version: 3,
|
|
108
|
+
sources: [file],
|
|
109
|
+
names: [],
|
|
110
|
+
mappings: mapLines.map((r) => r.join(',')).join(';'),
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/compiler/source.ts"],"names":[],"mappings":"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","sourcesContent":["// Module text helpers for the template compiler: offsets to line/column, code frames for build\n// errors, and string splicing with a source map (no magic-string: @gyral/core has no runtime\n// dependencies, and Vite doesn't expose one to plugins).\n\nexport interface Position {\n /** 1-based. */\n readonly line: number;\n /** 0-based. */\n readonly column: number;\n}\n\nexport class Lines {\n private readonly starts: number[] = [0];\n\n constructor(readonly code: string) {\n for (let k = code.indexOf('\\n'); k !== -1; k = code.indexOf('\\n', k + 1)) {\n this.starts.push(k + 1);\n }\n }\n\n position(offset: number): Position {\n let lo = 0;\n let hi = this.starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((this.starts[mid] ?? 0) <= offset) lo = mid;\n else hi = mid - 1;\n }\n return { line: lo + 1, column: offset - (this.starts[lo] ?? 0) };\n }\n\n /** Two lines of context around `offset`, with a caret under it (Vite prints it). */\n frame(offset: number, end = offset + 1): string {\n const { line, column } = this.position(offset);\n const lines = this.code.split('\\n');\n const first = Math.max(1, line - 2);\n const last = Math.min(lines.length, line + 2);\n const width = String(last).length;\n const out: string[] = [];\n for (let n = first; n <= last; n++) {\n const text = lines[n - 1] ?? '';\n out.push(`${n === line ? '>' : ' '} ${String(n).padStart(width)} | ${text}`);\n if (n === line) {\n const span = Math.max(1, Math.min(end - offset, text.length - column));\n out.push(` ${' '.repeat(width)} | ${' '.repeat(column)}${'^'.repeat(span)}`);\n }\n }\n return out.join('\\n');\n }\n}\n\nexport interface Edit {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n}\n\nexport interface SourceMap {\n readonly version: 3;\n readonly sources: string[];\n readonly names: string[];\n readonly mappings: string;\n}\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction vlq(value: number): string {\n let v = value < 0 ? (-value << 1) | 1 : value << 1;\n let out = '';\n do {\n let digit = v & 31;\n v >>>= 5;\n if (v > 0) digit |= 32;\n out += B64[digit] ?? '';\n } while (v > 0);\n return out;\n}\n\n/**\n * Applies non-overlapping `edits` to `lines.code` and maps the result back to it: a segment at\n * the start of every output line and at every edit boundary (line-level precision, like\n * magic-string without `hires`).\n */\nexport function splice(\n lines: Lines,\n edits: readonly Edit[],\n file: string,\n): { code: string; map: SourceMap } {\n const { code } = lines;\n const sorted = [...edits].sort((a, b) => a.start - b.start);\n let out = '';\n const mapLines: string[][] = [[]];\n let genCol = 0;\n let prev = { line: 0, column: 0 };\n let prevGenCol = 0;\n\n const mark = (offset: number): void => {\n const { line, column } = lines.position(offset);\n const at = { line: line - 1, column };\n const row = mapLines.at(-1);\n if (row === undefined) return;\n if (row.length === 0) prevGenCol = 0;\n row.push(\n vlq(genCol - prevGenCol) + 'A' + vlq(at.line - prev.line) + vlq(at.column - prev.column),\n );\n prevGenCol = genCol;\n prev = at;\n };\n\n const write = (text: string, origin: number, original: boolean): void => {\n let from = 0;\n mark(origin);\n for (let nl = text.indexOf('\\n'); nl !== -1; nl = text.indexOf('\\n', from)) {\n out += text.slice(from, nl + 1);\n from = nl + 1;\n mapLines.push([]);\n genCol = 0;\n mark(original ? origin + from : origin);\n }\n out += text.slice(from);\n genCol += text.length - from;\n };\n\n let pos = 0;\n for (const edit of sorted) {\n if (edit.start > pos) write(code.slice(pos, edit.start), pos, true);\n if (edit.text !== '') write(edit.text, edit.start, false);\n pos = Math.max(pos, edit.end);\n }\n if (pos < code.length) write(code.slice(pos), pos, true);\n return {\n code: out,\n map: {\n version: 3,\n sources: [file],\n names: [],\n mappings: mapLines.map((r) => r.join(',')).join(';'),\n },\n };\n}\n"]}
|
package/dist/define.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ComponentSpec, Tagged } from './types.js';
|
|
|
3
3
|
export type { GyralElement, GyralElementClass } from './element-types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.
|
|
6
|
-
* See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md
|
|
7
|
-
* 0008-forms.md and
|
|
6
|
+
* See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md,
|
|
7
|
+
* 0008-forms.md and view/05-element.md.
|
|
8
8
|
*/
|
|
9
9
|
export declare function define<S, M extends Tagged, P extends object = object, O extends Tagged = never>(tag: string, spec: ComponentSpec<S, M, P>): GyralElementClass<S, M, P, O>;
|
package/dist/define.js
CHANGED
|
@@ -1,338 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { StoreBinding } from './store-binding.js';
|
|
17
|
-
import { withViewTransition } from './transitions.js';
|
|
18
|
-
// Lit types `isServer` per build condition; widen it so both branches type-check (ADR 0012).
|
|
19
|
-
const onServer = isServer;
|
|
20
|
-
const DEFER_HYDRATION = 'defer-hydration';
|
|
21
|
-
/**
|
|
22
|
-
* Has Lit's hydrate support patched LitElement? It then defers `defer-hydration` elements
|
|
23
|
-
* itself. A bundler can evaluate Lit before `@gyral/ssr/hydrate`, so it may not have
|
|
24
|
-
* (gyral-czi.41); the patch adds an own static `observedAttributes` to LitElement.
|
|
25
|
-
*/
|
|
26
|
-
const litDefers = () => Object.prototype.hasOwnProperty.call(LitElement, 'observedAttributes');
|
|
1
|
+
import { elementClass } from './element.js';
|
|
2
|
+
import { markGyralHost } from './intent.js';
|
|
3
|
+
import { isLight } from './light-dom.js';
|
|
4
|
+
import { features } from './features.js';
|
|
5
|
+
import { recordSpec } from './server-specs.js';
|
|
6
|
+
import { DEV } from './view/index.js';
|
|
7
|
+
function checkSpec(tag, spec) {
|
|
8
|
+
const names = Object.keys(spec.props ?? {});
|
|
9
|
+
// The prop builders registered the prop feature (features.ts) if there are props.
|
|
10
|
+
if (names.length > 0)
|
|
11
|
+
features.props?.checkShadowed(tag, names);
|
|
12
|
+
if (DEV && isLight(spec) && spec.styles !== undefined) {
|
|
13
|
+
console.warn(`<${tag}> has shadow: false, so its styles are ignored; use document CSS.`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
27
16
|
/**
|
|
28
17
|
* Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.
|
|
29
|
-
* See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md
|
|
30
|
-
* 0008-forms.md and
|
|
18
|
+
* See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md,
|
|
19
|
+
* 0008-forms.md and view/05-element.md.
|
|
31
20
|
*/
|
|
32
21
|
export function define(tag, spec) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
checkSpec(tag, spec);
|
|
23
|
+
if (typeof HTMLElement === 'undefined') {
|
|
24
|
+
// No DOM (Node, Workers): the server renderer renders the spec itself (Phase 4). Only the
|
|
25
|
+
// spec is recorded here, so the server registry code never reaches client bundles.
|
|
26
|
+
recordSpec(tag, spec);
|
|
27
|
+
const Placeholder = Object.assign(function Placeholder() {
|
|
28
|
+
throw new Error(`<${tag}> is a browser element (render it with @gyral/core/server).`);
|
|
29
|
+
}, { spec, tagName: tag });
|
|
30
|
+
// Sound enough: outside the browser the class only carries `spec` and `tagName`.
|
|
31
|
+
return Placeholder;
|
|
40
32
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
constructor() {
|
|
46
|
-
super(...arguments);
|
|
47
|
-
this.drivers = {};
|
|
48
|
-
this.stores = {};
|
|
49
|
-
this.initialMessages = [];
|
|
50
|
-
/** Reads, subscriptions and writes for spec.stores (ADR 0013). */
|
|
51
|
-
this.#binding = new StoreBinding(this, tag, spec.stores ?? [], () => this.stores, (store, state, prev) => {
|
|
52
|
-
this.#storeChanged(store, state, prev);
|
|
53
|
-
});
|
|
54
|
-
this.#listening = false;
|
|
55
|
-
this.#pending = [];
|
|
56
|
-
/** init's commands on the hydration path; started in firstUpdated (ADR 0012). */
|
|
57
|
-
this.#afterHydration = [];
|
|
58
|
-
/** Resumed from server markup; reported by the Hydrated message. */
|
|
59
|
-
this.#serverRendered = false;
|
|
60
|
-
/** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */
|
|
61
|
-
this.#ssrShadow = false;
|
|
62
|
-
/** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */
|
|
63
|
-
this.#syncStates = spec.states === undefined || onServer ? undefined : attachStates(this);
|
|
64
|
-
// el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
|
|
65
|
-
this.#resolve = (driver) => this.drivers[driver.name] ??
|
|
66
|
-
providedDriver(this, driver.name) ??
|
|
67
|
-
spec.drivers?.[driver.name] ??
|
|
68
|
-
driver;
|
|
69
|
-
this.#onEvent = (event) => {
|
|
70
|
-
handleIntent(event, this.renderRoot, parsers, tag, this.#deliver);
|
|
71
|
-
};
|
|
72
|
-
this.#deliver = (msg) => {
|
|
73
|
-
if (msg !== undefined && this.isConnected)
|
|
74
|
-
this.#dispatch(msg);
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
static { this.properties = spec.props ?? {}; }
|
|
78
|
-
static { this.styles = componentStyles(spec, tag); }
|
|
79
|
-
static { this.spec = spec; }
|
|
80
|
-
static { this.tagName = tag; }
|
|
81
|
-
// Always observe `defer-hydration`, so Gyral can defer server-rendered children itself
|
|
82
|
-
// when Lit's hydrate support isn't installed (gyral-czi.41, ADR 0012).
|
|
83
|
-
static get observedAttributes() {
|
|
84
|
-
const base = super.observedAttributes;
|
|
85
|
-
return base.includes(DEFER_HYDRATION) ? base : [...base, DEFER_HYDRATION];
|
|
86
|
-
}
|
|
87
|
-
/** Reads, subscriptions and writes for spec.stores (ADR 0013). */
|
|
88
|
-
#binding;
|
|
89
|
-
#model;
|
|
90
|
-
/** Props as of the last init or PropsChanged; the `prev` of the next PropsChanged. */
|
|
91
|
-
#seenProps;
|
|
92
|
-
#listening;
|
|
93
|
-
#interpreter;
|
|
94
|
-
#pending;
|
|
95
|
-
/** init's commands on the hydration path; started in firstUpdated (ADR 0012). */
|
|
96
|
-
#afterHydration;
|
|
97
|
-
/** Resumed from server markup; reported by the Hydrated message. */
|
|
98
|
-
#serverRendered;
|
|
99
|
-
/** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */
|
|
100
|
-
#ssrShadow;
|
|
101
|
-
/** The latest view-transition update, awaited by updateComplete. */
|
|
102
|
-
#transition;
|
|
103
|
-
/** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */
|
|
104
|
-
#syncStates;
|
|
105
|
-
get state() {
|
|
106
|
-
if (this.#model === undefined) {
|
|
107
|
-
const missing = missingRequired(this, propTable);
|
|
108
|
-
if (missing.length > 0) {
|
|
109
|
-
console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);
|
|
110
|
-
}
|
|
111
|
-
this.#seenProps = this.#props();
|
|
112
|
-
this.#apply(runInit(spec, this.#seenProps));
|
|
113
|
-
for (const msg of this.initialMessages)
|
|
114
|
-
this.#dispatch(msg, false);
|
|
115
|
-
}
|
|
116
|
-
return this.#model.value;
|
|
117
|
-
}
|
|
118
|
-
send(msg) {
|
|
119
|
-
this.#dispatch(msg);
|
|
120
|
-
}
|
|
121
|
-
#dispatch(msg, render = true) {
|
|
122
|
-
const reducer = reducers[msg._tag];
|
|
123
|
-
if (reducer === undefined) {
|
|
124
|
-
// Framework messages have optional reducers; props and stores stay readable as context.
|
|
125
|
-
if (msg._tag !== 'PropsChanged' && msg._tag !== 'StoreChanged') {
|
|
126
|
-
console.warn(`<${tag}> has no update for message "${msg._tag}".`);
|
|
127
|
-
}
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
const prev = this.state;
|
|
131
|
-
this.#apply(reducer(prev, msg, this.#ctx()));
|
|
132
|
-
if (DEVTOOLS_ENABLED)
|
|
133
|
-
devUpdate(this, tag, msg, prev, this.state);
|
|
134
|
-
if (!render)
|
|
135
|
-
return;
|
|
136
|
-
if (spec.viewTransition?.(prev, this.state, msg) === true) {
|
|
137
|
-
// The DOM change happens inside the transition callback (ADR 0001 addendum);
|
|
138
|
-
// updateComplete waits for it, so tests and callers see the new DOM.
|
|
139
|
-
this.#transition = withViewTransition(async () => {
|
|
140
|
-
this.requestUpdate();
|
|
141
|
-
await super.getUpdateComplete();
|
|
142
|
-
}).catch((error) => {
|
|
143
|
-
console.error(`<${tag}> view transition update failed`, error);
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this.requestUpdate();
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
async getUpdateComplete() {
|
|
151
|
-
await this.#transition;
|
|
152
|
-
return super.getUpdateComplete();
|
|
153
|
-
}
|
|
154
|
-
connectedCallback() {
|
|
155
|
-
this.#resumeFromSeed();
|
|
156
|
-
// A component server-rendered inside another's view waits (`defer-hydration`) for its
|
|
157
|
-
// parent to hydrate first. Lit's hydrate support, when installed, defers LitElement
|
|
158
|
-
// itself; otherwise Gyral holds back Lit's connect until the attribute goes.
|
|
159
|
-
const waiting = this.hasAttribute(DEFER_HYDRATION);
|
|
160
|
-
if (!waiting || litDefers())
|
|
161
|
-
super.connectedCallback();
|
|
162
|
-
if (waiting) {
|
|
163
|
-
scheduleIsland(this); // lazy islands release themselves (gyral-4k7.4)
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
this.#connect();
|
|
167
|
-
}
|
|
168
|
-
attributeChangedCallback(name, old, value) {
|
|
169
|
-
super.attributeChangedCallback(name, old, value);
|
|
170
|
-
if (name !== DEFER_HYDRATION || value !== null || !this.isConnected)
|
|
171
|
-
return;
|
|
172
|
-
if (!litDefers())
|
|
173
|
-
super.connectedCallback(); // Lit's support would have connected it
|
|
174
|
-
this.#connect();
|
|
175
|
-
}
|
|
176
|
-
#connect() {
|
|
177
|
-
// Re-resolve on every connect: the nearest <gyral-stores> may differ after a move.
|
|
178
|
-
if (this.#binding.connect())
|
|
179
|
-
this.requestUpdate();
|
|
180
|
-
this.#interpreter = makeInterpreter(this.#resolve, (msg) => {
|
|
181
|
-
this.#dispatch(msg);
|
|
182
|
-
}, DEVTOOLS_ENABLED ? devCommands(() => devOwner(this, tag)) : undefined);
|
|
183
|
-
if (DEVTOOLS_ENABLED)
|
|
184
|
-
devConnect(this, tag, true);
|
|
185
|
-
const pending = this.#pending;
|
|
186
|
-
this.#pending = [];
|
|
187
|
-
for (const cmd of pending)
|
|
188
|
-
this.#interpreter.run(cmd);
|
|
189
|
-
if (this.#listening)
|
|
190
|
-
return;
|
|
191
|
-
listenForIntents(this.renderRoot, spec.events ?? [], this.#onEvent);
|
|
192
|
-
this.#listening = true;
|
|
193
|
-
}
|
|
194
|
-
disconnectedCallback() {
|
|
195
|
-
super.disconnectedCallback();
|
|
196
|
-
this.#binding.disconnect();
|
|
197
|
-
this.#interpreter?.dispose();
|
|
198
|
-
this.#interpreter = undefined;
|
|
199
|
-
if (DEVTOOLS_ENABLED)
|
|
200
|
-
devConnect(this, tag, false);
|
|
201
|
-
}
|
|
202
|
-
willUpdate(changed) {
|
|
203
|
-
super.willUpdate(changed);
|
|
204
|
-
if (onServer) {
|
|
205
|
-
// Server renders run constructor, willUpdate and render only (ADR 0012).
|
|
206
|
-
// init is pure, so the client can recompute an unchanged state from the props.
|
|
207
|
-
const [initial] = splitNext(runInit(spec, this.#props()));
|
|
208
|
-
writeSeed(this, this.state, readRawProps(this, propTable), propTable, { value: initial });
|
|
209
|
-
if (isLight(spec))
|
|
210
|
-
markLightHost(this);
|
|
211
|
-
markIsland(this, spec.hydrate);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const prev = this.#seenProps;
|
|
215
|
-
if (prev === undefined)
|
|
216
|
-
return; // first render: init() sees the props
|
|
217
|
-
const props = this.#props();
|
|
218
|
-
if (sameProps(propNames, props, prev))
|
|
219
|
-
return;
|
|
220
|
-
this.#seenProps = props;
|
|
221
|
-
// Inside the update cycle, so the new state renders in this same pass.
|
|
222
|
-
this.#dispatch({ _tag: 'PropsChanged', props, prev }, false);
|
|
223
|
-
}
|
|
224
|
-
// Light-DOM mode (ADR 0014): render into the element itself. A server-rendered shadow root
|
|
225
|
-
// (Declarative Shadow DOM) is reused as is and hydrated in update() (gyral-czi.41): this
|
|
226
|
-
// bypasses Lit's hydrate-support patch on purpose, so hydration is correct whether or not
|
|
227
|
-
// that patch was installed before Lit evaluated (bundlers can reorder it; ADR 0012).
|
|
228
|
-
createRenderRoot() {
|
|
229
|
-
if (isLight(spec))
|
|
230
|
-
return this;
|
|
231
|
-
if (!onServer && this.shadowRoot !== null) {
|
|
232
|
-
this.#ssrShadow = true;
|
|
233
|
-
return this.shadowRoot;
|
|
234
|
-
}
|
|
235
|
-
return super.createRenderRoot();
|
|
236
|
-
}
|
|
237
|
-
update(changed) {
|
|
238
|
-
if (this.#ssrShadow && !this.hasUpdated) {
|
|
239
|
-
const styles = this.constructor.elementStyles;
|
|
240
|
-
hydrateShadow(this.renderRoot, this.render(), this.renderOptions, styles);
|
|
241
|
-
}
|
|
242
|
-
if (isLight(spec) && !this.hasUpdated && this.#serverRendered) {
|
|
243
|
-
hydrateLight(this, this.render(), this.renderOptions); // ADR 0014
|
|
244
|
-
}
|
|
245
|
-
super.update(changed);
|
|
246
|
-
}
|
|
247
|
-
render() {
|
|
248
|
-
return spec.view(this.state, intentNames, this.#ctx());
|
|
249
|
-
}
|
|
250
|
-
updated(changed) {
|
|
251
|
-
super.updated(changed);
|
|
252
|
-
if (spec.states !== undefined)
|
|
253
|
-
this.#syncStates?.(spec.states(this.state));
|
|
254
|
-
}
|
|
255
|
-
#apply(next) {
|
|
256
|
-
const [state, commands] = splitNext(next);
|
|
257
|
-
this.#model = { value: state };
|
|
258
|
-
if (onServer)
|
|
259
|
-
return; // commands never run on the server; the client's init starts them
|
|
260
|
-
for (const cmd of commands) {
|
|
261
|
-
if (cmd.driver === EMIT)
|
|
262
|
-
dispatchOutput(this, cmd.input);
|
|
263
|
-
else if (cmd.driver === STORE_SEND)
|
|
264
|
-
this.#binding.send(cmd.input);
|
|
265
|
-
else if (cmd.driver === FOCUS)
|
|
266
|
-
focusAfterUpdate(this, tag, cmd.input);
|
|
267
|
-
else if (this.#interpreter === undefined)
|
|
268
|
-
this.#pending.push(cmd);
|
|
269
|
-
else
|
|
270
|
-
this.#interpreter.run(cmd);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Hydration (ADR 0012): use the server's state and restore props that only travelled in the
|
|
275
|
-
* seed. init(props) runs again for its commands only, and they start after the hydrating
|
|
276
|
-
* render: a driver that answers synchronously must not change state before hydration.
|
|
277
|
-
*/
|
|
278
|
-
#resumeFromSeed() {
|
|
279
|
-
if (this.#model !== undefined)
|
|
280
|
-
return;
|
|
281
|
-
const seed = takeSeed(this);
|
|
282
|
-
if (seed === undefined)
|
|
283
|
-
return;
|
|
284
|
-
restoreProps(this, propNames, seed.props);
|
|
285
|
-
this.#seenProps = this.#props();
|
|
286
|
-
const [initial, commands] = splitNext(runInit(spec, this.#seenProps));
|
|
287
|
-
// Sound: the seed is this component's own state, serialized by writeSeed() on the server;
|
|
288
|
-
// when absent, the server's state was exactly init(props) (seed deduplication).
|
|
289
|
-
this.#model = { value: 'state' in seed ? seed.state : initial };
|
|
290
|
-
this.#afterHydration = commands;
|
|
291
|
-
this.#serverRendered = true;
|
|
292
|
-
}
|
|
293
|
-
firstUpdated(changed) {
|
|
294
|
-
super.firstUpdated(changed);
|
|
295
|
-
if (this.#serverRendered)
|
|
296
|
-
fillEmptyTextParts(this.renderRoot); // gyral-4k7.12
|
|
297
|
-
if (DEVTOOLS_ENABLED)
|
|
298
|
-
devHydrated(this, tag, this.#serverRendered);
|
|
299
|
-
const commands = this.#afterHydration;
|
|
300
|
-
const wantsHydrated = reducers['Hydrated'] !== undefined;
|
|
301
|
-
if (commands.length === 0 && !wantsHydrated)
|
|
302
|
-
return;
|
|
303
|
-
this.#afterHydration = [];
|
|
304
|
-
// After the first (possibly hydrating) update has fully completed, so whatever these
|
|
305
|
-
// change starts a fresh update instead of diverging from the server markup.
|
|
306
|
-
void this.updateComplete.then(() => {
|
|
307
|
-
if (wantsHydrated) {
|
|
308
|
-
this.#dispatch({ _tag: 'Hydrated', serverRendered: this.#serverRendered });
|
|
309
|
-
}
|
|
310
|
-
if (commands.length > 0)
|
|
311
|
-
this.#apply([this.state, commands]);
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
// el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).
|
|
315
|
-
#resolve;
|
|
316
|
-
#onEvent;
|
|
317
|
-
#deliver;
|
|
318
|
-
#ctx() {
|
|
319
|
-
return { props: this.#props(), read: (store) => this.#binding.read(store) };
|
|
320
|
-
}
|
|
321
|
-
#storeChanged(store, state, prev) {
|
|
322
|
-
if (reducers['StoreChanged'] === undefined)
|
|
323
|
-
this.requestUpdate();
|
|
324
|
-
else
|
|
325
|
-
this.#dispatch({ _tag: 'StoreChanged', store: store.name, state, prev });
|
|
326
|
-
}
|
|
327
|
-
#props() {
|
|
328
|
-
// Sound: propNames are exactly the declared props, P's keys.
|
|
329
|
-
return readProps(this, propTable);
|
|
33
|
+
const existing = customElements.get(tag);
|
|
34
|
+
if (existing !== undefined) {
|
|
35
|
+
if (DEV && existing.spec !== spec) {
|
|
36
|
+
console.warn(`<${tag}> is already defined with a different spec; keeping the first.`);
|
|
330
37
|
}
|
|
38
|
+
return existing;
|
|
331
39
|
}
|
|
40
|
+
const Element = elementClass(tag, spec);
|
|
332
41
|
markGyralHost(Element);
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
// Sound: the declared props are reactive properties on every instance.
|
|
42
|
+
customElements.define(tag, Element);
|
|
43
|
+
// Sound: every declared prop is an accessor on the prototype.
|
|
336
44
|
return Element;
|
|
337
45
|
}
|
|
338
46
|
//# sourceMappingURL=define.js.map
|
package/dist/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServer, LitElement } from 'lit';\nimport { providedDriver } from './drivers-scope.js';\nimport {\n DEVTOOLS_ENABLED,\n devCommands,\n devConnect,\n devHydrated,\n devOwner,\n devUpdate,\n} from '#devtools';\nimport {\n splitNext,\n type AnyDriver,\n type Command,\n type DriverOverrides,\n type Next,\n} from './command.js';\nimport { dispatchOutput, EMIT } from './children.js';\nimport { FOCUS, focusAfterUpdate, type FocusInput } from './focus.js';\nimport type { GyralElement, GyralElementClass } from './element-types.js';\nimport { fillEmptyTextParts, takeSeed, writeSeed } from './hydration.js';\nimport { markIsland, scheduleIsland } from './islands.js';\nimport { runInit } from './init.js';\nimport { handleIntent, intentNames, listenForIntents, markGyralHost } from './intent.js';\nimport {\n componentStyles,\n hydrateLight,\n hydrateShadow,\n isLight,\n markLightHost,\n} from './light-dom.js';\nimport { makeInterpreter, type Interpreter } from './internal/interpreter.js';\nimport {\n missingRequired,\n readProps,\n readRawProps,\n restoreProps,\n sameProps,\n shadowedBuiltins,\n type PropTable,\n} from './props.js';\nimport { attachStates, type StateSync } from './states.js';\nimport { STORE_SEND, type AnyStore, type StoreOverrides, type StoreSendInput } from './store.js';\nimport { StoreBinding } from './store-binding.js';\nimport { withViewTransition } from './transitions.js';\nimport type {\n ComponentSpec,\n Ctx,\n IntentNames,\n IntentParser,\n IntentRejected,\n Tagged,\n} from './types.js';\n\nexport type { GyralElement, GyralElementClass } from './element-types.js';\n\n// Lit types `isServer` per build condition; widen it so both branches type-check (ADR 0012).\nconst onServer: boolean = isServer;\n\nconst DEFER_HYDRATION = 'defer-hydration';\n\n/**\n * Has Lit's hydrate support patched LitElement? It then defers `defer-hydration` elements\n * itself. A bundler can evaluate Lit before `@gyral/ssr/hydrate`, so it may not have\n * (gyral-czi.41); the patch adds an own static `observedAttributes` to LitElement.\n */\nconst litDefers = (): boolean =>\n Object.prototype.hasOwnProperty.call(LitElement, 'observedAttributes');\n\n/**\n * Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.\n * See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md\n * 0008-forms.md and 0012-ssr.md.\n */\nexport function define<S, M extends Tagged, P extends object = object, O extends Tagged = never>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): GyralElementClass<S, M, P, O> {\n const propTable = (spec.props ?? {}) as PropTable;\n const propNames = Object.keys(propTable);\n const shadowed = onServer ? [] : shadowedBuiltins(propNames);\n if (shadowed.length > 0) {\n console.warn(\n `<${tag}> declares prop(s) that shadow built-in element properties: ` +\n `${shadowed.join(', ')}. Setting them changes platform behaviour ` +\n `(a prop named \"hidden\" hides the element). Rename them.`,\n );\n }\n const parsers = spec.intent as Readonly<Record<string, IntentParser<M> | undefined>>;\n // Sound: #dispatch() only calls the reducer whose key equals msg._tag.\n const reducers = spec.update as unknown as Readonly<\n Record<string, ((state: S, msg: Tagged, ctx: Ctx<P>) => Next<S, M>) | undefined>\n >;\n\n class Element extends LitElement implements GyralElement<S, M> {\n static override properties = spec.props ?? {};\n static override styles = componentStyles(spec, tag);\n static readonly spec = spec;\n static readonly tagName = tag;\n\n // Always observe `defer-hydration`, so Gyral can defer server-rendered children itself\n // when Lit's hydrate support isn't installed (gyral-czi.41, ADR 0012).\n static override get observedAttributes(): string[] {\n const base = super.observedAttributes;\n return base.includes(DEFER_HYDRATION) ? base : [...base, DEFER_HYDRATION];\n }\n\n drivers: DriverOverrides = {};\n stores: StoreOverrides = {};\n initialMessages: readonly Tagged[] = [];\n\n /** Reads, subscriptions and writes for spec.stores (ADR 0013). */\n #binding = new StoreBinding(\n this,\n tag,\n spec.stores ?? [],\n () => this.stores,\n (store, state, prev) => {\n this.#storeChanged(store, state, prev);\n },\n );\n #model: { value: S } | undefined;\n /** Props as of the last init or PropsChanged; the `prev` of the next PropsChanged. */\n #seenProps: P | undefined;\n #listening = false;\n #interpreter: Interpreter<M | IntentRejected> | undefined;\n #pending: Command<M | IntentRejected>[] = [];\n /** init's commands on the hydration path; started in firstUpdated (ADR 0012). */\n #afterHydration: readonly Command<M | IntentRejected>[] = [];\n /** Resumed from server markup; reported by the Hydrated message. */\n #serverRendered = false;\n /** The renderRoot is a server-rendered (declarative) shadow root to hydrate in place. */\n #ssrShadow = false;\n /** The latest view-transition update, awaited by updateComplete. */\n #transition: Promise<void> | undefined;\n /** Mirrors spec.states onto CSS custom states; only attached when the spec asks. */\n #syncStates: StateSync | undefined =\n spec.states === undefined || onServer ? undefined : attachStates(this);\n\n get state(): S {\n if (this.#model === undefined) {\n const missing = missingRequired(this, propTable);\n if (missing.length > 0) {\n console.warn(`<${tag}> is missing required prop(s): ${missing.join(', ')}.`);\n }\n this.#seenProps = this.#props();\n this.#apply(runInit(spec, this.#seenProps));\n for (const msg of this.initialMessages) this.#dispatch(msg, false);\n }\n return (this.#model as { value: S }).value;\n }\n\n send(msg: M): void {\n this.#dispatch(msg);\n }\n\n #dispatch(msg: Tagged, render = true): void {\n const reducer = reducers[msg._tag];\n if (reducer === undefined) {\n // Framework messages have optional reducers; props and stores stay readable as context.\n if (msg._tag !== 'PropsChanged' && msg._tag !== 'StoreChanged') {\n console.warn(`<${tag}> has no update for message \"${msg._tag}\".`);\n }\n return;\n }\n const prev = this.state;\n this.#apply(reducer(prev, msg, this.#ctx()));\n if (DEVTOOLS_ENABLED) devUpdate(this, tag, msg, prev, this.state);\n if (!render) return;\n if (spec.viewTransition?.(prev, this.state, msg) === true) {\n // The DOM change happens inside the transition callback (ADR 0001 addendum);\n // updateComplete waits for it, so tests and callers see the new DOM.\n this.#transition = withViewTransition(async () => {\n this.requestUpdate();\n await super.getUpdateComplete();\n }).catch((error: unknown) => {\n console.error(`<${tag}> view transition update failed`, error);\n });\n } else {\n this.requestUpdate();\n }\n }\n\n protected override async getUpdateComplete(): Promise<boolean> {\n await this.#transition;\n return super.getUpdateComplete();\n }\n\n override connectedCallback(): void {\n this.#resumeFromSeed();\n // A component server-rendered inside another's view waits (`defer-hydration`) for its\n // parent to hydrate first. Lit's hydrate support, when installed, defers LitElement\n // itself; otherwise Gyral holds back Lit's connect until the attribute goes.\n const waiting = this.hasAttribute(DEFER_HYDRATION);\n if (!waiting || litDefers()) super.connectedCallback();\n if (waiting) {\n scheduleIsland(this); // lazy islands release themselves (gyral-4k7.4)\n return;\n }\n this.#connect();\n }\n\n override attributeChangedCallback(name: string, old: string | null, value: string | null) {\n super.attributeChangedCallback(name, old, value);\n if (name !== DEFER_HYDRATION || value !== null || !this.isConnected) return;\n if (!litDefers()) super.connectedCallback(); // Lit's support would have connected it\n this.#connect();\n }\n\n #connect(): void {\n // Re-resolve on every connect: the nearest <gyral-stores> may differ after a move.\n if (this.#binding.connect()) this.requestUpdate();\n this.#interpreter = makeInterpreter<M | IntentRejected>(\n this.#resolve,\n (msg) => {\n this.#dispatch(msg);\n },\n DEVTOOLS_ENABLED ? devCommands(() => devOwner(this, tag)) : undefined,\n );\n if (DEVTOOLS_ENABLED) devConnect(this, tag, true);\n const pending = this.#pending;\n this.#pending = [];\n for (const cmd of pending) this.#interpreter.run(cmd);\n if (this.#listening) return;\n listenForIntents(this.renderRoot, spec.events ?? [], this.#onEvent);\n this.#listening = true;\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#binding.disconnect();\n this.#interpreter?.dispose();\n this.#interpreter = undefined;\n if (DEVTOOLS_ENABLED) devConnect(this, tag, false);\n }\n\n protected override willUpdate(changed: Map<PropertyKey, unknown>): void {\n super.willUpdate(changed);\n if (onServer) {\n // Server renders run constructor, willUpdate and render only (ADR 0012).\n // init is pure, so the client can recompute an unchanged state from the props.\n const [initial] = splitNext(runInit(spec, this.#props()));\n writeSeed(this, this.state, readRawProps(this, propTable), propTable, { value: initial });\n if (isLight(spec)) markLightHost(this);\n markIsland(this, spec.hydrate);\n return;\n }\n const prev = this.#seenProps;\n if (prev === undefined) return; // first render: init() sees the props\n const props = this.#props();\n if (sameProps(propNames, props, prev)) return;\n this.#seenProps = props;\n // Inside the update cycle, so the new state renders in this same pass.\n this.#dispatch({ _tag: 'PropsChanged', props, prev } as Tagged, false);\n }\n\n // Light-DOM mode (ADR 0014): render into the element itself. A server-rendered shadow root\n // (Declarative Shadow DOM) is reused as is and hydrated in update() (gyral-czi.41): this\n // bypasses Lit's hydrate-support patch on purpose, so hydration is correct whether or not\n // that patch was installed before Lit evaluated (bundlers can reorder it; ADR 0012).\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n if (isLight(spec)) return this;\n if (!onServer && this.shadowRoot !== null) {\n this.#ssrShadow = true;\n return this.shadowRoot;\n }\n return super.createRenderRoot();\n }\n\n protected override update(changed: Map<PropertyKey, unknown>): void {\n if (this.#ssrShadow && !this.hasUpdated) {\n const styles = (this.constructor as typeof LitElement).elementStyles;\n hydrateShadow(this.renderRoot as ShadowRoot, this.render(), this.renderOptions, styles);\n }\n if (isLight(spec) && !this.hasUpdated && this.#serverRendered) {\n hydrateLight(this, this.render(), this.renderOptions); // ADR 0014\n }\n super.update(changed);\n }\n\n protected override render(): unknown {\n return spec.view(this.state, intentNames as IntentNames<M>, this.#ctx());\n }\n\n protected override updated(changed: Map<PropertyKey, unknown>): void {\n super.updated(changed);\n if (spec.states !== undefined) this.#syncStates?.(spec.states(this.state));\n }\n\n #apply(next: Next<S, M>): void {\n const [state, commands] = splitNext(next);\n this.#model = { value: state };\n if (onServer) return; // commands never run on the server; the client's init starts them\n for (const cmd of commands) {\n if (cmd.driver === EMIT) dispatchOutput(this, cmd.input);\n else if (cmd.driver === STORE_SEND) this.#binding.send(cmd.input as StoreSendInput);\n else if (cmd.driver === FOCUS) focusAfterUpdate(this, tag, cmd.input as FocusInput);\n else if (this.#interpreter === undefined) this.#pending.push(cmd);\n else this.#interpreter.run(cmd);\n }\n }\n\n /**\n * Hydration (ADR 0012): use the server's state and restore props that only travelled in the\n * seed. init(props) runs again for its commands only, and they start after the hydrating\n * render: a driver that answers synchronously must not change state before hydration.\n */\n #resumeFromSeed(): void {\n if (this.#model !== undefined) return;\n const seed = takeSeed(this);\n if (seed === undefined) return;\n restoreProps(this, propNames, seed.props);\n this.#seenProps = this.#props();\n const [initial, commands] = splitNext(runInit(spec, this.#seenProps));\n // Sound: the seed is this component's own state, serialized by writeSeed() on the server;\n // when absent, the server's state was exactly init(props) (seed deduplication).\n this.#model = { value: 'state' in seed ? (seed.state as S) : initial };\n this.#afterHydration = commands;\n this.#serverRendered = true;\n }\n\n protected override firstUpdated(changed: Map<PropertyKey, unknown>): void {\n super.firstUpdated(changed);\n if (this.#serverRendered) fillEmptyTextParts(this.renderRoot); // gyral-4k7.12\n if (DEVTOOLS_ENABLED) devHydrated(this, tag, this.#serverRendered);\n const commands = this.#afterHydration;\n const wantsHydrated = reducers['Hydrated'] !== undefined;\n if (commands.length === 0 && !wantsHydrated) return;\n this.#afterHydration = [];\n // After the first (possibly hydrating) update has fully completed, so whatever these\n // change starts a fresh update instead of diverging from the server markup.\n void this.updateComplete.then(() => {\n if (wantsHydrated) {\n this.#dispatch({ _tag: 'Hydrated', serverRendered: this.#serverRendered } as Tagged);\n }\n if (commands.length > 0) this.#apply([this.state, commands]);\n });\n }\n\n // el.drivers → nearest provider → spec.drivers → the command's own (gyral-czi.35).\n #resolve = (driver: AnyDriver): AnyDriver =>\n this.drivers[driver.name] ??\n providedDriver(this, driver.name) ??\n spec.drivers?.[driver.name] ??\n driver;\n\n #onEvent = (event: Event): void => {\n handleIntent(event, this.renderRoot, parsers, tag, this.#deliver);\n };\n\n #deliver = (msg: Tagged | undefined): void => {\n if (msg !== undefined && this.isConnected) this.#dispatch(msg);\n };\n\n #ctx(): Ctx<P> {\n return { props: this.#props(), read: (store) => this.#binding.read(store) };\n }\n\n #storeChanged(store: AnyStore, state: unknown, prev: unknown): void {\n if (reducers['StoreChanged'] === undefined) this.requestUpdate();\n else this.#dispatch({ _tag: 'StoreChanged', store: store.name, state, prev } as Tagged);\n }\n\n #props(): P {\n // Sound: propNames are exactly the declared props, P's keys.\n return readProps(this, propTable) as P;\n }\n }\n\n markGyralHost(Element);\n if (customElements.get(tag) === undefined) customElements.define(tag, Element);\n // Sound: the declared props are reactive properties on every instance.\n return Element as unknown as GyralElementClass<S, M, P, O>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAUtC,SAAS,SAAS,CAAC,GAAW,EAAE,IAAe;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC5C,kFAAkF;IAClF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChE,IAAI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,mEAAmE,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CACpB,GAAW,EACX,IAA4B;IAE5B,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,IAAI,OAAO,WAAW,KAAK,WAAW,EAAE,CAAC;QACvC,0FAA0F;QAC1F,mFAAmF;QACnF,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACtB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAC/B,SAAS,WAAW;YAClB,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,6DAA6D,CAAC,CAAC;QACxF,CAAC,EACD,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CACvB,CAAC;QACF,iFAAiF;QACjF,OAAO,WAAuD,CAAC;IACjE,CAAC;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,IAAI,GAAG,IAAK,QAAwC,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,gEAAgE,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,QAAoD,CAAC;IAC9D,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxC,aAAa,CAAC,OAAO,CAAC,CAAC;IACvB,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,8DAA8D;IAC9D,OAAO,OAAmD,CAAC;AAC7D,CAAC","sourcesContent":["// `define(tag, spec)` (docs/design-docs/view/05-element.md): compiles a Model-View-Intent spec\n// into a custom element and registers it. Outside the browser it records the spec in the\n// server registry instead (view/06-server.md) and returns a placeholder class.\nimport type { GyralElementClass } from './element-types.js';\nimport { elementClass } from './element.js';\nimport { markGyralHost } from './intent.js';\nimport { isLight } from './light-dom.js';\nimport { features } from './features.js';\nimport { recordSpec } from './server-specs.js';\nimport type { ComponentSpec, Tagged } from './types.js';\nimport { DEV } from './view/index.js';\n\nexport type { GyralElement, GyralElementClass } from './element-types.js';\n\ninterface SpecShape {\n readonly props?: object;\n readonly shadow?: boolean;\n readonly styles?: unknown;\n}\n\nfunction checkSpec(tag: string, spec: SpecShape): void {\n const names = Object.keys(spec.props ?? {});\n // The prop builders registered the prop feature (features.ts) if there are props.\n if (names.length > 0) features.props?.checkShadowed(tag, names);\n if (DEV && isLight(spec) && spec.styles !== undefined) {\n console.warn(`<${tag}> has shadow: false, so its styles are ignored; use document CSS.`);\n }\n}\n\n/**\n * Compiles a Model-View-Intent spec into a custom element and registers it under `tag`.\n * See docs/design-docs/0001-mvi-parsed-intent.md, 0006-effects-and-drivers.md, 0007-props.md,\n * 0008-forms.md and view/05-element.md.\n */\nexport function define<S, M extends Tagged, P extends object = object, O extends Tagged = never>(\n tag: string,\n spec: ComponentSpec<S, M, P>,\n): GyralElementClass<S, M, P, O> {\n checkSpec(tag, spec);\n if (typeof HTMLElement === 'undefined') {\n // No DOM (Node, Workers): the server renderer renders the spec itself (Phase 4). Only the\n // spec is recorded here, so the server registry code never reaches client bundles.\n recordSpec(tag, spec);\n const Placeholder = Object.assign(\n function Placeholder(): never {\n throw new Error(`<${tag}> is a browser element (render it with @gyral/core/server).`);\n },\n { spec, tagName: tag },\n );\n // Sound enough: outside the browser the class only carries `spec` and `tagName`.\n return Placeholder as unknown as GyralElementClass<S, M, P, O>;\n }\n const existing = customElements.get(tag);\n if (existing !== undefined) {\n if (DEV && (existing as { readonly spec?: unknown }).spec !== spec) {\n console.warn(`<${tag}> is already defined with a different spec; keeping the first.`);\n }\n return existing as unknown as GyralElementClass<S, M, P, O>;\n }\n const Element = elementClass(tag, spec);\n markGyralHost(Element);\n customElements.define(tag, Element);\n // Sound: every declared prop is an accessor on the prototype.\n return Element as unknown as GyralElementClass<S, M, P, O>;\n}\n"]}
|
|
@@ -35,6 +35,11 @@ export type DevEvent = {
|
|
|
35
35
|
readonly kind: 'hydrated';
|
|
36
36
|
readonly component: DevComponentRef;
|
|
37
37
|
readonly serverRendered: boolean;
|
|
38
|
+
} | {
|
|
39
|
+
/** The server DOM didn't match the first render (view/07-hydration.md "Mismatches"). */
|
|
40
|
+
readonly kind: 'mismatch';
|
|
41
|
+
readonly component: DevComponentRef;
|
|
42
|
+
readonly message: string;
|
|
38
43
|
} | ({
|
|
39
44
|
readonly kind: 'command';
|
|
40
45
|
readonly owner: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devtools-events.js","sourceRoot":"","sources":["../src/devtools-events.ts"],"names":[],"mappings":"AAKA,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,oBAAoB,CAAC","sourcesContent":["// The devtools event stream (ADR 0017). Types and the global hook name only: the emitting code\n// lives in devtools.ts (development builds) and devtools-off.ts (production builds).\nimport type { Concurrency } from './command.js';\nimport type { Tagged } from './types.js';\n\n/** Where a listener installs itself: `globalThis.__GYRAL_DEVTOOLS__ = { emit }`. */\nexport const DEVTOOLS_GLOBAL = '__GYRAL_DEVTOOLS__';\n\n/** A live component, identified for the timeline. `element` gives the panel its state. */\nexport interface DevComponentRef {\n readonly tag: string;\n readonly id: number;\n readonly element: Element;\n}\n\nexport type CommandPhase = 'issued' | 'dropped' | 'settled' | 'failed' | 'interrupted';\n\n/** What the interpreter reports about one command (ADR 0006 lanes and policies). */\nexport interface CommandTraceEvent {\n readonly phase: CommandPhase;\n readonly driver: string;\n readonly lane: string;\n readonly policy: Concurrency;\n readonly input: unknown;\n /** Driver output (`settled`) or error (`failed`). */\n readonly result?: unknown;\n}\n\nexport type CommandTrace = (event: CommandTraceEvent) => void;\n\nexport type DevEvent = { readonly at: number } & (\n | { readonly kind: 'connect' | 'disconnect'; readonly component: DevComponentRef }\n | {\n readonly kind: 'update';\n readonly component: DevComponentRef;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n | {\n readonly kind: 'hydrated';\n readonly component: DevComponentRef;\n readonly serverRendered: boolean;\n }\n | ({ readonly kind: 'command'; readonly owner: string } & CommandTraceEvent)\n | {\n readonly kind: 'store';\n readonly store: string;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n);\n\n/** Installed by a devtools panel (or a test) on `globalThis[DEVTOOLS_GLOBAL]`. */\nexport interface DevtoolsHook {\n emit(event: DevEvent): void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"devtools-events.js","sourceRoot":"","sources":["../src/devtools-events.ts"],"names":[],"mappings":"AAKA,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,oBAAoB,CAAC","sourcesContent":["// The devtools event stream (ADR 0017). Types and the global hook name only: the emitting code\n// lives in devtools.ts (development builds) and devtools-off.ts (production builds).\nimport type { Concurrency } from './command.js';\nimport type { Tagged } from './types.js';\n\n/** Where a listener installs itself: `globalThis.__GYRAL_DEVTOOLS__ = { emit }`. */\nexport const DEVTOOLS_GLOBAL = '__GYRAL_DEVTOOLS__';\n\n/** A live component, identified for the timeline. `element` gives the panel its state. */\nexport interface DevComponentRef {\n readonly tag: string;\n readonly id: number;\n readonly element: Element;\n}\n\nexport type CommandPhase = 'issued' | 'dropped' | 'settled' | 'failed' | 'interrupted';\n\n/** What the interpreter reports about one command (ADR 0006 lanes and policies). */\nexport interface CommandTraceEvent {\n readonly phase: CommandPhase;\n readonly driver: string;\n readonly lane: string;\n readonly policy: Concurrency;\n readonly input: unknown;\n /** Driver output (`settled`) or error (`failed`). */\n readonly result?: unknown;\n}\n\nexport type CommandTrace = (event: CommandTraceEvent) => void;\n\nexport type DevEvent = { readonly at: number } & (\n | { readonly kind: 'connect' | 'disconnect'; readonly component: DevComponentRef }\n | {\n readonly kind: 'update';\n readonly component: DevComponentRef;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n | {\n readonly kind: 'hydrated';\n readonly component: DevComponentRef;\n readonly serverRendered: boolean;\n }\n | {\n /** The server DOM didn't match the first render (view/07-hydration.md \"Mismatches\"). */\n readonly kind: 'mismatch';\n readonly component: DevComponentRef;\n readonly message: string;\n }\n | ({ readonly kind: 'command'; readonly owner: string } & CommandTraceEvent)\n | {\n readonly kind: 'store';\n readonly store: string;\n readonly msg: Tagged;\n readonly prev: unknown;\n readonly next: unknown;\n }\n);\n\n/** Installed by a devtools panel (or a test) on `globalThis[DEVTOOLS_GLOBAL]`. */\nexport interface DevtoolsHook {\n emit(event: DevEvent): void;\n}\n"]}
|
package/dist/devtools-off.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare const DEVTOOLS_ENABLED: boolean;
|
|
|
3
3
|
export declare const devConnect: typeof Dev.devConnect;
|
|
4
4
|
export declare const devUpdate: typeof Dev.devUpdate;
|
|
5
5
|
export declare const devHydrated: typeof Dev.devHydrated;
|
|
6
|
+
export declare const devMismatch: typeof Dev.devMismatch;
|
|
6
7
|
export declare const devStore: typeof Dev.devStore;
|
|
7
8
|
export declare const devCommands: typeof Dev.devCommands;
|
|
8
9
|
export declare const devOwner: typeof Dev.devOwner;
|
package/dist/devtools-off.js
CHANGED
|
@@ -3,6 +3,7 @@ const noop = () => undefined;
|
|
|
3
3
|
export const devConnect = noop;
|
|
4
4
|
export const devUpdate = noop;
|
|
5
5
|
export const devHydrated = noop;
|
|
6
|
+
export const devMismatch = noop;
|
|
6
7
|
export const devStore = noop;
|
|
7
8
|
export const devCommands = () => noop;
|
|
8
9
|
export const devOwner = () => '';
|