@velarscript/web 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +89 -0
  3. package/dist/analyzer.d.ts +302 -0
  4. package/dist/analyzer.d.ts.map +1 -0
  5. package/dist/analyzer.js +2931 -0
  6. package/dist/analyzer.js.map +1 -0
  7. package/dist/ast.d.ts +220 -0
  8. package/dist/ast.d.ts.map +1 -0
  9. package/dist/ast.js +102 -0
  10. package/dist/ast.js.map +1 -0
  11. package/dist/browser-test.d.ts +29 -0
  12. package/dist/browser-test.d.ts.map +1 -0
  13. package/dist/browser-test.js +33 -0
  14. package/dist/browser-test.js.map +1 -0
  15. package/dist/compiler.d.ts +9 -0
  16. package/dist/compiler.d.ts.map +1 -0
  17. package/dist/compiler.js +715 -0
  18. package/dist/compiler.js.map +1 -0
  19. package/dist/css-tokens.d.ts +46 -0
  20. package/dist/css-tokens.d.ts.map +1 -0
  21. package/dist/css-tokens.js +363 -0
  22. package/dist/css-tokens.js.map +1 -0
  23. package/dist/editor.d.ts +3 -0
  24. package/dist/editor.d.ts.map +1 -0
  25. package/dist/editor.js +147 -0
  26. package/dist/editor.js.map +1 -0
  27. package/dist/elements.d.ts +11 -0
  28. package/dist/elements.d.ts.map +1 -0
  29. package/dist/elements.js +24 -0
  30. package/dist/elements.js.map +1 -0
  31. package/dist/emitter.d.ts +79 -0
  32. package/dist/emitter.d.ts.map +1 -0
  33. package/dist/emitter.js +2699 -0
  34. package/dist/emitter.js.map +1 -0
  35. package/dist/host.d.ts +7 -0
  36. package/dist/host.d.ts.map +1 -0
  37. package/dist/host.js +224 -0
  38. package/dist/host.js.map +1 -0
  39. package/dist/index.d.ts +11 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +23 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/inspection.d.ts +3 -0
  44. package/dist/inspection.d.ts.map +1 -0
  45. package/dist/inspection.js +82 -0
  46. package/dist/inspection.js.map +1 -0
  47. package/dist/keyframes.d.ts +16 -0
  48. package/dist/keyframes.d.ts.map +1 -0
  49. package/dist/keyframes.js +29 -0
  50. package/dist/keyframes.js.map +1 -0
  51. package/dist/lexer.d.ts +85 -0
  52. package/dist/lexer.d.ts.map +1 -0
  53. package/dist/lexer.js +422 -0
  54. package/dist/lexer.js.map +1 -0
  55. package/dist/look-static.d.ts +31 -0
  56. package/dist/look-static.d.ts.map +1 -0
  57. package/dist/look-static.js +266 -0
  58. package/dist/look-static.js.map +1 -0
  59. package/dist/look.d.ts +134 -0
  60. package/dist/look.d.ts.map +1 -0
  61. package/dist/look.js +627 -0
  62. package/dist/look.js.map +1 -0
  63. package/dist/parser.d.ts +71 -0
  64. package/dist/parser.d.ts.map +1 -0
  65. package/dist/parser.js +976 -0
  66. package/dist/parser.js.map +1 -0
  67. package/dist/project-config.d.ts +33 -0
  68. package/dist/project-config.d.ts.map +1 -0
  69. package/dist/project-config.js +199 -0
  70. package/dist/project-config.js.map +1 -0
  71. package/dist/runtime-foundation.d.ts +7 -0
  72. package/dist/runtime-foundation.d.ts.map +1 -0
  73. package/dist/runtime-foundation.js +1245 -0
  74. package/dist/runtime-foundation.js.map +1 -0
  75. package/dist/runtime.d.ts +7 -0
  76. package/dist/runtime.d.ts.map +1 -0
  77. package/dist/runtime.js +3444 -0
  78. package/dist/runtime.js.map +1 -0
  79. package/dist/semantic.d.ts +3 -0
  80. package/dist/semantic.d.ts.map +1 -0
  81. package/dist/semantic.js +150 -0
  82. package/dist/semantic.js.map +1 -0
  83. package/dist/types.d.ts +56 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +178 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/websocket-runtime.d.ts +2 -0
  88. package/dist/websocket-runtime.d.ts.map +1 -0
  89. package/dist/websocket-runtime.js +30 -0
  90. package/dist/websocket-runtime.js.map +1 -0
  91. package/dist/worker-runtime.d.ts +2 -0
  92. package/dist/worker-runtime.d.ts.map +1 -0
  93. package/dist/worker-runtime.js +72 -0
  94. package/dist/worker-runtime.js.map +1 -0
  95. package/package.json +52 -0
@@ -0,0 +1,2699 @@
1
+ import { cssPropertyName, LOOK_ARITHMETIC_HINT, LOOK_MEDIA_LENGTH_UNITS, LOOK_PROPERTIES } from "./look.js";
2
+ import { collectLookStaticValues, evaluateLookStaticExpression, isLookStaticValue, lookStaticCss } from "./look-static.js";
3
+ import { keyframeCssValue, keyframesCanonical, keyframesName } from "./keyframes.js";
4
+ import { JavaScriptEmitter, spanIdentity, VELAR_ERROR_NORMALIZATION_MODULE, VELAR_RUNTIME_REGISTRY_KEY } from "@velarscript/compiler/extension";
5
+ import { WEB_RUNTIME_FOUNDATION, WEB_RUNTIME_FOUNDATION_SHARED_ERROR } from "./runtime-foundation.js";
6
+ import { isWebExpression, isWebJsx, isWebKeyframes, isWebLook, isWebStatement, isWebUnit, webExpressionContainsDirectAwait, webStatementContainsDirectAwait, } from "./ast.js";
7
+ const FILE_TYPE_RUNTIME = String.raw `
8
+ function __velarFileTypeIs(value) {
9
+ const descriptor = Object.getOwnPropertyDescriptor(globalThis, Symbol.for("velar.file.registry.v1"));
10
+ if (!descriptor || !("value" in descriptor) || descriptor.configurable || descriptor.enumerable || descriptor.writable) return false;
11
+ try { return WeakMap.prototype.has.call(descriptor.value, value); }
12
+ catch { return false; }
13
+ }
14
+ `.trimStart();
15
+ const WEB_LOCAL_REACTIVE_BRIDGE_RUNTIME = String.raw `
16
+ const __velarReactiveRaw = __velarToRaw;
17
+ function __velarHostRaw(value) { return __velarToRaw(value); }
18
+ `.trimStart();
19
+ const WEB_LOCAL_REACTIVE_COLLECTION_BRIDGE_RUNTIME = String.raw `
20
+ const __velarReactiveIterateKey = Symbol.for("velar.reactive.iterate.v1");
21
+ const __velarReactiveStructureKey = Symbol.for("velar.reactive.structure.v1");
22
+ const __velarReactiveCollectionReadOperation = __velarRuntime.collectionRead;
23
+ const __velarReactiveCollectionTriggerOperation = __velarRuntime.collectionTrigger;
24
+ const __velarReactiveCollectionUnlinkOperation = __velarRuntime.collectionUnlink;
25
+ const __velarReactiveOperation = __velarRuntime.reactive;
26
+ const __velarReactiveTrackOperation = __velarRuntime.track;
27
+ function __velarReactiveCollectionRead(value, key, child) { return __velarReactiveCollectionReadOperation(value, key, child === undefined ? null : child); }
28
+ function __velarReactiveCollectionTrack(value, key = __velarReactiveIterateKey) { __velarReactiveTrackOperation(__velarToRaw(value), key); }
29
+ function __velarReactiveCollectionLink(value, child) { __velarReactiveOperation(child, __velarToRaw(value)); }
30
+ function __velarReactiveCollectionTrigger(value, key, iterate = true, structure = false, indexFrom = null, allKeys = false) { __velarReactiveCollectionTriggerOperation(value, key, iterate, structure, indexFrom, allKeys); }
31
+ function __velarReactiveCollectionUnlink(value, child) { __velarReactiveCollectionUnlinkOperation(value, child); }
32
+ `.trimStart();
33
+ export class WebJavaScriptEmitter extends JavaScriptEmitter {
34
+ currentScope = null;
35
+ currentJsxNamespace = '"html"';
36
+ resourceContents;
37
+ cssOutput = "";
38
+ cssSegments = { before: "", controlled: "", after: "" };
39
+ webOutput = false;
40
+ needsFileTypeHelper = false;
41
+ needsLookArithmeticRuntime = false;
42
+ importedLookStaticValues;
43
+ lookStaticValues = new Map();
44
+ jsxId = 0;
45
+ keyframeNames = new Map();
46
+ constructor(hints, forcedFunctionExports = new Set(), resourceContents = new Map(), extensionImports = new Map(), options = {}) {
47
+ super(hints, forcedFunctionExports, options);
48
+ this.resourceContents = resourceContents;
49
+ this.importedLookStaticValues = new Map([...(extensionImports.get("@velarscript/web") ?? [])]
50
+ .filter((entry) => isLookStaticValue(entry[1])));
51
+ }
52
+ emit(program) {
53
+ this.lookStaticValues = collectLookStaticValues(program, this.importedLookStaticValues);
54
+ this.prepareLooks(program);
55
+ this.webOutput = containsWebSyntax(program);
56
+ this.needsFileTypeHelper = false;
57
+ this.needsLookArithmeticRuntime = [...this.hints.extensionCalls.values()].includes(LOOK_ARITHMETIC_HINT);
58
+ return super.emit(program);
59
+ }
60
+ css() {
61
+ return this.cssOutput;
62
+ }
63
+ styleSegments() {
64
+ return this.cssSegments;
65
+ }
66
+ web() {
67
+ return this.webOutput;
68
+ }
69
+ emitTypeCheck(type, value, state = "undefined") {
70
+ if (type.kind === "named") {
71
+ if (type.name === "Event" || type.name === "KeyboardEvent" || type.name === "PointerEvent" || type.name === "InputEvent" || type.name === "CompositionEvent" || type.name === "ClipboardEvent") {
72
+ return `(typeof ${type.name} !== "undefined" && ${value} instanceof ${type.name})`;
73
+ }
74
+ if (type.name === "Element")
75
+ return `(typeof Element !== "undefined" && ${value} instanceof Element)`;
76
+ if (type.name === "CanvasElement")
77
+ return `(typeof HTMLCanvasElement !== "undefined" && ${value} instanceof HTMLCanvasElement)`;
78
+ if (type.name === "DialogElement")
79
+ return `(typeof HTMLDialogElement !== "undefined" && ${value} instanceof HTMLDialogElement)`;
80
+ if (type.name === "InputElement") {
81
+ return `((typeof HTMLInputElement !== "undefined" && ${value} instanceof HTMLInputElement) || (typeof HTMLSelectElement !== "undefined" && ${value} instanceof HTMLSelectElement) || (typeof HTMLTextAreaElement !== "undefined" && ${value} instanceof HTMLTextAreaElement))`;
82
+ }
83
+ if (type.name === "TextAreaElement")
84
+ return `(typeof HTMLTextAreaElement !== "undefined" && ${value} instanceof HTMLTextAreaElement)`;
85
+ if (type.name === "Blob")
86
+ return `(typeof Blob !== "undefined" && ${value} instanceof Blob)`;
87
+ if (type.name === "File") {
88
+ this.needsFileTypeHelper = true;
89
+ return `__velarFileTypeIs(${value})`;
90
+ }
91
+ }
92
+ return super.emitTypeCheck(type, value, state);
93
+ }
94
+ emitIsCheck(type, value) {
95
+ if (type.kind === "named" && (type.name === "Event"
96
+ || type.name === "KeyboardEvent"
97
+ || type.name === "PointerEvent"
98
+ || type.name === "InputEvent"
99
+ || type.name === "CompositionEvent"
100
+ || type.name === "ClipboardEvent"
101
+ || type.name === "Element"
102
+ || type.name === "CanvasElement"
103
+ || type.name === "DialogElement"
104
+ || type.name === "InputElement"
105
+ || type.name === "TextAreaElement"
106
+ || type.name === "Blob"
107
+ || type.name === "File"))
108
+ return this.emitTypeCheck(type, value);
109
+ return super.emitIsCheck(type, value);
110
+ }
111
+ additionalHelpers(_program) {
112
+ return [
113
+ ...(this.needsLookArithmeticRuntime ? [LOOK_ARITHMETIC_RUNTIME] : []),
114
+ ...(this.webOutput ? this.webRuntimeHelpers() : []),
115
+ ...(this.needsFileTypeHelper ? [FILE_TYPE_RUNTIME] : []),
116
+ ];
117
+ }
118
+ webRuntimeHelpers() {
119
+ if (!this.usesSharedRuntimeModules())
120
+ return [webRuntime(WEB_RUNTIME_FOUNDATION)];
121
+ this.requireRuntimeModule(VELAR_ERROR_NORMALIZATION_MODULE);
122
+ return [
123
+ `import { errorApply as __velarErrorApply, errorCode as __velarErrorCode, isError as __velarIsError, normalizeError as __velarNormalizeError } from ${JSON.stringify(VELAR_ERROR_NORMALIZATION_MODULE)};`,
124
+ webRuntime(WEB_RUNTIME_FOUNDATION_SHARED_ERROR),
125
+ ];
126
+ }
127
+ reactiveBridgeHelpers(needsJavaScriptCallBoundary, needsCollections) {
128
+ if (this.usesSharedRuntimeModules())
129
+ return super.reactiveBridgeHelpers(needsJavaScriptCallBoundary, needsCollections);
130
+ if (!this.webOutput)
131
+ return super.reactiveBridgeHelpers(needsJavaScriptCallBoundary, needsCollections);
132
+ if (!needsJavaScriptCallBoundary && !needsCollections)
133
+ return [];
134
+ return [WEB_LOCAL_REACTIVE_BRIDGE_RUNTIME, ...(needsCollections ? [WEB_LOCAL_REACTIVE_COLLECTION_BRIDGE_RUNTIME] : [])];
135
+ }
136
+ includesErrorNormalizationRuntime() {
137
+ return this.webOutput;
138
+ }
139
+ // Web detached tasks report through the velar/app error chain with the
140
+ // distinct "detached" phase. The runtime registry is looked up at report
141
+ // time (module-level tasks can finish before or after the application
142
+ // runtime installs); the captured microtask throw keeps a failure loud when
143
+ // no runtime exists yet, and 'unhandled: true' keeps it loud when no
144
+ // onError handler is installed. Host operations are captured at module
145
+ // initialization, matching the owned-callback discipline.
146
+ detachedTaskHelpers() {
147
+ // A module with no Web syntax emits no Web runtime, so it must keep Core's
148
+ // host reporting: the browser path would route a detached failure through a
149
+ // runtime registry that never gets installed and end in a microtask throw,
150
+ // which under `velar test` kills the whole Node test process.
151
+ if (!this.webOutput)
152
+ return super.detachedTaskHelpers();
153
+ return [[
154
+ `const __velarDetachedRegistryKey = Symbol.for(${JSON.stringify(VELAR_RUNTIME_REGISTRY_KEY)});`,
155
+ "const __velarDetachedPromiseThen = globalThis.Promise.prototype.then;",
156
+ "const __velarDetachedApply = Reflect.apply;",
157
+ "const __velarDetachedEnqueue = queueMicrotask;",
158
+ "function __velarDetachedReport(failure) {",
159
+ " const error = __velarNormalizeError(failure);",
160
+ " const runtime = globalThis[__velarDetachedRegistryKey];",
161
+ " if (runtime && typeof runtime.report === \"function\") {",
162
+ " // An action reports its own failure once, in the action phase with",
163
+ " // the action's name as detail. The detached observer of that same",
164
+ " // rejection must not report it a second time.",
165
+ " try {",
166
+ " if (__velarIsError(failure) && __velarGraphWeakSetRemove(runtime.actionFailures, failure)) return;",
167
+ " } catch {}",
168
+ " runtime.report(error, { phase: \"detached\", detail: \"\", unhandled: true });",
169
+ " return;",
170
+ " }",
171
+ " __velarDetachedApply(__velarDetachedEnqueue, globalThis, [() => { throw error; }]);",
172
+ "}",
173
+ "function __velarDetachedTask(task) {",
174
+ " __velarDetachedApply(__velarDetachedPromiseThen, task, [null, __velarDetachedReport]);",
175
+ " return null;",
176
+ "}",
177
+ ].join("\n")];
178
+ }
179
+ visitExtensionRuntimeExpression(expression, visitExpression) {
180
+ if (isWebUnit(expression))
181
+ return true;
182
+ if (isWebKeyframes(expression)) {
183
+ for (const stop of expression.stops)
184
+ for (const entry of stop.entries)
185
+ visitExpression(entry.value);
186
+ return true;
187
+ }
188
+ if (isWebLook(expression)) {
189
+ visitLookExpressions(expression.entries, visitExpression);
190
+ return true;
191
+ }
192
+ if (!isWebJsx(expression))
193
+ return false;
194
+ expression.attributes.forEach((attribute) => {
195
+ if (typeof attribute.value !== "string" && attribute.value)
196
+ visitExpression(attribute.value);
197
+ });
198
+ expression.children.forEach((child) => {
199
+ if (child.kind === "JSXExpressionChild")
200
+ visitExpression(child.expression);
201
+ else if (child.kind === "ExtensionExpression:web:jsx")
202
+ visitExpression(child);
203
+ });
204
+ return true;
205
+ }
206
+ visitExtensionRuntimeStatement(statement, visitExpression, visitStatement) {
207
+ if (!isWebStatement(statement))
208
+ return false;
209
+ if (statement.kind === "ExtensionStatement:web:unsafe-css")
210
+ return true;
211
+ if (statement.kind === "ExtensionStatement:web:state" || statement.kind === "ExtensionStatement:web:computed"
212
+ || statement.kind === "ExtensionStatement:web:resource") {
213
+ visitExpression(statement.initializer);
214
+ return true;
215
+ }
216
+ if (statement.kind === "ExtensionStatement:web:action") {
217
+ statement.parameters.forEach((parameter) => { if (parameter.defaultValue)
218
+ visitExpression(parameter.defaultValue); });
219
+ statement.body.forEach(visitStatement);
220
+ return true;
221
+ }
222
+ if (statement.kind === "ExtensionStatement:web:watch") {
223
+ visitExpression(statement.expression);
224
+ statement.body.forEach(visitStatement);
225
+ return true;
226
+ }
227
+ if (statement.kind !== "ExtensionStatement:web:component")
228
+ return false;
229
+ statement.parameters.forEach((parameter) => { if (parameter.defaultValue)
230
+ visitExpression(parameter.defaultValue); });
231
+ statement.body.forEach((item) => {
232
+ if (item.kind === "ExtensionStatement:web:state" || item.kind === "ExtensionStatement:web:computed"
233
+ || item.kind === "ExtensionStatement:web:resource")
234
+ visitExpression(item.initializer);
235
+ else if (item.kind === "ExtensionStatement:web:action") {
236
+ item.parameters.forEach((parameter) => { if (parameter.defaultValue)
237
+ visitExpression(parameter.defaultValue); });
238
+ item.body.forEach(visitStatement);
239
+ }
240
+ else if (item.kind === "ExtensionStatement:web:watch") {
241
+ visitExpression(item.expression);
242
+ item.body.forEach(visitStatement);
243
+ }
244
+ else if (item.kind === "ExtensionStatement:web:expose")
245
+ visitExpression(item.value);
246
+ else if (item.kind === "ExtensionStatement:web:mounted" || item.kind === "ExtensionStatement:web:cleanup")
247
+ item.body.forEach(visitStatement);
248
+ else
249
+ visitStatement(item);
250
+ });
251
+ return true;
252
+ }
253
+ extensionExpressionContainsDirectAwait(expression, contains) {
254
+ return webExpressionContainsDirectAwait(expression, contains);
255
+ }
256
+ extensionStatementContainsDirectAwait(statement, containsExpression, containsBlock) {
257
+ return webStatementContainsDirectAwait(statement, containsExpression, containsBlock);
258
+ }
259
+ emitStatement(statement, depth) {
260
+ if (isWebStatement(statement)) {
261
+ if (statement.kind === "ExtensionStatement:web:unsafe-css")
262
+ return "";
263
+ if (statement.kind === "ExtensionStatement:web:component")
264
+ return this.emitComponent(statement, depth);
265
+ if (statement.kind === "ExtensionStatement:web:state") {
266
+ const indentation = " ".repeat(depth);
267
+ return `${indentation}${statement.exported ? "export " : ""}const ${statement.name} = __velarState(${this.emitMappedExpression(statement.initializer)});`;
268
+ }
269
+ if (statement.kind === "ExtensionStatement:web:computed") {
270
+ const indentation = " ".repeat(depth);
271
+ return `${indentation}${statement.exported ? "export " : ""}const ${statement.name} = __velarComputed(() => (${this.emitMappedExpression(statement.initializer)}));`;
272
+ }
273
+ if (statement.kind === "ExtensionStatement:web:resource")
274
+ return "";
275
+ if (statement.kind === "ExtensionStatement:web:action") {
276
+ // A module action wires the same reactive pending/error cells as a
277
+ // component action, but it lives in the never-destroyed global scope, so
278
+ // its lifetime is the module and no component disposal applies.
279
+ const indentation = " ".repeat(depth);
280
+ const parameters = statement.parameters.map((parameter) => this.emitParameter(parameter.name, parameter.defaultValue, parameter.rest)).join(", ");
281
+ const actionLines = [...this.emitStatementLines(statement.body, depth + 1)];
282
+ if (!this.blockAlwaysReturns(statement.body))
283
+ actionLines.push(`${" ".repeat(depth + 1)}return null;`);
284
+ const actionBody = actionLines.join("\n");
285
+ return `${indentation}${statement.exported ? "export " : ""}const ${statement.name} = __velarAction(async (${parameters}) => {${actionBody ? `\n${actionBody}\n${indentation}` : ""}}, __velarGlobalScope, ${JSON.stringify(statement.name)});`;
286
+ }
287
+ if (statement.kind === "ExtensionStatement:web:watch") {
288
+ const indentation = " ".repeat(depth);
289
+ const parameters = [statement.currentName, statement.previousName].filter((name) => name !== null).join(", ");
290
+ const body = this.emitStatementLines(statement.body, depth + 1).join("\n");
291
+ return `${indentation}__velarWatch(() => ${this.emitMappedExpression(statement.expression)}, (${parameters}) => {${body ? `\n${body}\n${indentation}` : ""}}, __velarGlobalScope);`;
292
+ }
293
+ }
294
+ if (statement.kind === "AssignmentStatement") {
295
+ const reactive = this.emitReactiveAssignment(statement, depth);
296
+ if (reactive)
297
+ return reactive;
298
+ }
299
+ return super.emitStatement(statement, depth);
300
+ }
301
+ emitExpression(expression) {
302
+ if (isWebUnit(expression))
303
+ return JSON.stringify(expression.raw);
304
+ if (isWebKeyframes(expression)) {
305
+ const name = this.keyframeNames.get(spanIdentity(expression.span)) ?? keyframesName(keyframesCanonical(expression, this.lookStaticValues));
306
+ return `__velarKeyframesValue(${JSON.stringify(name)})`;
307
+ }
308
+ if (expression.kind === "UnaryExpression" && (expression.operator === "+" || expression.operator === "-")
309
+ && (isWebUnit(expression.operand)
310
+ || this.hints.extensionCalls.get(spanIdentity(expression.span)) === LOOK_ARITHMETIC_HINT)) {
311
+ if (isWebUnit(expression.operand)) {
312
+ const value = expression.operator === "-" ? -expression.operand.value : expression.operand.value;
313
+ return JSON.stringify(`${Object.is(value, -0) ? 0 : value}${expression.operand.unit}`);
314
+ }
315
+ return `__velarLookUnary(${JSON.stringify(expression.operator)}, ${this.emitMappedExpression(expression.operand)})`;
316
+ }
317
+ if (expression.kind === "BinaryExpression" && ["+", "-", "*", "/"].includes(expression.operator)
318
+ && (containsUnitLiteral(expression)
319
+ || this.hints.extensionCalls.get(spanIdentity(expression.span)) === LOOK_ARITHMETIC_HINT)) {
320
+ return this.emitLookArithmetic(expression);
321
+ }
322
+ if (isWebExpression(expression) && expression.kind === "ExtensionExpression:web:look-hook")
323
+ return "false";
324
+ if (isWebLook(expression))
325
+ return this.emitLook(expression);
326
+ if (expression.kind === "IdentifierExpression") {
327
+ if (this.hints.reactiveReferences.has(spanIdentity(expression.span))) {
328
+ return `${expression.name}.get()`;
329
+ }
330
+ if (expression.name === "mount")
331
+ return "__velarMount";
332
+ if (expression.name === "tick")
333
+ return "__velarTick";
334
+ if (expression.name === "cached")
335
+ return "__velarRuntime.computed";
336
+ const controlled = this.hints.extensionLiterals.get(spanIdentity(expression.span));
337
+ if (controlled !== undefined)
338
+ return JSON.stringify(controlled);
339
+ }
340
+ if (isWebJsx(expression)) {
341
+ return this.emitJsx(expression, this.currentScope ?? "__velarGlobalScope", this.currentScope !== null, this.currentJsxNamespace, false);
342
+ }
343
+ if (expression.kind === "CallExpression" && expression.callee.kind === "IdentifierExpression"
344
+ && expression.callee.name === "mount" && expression.arguments.length === 2) {
345
+ const sourceArguments = expression.arguments.map((argument) => this.emitMappedExpression(argument));
346
+ const namedOrder = this.hints.namedArgumentOrders.get(spanIdentity(expression.span));
347
+ const arguments_ = namedOrder
348
+ ? namedOrder.map((source) => source === -1 ? "undefined" : `__velarNamedArguments[${source}]`)
349
+ : sourceArguments;
350
+ const evaluated = namedOrder
351
+ ? `((__velarNamedArguments) => [${arguments_.join(", ")}])([${sourceArguments.join(", ")}])`
352
+ : `[${arguments_.join(", ")}]`;
353
+ const targetSource = namedOrder?.[1] ?? 1;
354
+ const target = targetSource >= 0 ? expression.arguments[targetSource] : null;
355
+ const fallbackTarget = target?.kind === "LiteralExpression" && typeof target.value === "string"
356
+ ? JSON.stringify(target.value)
357
+ : "null";
358
+ return `__velarMount(() => ${evaluated}, ${fallbackTarget})`;
359
+ }
360
+ const emitted = super.emitExpression(expression);
361
+ if (!this.webOutput)
362
+ return emitted;
363
+ // One expression can lower to more than one pop, so the reactive wrapper
364
+ // has to reach every occurrence rather than the first match.
365
+ if (!emitted.includes("__velarListPop("))
366
+ return emitted;
367
+ return emitted.replaceAll("__velarListPop(", "__velarWebListPop(");
368
+ }
369
+ emitLook(expression) {
370
+ return `__velarLook([${this.emitLookEntries(expression.entries, [EMPTY_LOOK_TERM], "").join(", ")}])`;
371
+ }
372
+ emitLookEntries(entries, contexts, target) {
373
+ const parts = [];
374
+ for (const entry of entries) {
375
+ if (entry.kind === "LookSpread") {
376
+ parts.push(this.emitMappedExpression(entry.value));
377
+ continue;
378
+ }
379
+ if (entry.kind === "LookIf") {
380
+ const thenContexts = combineLookTerms(contexts, lookConditionTerms(entry.condition, false, this.lookStaticValues));
381
+ const elseContexts = combineLookTerms(contexts, lookConditionTerms(entry.condition, true, this.lookStaticValues));
382
+ parts.push(...this.emitLookEntries(entry.thenEntries, thenContexts, target));
383
+ parts.push(...this.emitLookEntries(entry.elseEntries, elseContexts, target));
384
+ continue;
385
+ }
386
+ if (entry.kind === "LookTarget") {
387
+ parts.push(...this.emitLookEntries(entry.entries, contexts, entry.name));
388
+ continue;
389
+ }
390
+ const property = cssPropertyName(entry.name);
391
+ for (const context of contexts) {
392
+ const token = lookToken(context.staticAtoms, target, property);
393
+ const rule = `{ rules: { ${JSON.stringify(token)}: ${this.emitLookValue(entry.value)} } }`;
394
+ const runtime = context.runtimeAtoms.map((atom) => {
395
+ const value = this.emitCondition(atom.expression);
396
+ return atom.negated ? `!(${value})` : `(${value})`;
397
+ }).join(" && ");
398
+ parts.push(runtime ? `(${runtime} ? ${rule} : null)` : rule);
399
+ }
400
+ }
401
+ return parts;
402
+ }
403
+ emitLookValue(expression) {
404
+ return this.emitMappedExpression(expression);
405
+ }
406
+ emitLookArithmetic(expression) {
407
+ return `__velarLookMath(${JSON.stringify(expression.operator)}, ${this.emitMappedExpression(expression.left)}, ${this.emitMappedExpression(expression.right)})`;
408
+ }
409
+ emitComponent(statement, depth) {
410
+ const indentation = " ".repeat(depth);
411
+ const outerIndent = " ".repeat(depth + 1);
412
+ const bodyIndent = " ".repeat(depth + 2);
413
+ const previousScope = this.currentScope;
414
+ const previousJsxNamespace = this.currentJsxNamespace;
415
+ this.currentScope = "__velarComponentScope";
416
+ this.currentJsxNamespace = "__velarNamespace";
417
+ // Props are live reactive inputs: every parameter becomes a read-only
418
+ // handle over the per-instance props store, so prop reads lower through
419
+ // .get() exactly like state reads do.
420
+ const lines = [];
421
+ for (const parameter of statement.parameters) {
422
+ if (parameter.defaultValue) {
423
+ lines.push(`${bodyIndent}const ${parameter.name} = __velarProp(__velarProps, ${JSON.stringify(parameter.name)}, () => (${this.emitMappedExpression(parameter.defaultValue)}));`);
424
+ }
425
+ else {
426
+ lines.push(`${bodyIndent}const ${parameter.name} = __velarRequiredProp(__velarProps, ${JSON.stringify(parameter.name)}, ${JSON.stringify(statement.name)});`);
427
+ }
428
+ }
429
+ let render = null;
430
+ let expose = null;
431
+ let mountedBody = [];
432
+ let cleanupBody = [];
433
+ for (const item of statement.body) {
434
+ if (item.kind === "ExtensionStatement:web:state") {
435
+ lines.push(`${bodyIndent}const ${item.name} = __velarState(${this.emitMappedExpression(item.initializer)});`);
436
+ }
437
+ else if (item.kind === "ExtensionStatement:web:computed") {
438
+ lines.push(`${bodyIndent}const ${item.name} = __velarComputed(() => (${this.emitMappedExpression(item.initializer)}));`);
439
+ }
440
+ else if (item.kind === "ExtensionStatement:web:resource") {
441
+ lines.push(`${bodyIndent}const ${item.name} = __velarResource(() => ${this.emitMappedExpression(item.initializer)}, __velarComponentScope, ${JSON.stringify(item.name)});`);
442
+ }
443
+ else if (item.kind === "ExtensionStatement:web:action") {
444
+ const parameters = item.parameters.map((parameter) => this.emitParameter(parameter.name, parameter.defaultValue, parameter.rest)).join(", ");
445
+ const actionLines = [...this.emitStatementLines(item.body, depth + 3)];
446
+ if (!this.blockAlwaysReturns(item.body))
447
+ actionLines.push(`${" ".repeat(depth + 3)}return null;`);
448
+ const actionBody = actionLines.join("\n");
449
+ lines.push(`${bodyIndent}const ${item.name} = __velarAction(async (${parameters}) => {${actionBody ? `\n${actionBody}\n${bodyIndent}` : ""}}, __velarComponentScope, ${JSON.stringify(item.name)});`);
450
+ }
451
+ else if (item.kind === "ExtensionStatement:web:watch") {
452
+ const parameters = [item.currentName, item.previousName].filter((name) => name !== null).join(", ");
453
+ const watchLines = this.emitStatementLines(item.body, depth + 3).join("\n");
454
+ lines.push(`${bodyIndent}__velarWatch(() => ${this.emitMappedExpression(item.expression)}, (${parameters}) => {${watchLines ? `\n${watchLines}\n${bodyIndent}` : ""}}, __velarComponentScope);`);
455
+ }
456
+ else if (item.kind === "ExtensionStatement:web:expose") {
457
+ expose ??= item.value;
458
+ }
459
+ else if (item.kind === "ExtensionStatement:web:mounted") {
460
+ mountedBody = item.body;
461
+ }
462
+ else if (item.kind === "ExtensionStatement:web:cleanup") {
463
+ cleanupBody = item.body;
464
+ }
465
+ else if (item.kind === "ReturnStatement") {
466
+ render = item.value;
467
+ }
468
+ else {
469
+ lines.push(this.emitMappedStatement(item, depth + 2));
470
+ }
471
+ }
472
+ // A direct JSX root owns its own attribute/child observers and keeps a
473
+ // stable host. Every other WebNode expression is a live root position:
474
+ // evaluate it inside a dedicated child scope so conditions and helper
475
+ // calls can replace the root without rerunning component setup.
476
+ let renderedRoot = "__velarDomCreateComment(\"missing render\")";
477
+ if (render) {
478
+ if (isWebJsx(render))
479
+ renderedRoot = this.emitMappedExpression(render);
480
+ else {
481
+ const rootScope = this.currentScope;
482
+ this.currentScope = "__velarDynamicScope";
483
+ try {
484
+ renderedRoot = `__velarDynamicComponent((__velarDynamicScope) => ${this.emitMappedExpression(render)}, __velarComponentScope)`;
485
+ }
486
+ finally {
487
+ this.currentScope = rootScope;
488
+ }
489
+ }
490
+ }
491
+ lines.push(`${bodyIndent}const __velarRoot = ${renderedRoot};`);
492
+ lines.push(`${bodyIndent}const __velarHandle = ${expose ? `__velarComponentHandle(${this.emitMappedExpression(expose)}, ${JSON.stringify(statement.name)})` : "null"};`);
493
+ lines.push(`${bodyIndent}if (__velarProps.class !== undefined) __velarClassBindRoot(__velarRoot, () => __velarProps.class, __velarComponentScope);`);
494
+ lines.push(`${bodyIndent}if (__velarProps.look !== undefined) __velarLookBindRoot(__velarRoot, () => __velarProps.look, __velarComponentScope);`);
495
+ lines.push(`${bodyIndent}if (__velarProps.__velarStyle !== undefined) __velarStyleBindRoot(__velarRoot, () => __velarProps.__velarStyle, __velarComponentScope);`);
496
+ const mounted = this.emitStatementLines(mountedBody, depth + 3).join("\n");
497
+ const cleanup = cleanupBody.map((child) => {
498
+ if (["VariableDeclaration", "FunctionDeclaration", "ClassDeclaration", "TypeDeclaration", "EnumDeclaration"].includes(child.kind)) {
499
+ return this.emitMappedStatement(child, depth + 3);
500
+ }
501
+ const inner = this.emitMappedStatement(child, depth + 4);
502
+ if (!inner)
503
+ return "";
504
+ const cleanupIndent = " ".repeat(depth + 3);
505
+ return `${cleanupIndent}__velarCleanupStep(() => {\n${inner}\n${cleanupIndent}}, __velarComponentScope);`;
506
+ }).filter(Boolean).join("\n");
507
+ const cleanupBodyText = `() => {${cleanup ? `\n${cleanup}\n${bodyIndent}` : ""}}`;
508
+ const functionLines = [
509
+ `${outerIndent}const __velarComponentScope = __velarSetupBegin(__velarScope(${JSON.stringify(statement.name)}));`,
510
+ `${outerIndent}let __velarConstructionCleanup = () => {};`,
511
+ `${outerIndent}try {`,
512
+ `${bodyIndent}__velarConstructionCleanup = ${cleanupBodyText};`,
513
+ ...lines,
514
+ `${bodyIndent}return __velarSetupEnd(__velarComponent(__velarRoot, __velarComponentScope, async () => {${mounted ? `\n${mounted}\n${bodyIndent}` : ""}}, __velarConstructionCleanup, __velarHandle));`,
515
+ `${outerIndent}} catch (__velarConstructionError) {`,
516
+ `${bodyIndent}__velarSetupEnd(null);`,
517
+ `${bodyIndent}try { __velarConstructionCleanup(); } catch (__velarCleanupError) { __velarReport(__velarCleanupError, "cleanup", __velarComponentScope); }`,
518
+ `${bodyIndent}__velarDestroyScope(__velarComponentScope);`,
519
+ `${bodyIndent}throw __velarConstructionError;`,
520
+ `${outerIndent}}`,
521
+ ];
522
+ this.currentScope = previousScope;
523
+ this.currentJsxNamespace = previousJsxNamespace;
524
+ return `${indentation}${statement.exported ? "export " : ""}function ${statement.name}(__velarProps = {}, __velarNamespace = "html") {\n${functionLines.filter(Boolean).join("\n")}\n${indentation}}`;
525
+ }
526
+ emitReactiveAssignment(statement, depth) {
527
+ const indentation = " ".repeat(depth);
528
+ if (statement.target.kind === "IdentifierExpression"
529
+ && this.hints.reactiveReferences.get(spanIdentity(statement.target.span)) === "state") {
530
+ const state = statement.target.name;
531
+ const value = this.emitMappedExpression(statement.value);
532
+ if (statement.operator === "=")
533
+ return `${indentation}${state}.set(${value});`;
534
+ return `${indentation}${state}.set(${state}.get() ${statement.operator.slice(0, -1)} ${value});`;
535
+ }
536
+ return null;
537
+ }
538
+ emitJsx(expression, scope, asChild, namespace, mapped = true) {
539
+ const render = () => this.emitJsxCode(expression, scope, asChild, namespace);
540
+ return mapped ? this.emitMappedJavaScript(expression.span, render) : render();
541
+ }
542
+ emitJsxCode(expression, scope, asChild, namespace) {
543
+ if (/^[A-Z]/u.test(expression.tag)) {
544
+ const reactiveComponent = this.hints.reactiveReferences.has(spanIdentity(expression.tagSpan));
545
+ const componentScope = reactiveComponent ? "__velarDynamicScope" : scope;
546
+ const previousScope = this.currentScope;
547
+ if (reactiveComponent)
548
+ this.currentScope = componentScope;
549
+ try {
550
+ // Static component identity keeps the existing stable child fast path.
551
+ // A reactive Component value owns a dynamic region that remounts only
552
+ // when the constructor identity itself changes; ordinary prop updates
553
+ // continue through the child's live prop cells.
554
+ const properties = expression.attributes
555
+ .filter((attribute) => attribute.name !== "key" && attribute.name !== "ref" && attribute.name !== "look" && !attribute.name.startsWith("look:")
556
+ && attribute.name !== "style" && !attribute.name.startsWith("style:"))
557
+ .map((attribute) => this.emitMappedJavaScript(attribute.span, () => `${this.emitObjectKey(attribute.name)}: () => (${this.emitJsxAttributeValue(attribute)})`));
558
+ const lookValue = this.emitJsxLookValue(expression);
559
+ const lookAttribute = expression.attributes.find((attribute) => attribute.name === "look" || attribute.name.startsWith("look:"));
560
+ if (lookValue && lookAttribute) {
561
+ properties.push(this.emitMappedJavaScript(lookAttribute.span, () => `look: () => (${lookValue})`));
562
+ }
563
+ const styleValue = this.emitJsxStyleValue(expression);
564
+ const styleAttribute = expression.attributes.find((attribute) => attribute.name.startsWith("style:"));
565
+ if (styleValue && styleAttribute) {
566
+ properties.push(this.emitMappedJavaScript(styleAttribute.span, () => `__velarStyle: () => (${styleValue})`));
567
+ }
568
+ // Children stay a thunk so the charter's evaluation order holds at
569
+ // the runtime boundary: props left to right, then children, then the
570
+ // component function.
571
+ const children = hasMeaningfulChildren(expression.children)
572
+ ? `() => (${this.emitJsxChildren(expression.children, componentScope, namespace)})`
573
+ : "undefined";
574
+ const ref = expression.attributes.find((attribute) => attribute.name === "ref")?.value;
575
+ const refSetter = ref && typeof ref !== "string" && ref.kind === "IdentifierExpression"
576
+ ? `(next, previous) => { if (previous === undefined || ${ref.name} === previous) ${ref.name} = next; }`
577
+ : null;
578
+ const component = reactiveComponent ? `${expression.tag}.get()` : expression.tag;
579
+ const arguments_ = `${component}, { ${properties.join(", ")} }, ${children}, ${componentScope}, ${namespace}${refSetter ? `, ${refSetter}` : ""}`;
580
+ if (reactiveComponent) {
581
+ return `__velarDynamicComponent((__velarDynamicScope) => __velarChild(${arguments_}), ${scope})`;
582
+ }
583
+ return asChild ? `__velarChild(${arguments_})` : `__velarInstantiate(${arguments_})`;
584
+ }
585
+ finally {
586
+ this.currentScope = previousScope;
587
+ }
588
+ }
589
+ const id = ++this.jsxId;
590
+ const element = `__velarElement${id}`;
591
+ const elementNamespace = expression.tag === "svg" ? '"svg"' : namespace;
592
+ const childNamespace = expression.tag === "foreignObject" ? '"html"' : elementNamespace;
593
+ const lines = [expression.tag
594
+ ? `const ${element} = __velarCreateElement(${JSON.stringify(expression.tag)}, ${elementNamespace});`
595
+ : `const ${element} = __velarDomCreateFragment();`];
596
+ let emittedLook = false;
597
+ let emittedStyle = false;
598
+ for (const attribute of expression.attributes) {
599
+ if (attribute.name === "key")
600
+ continue;
601
+ if (attribute.name === "look" || attribute.name.startsWith("look:")) {
602
+ if (!emittedLook) {
603
+ emittedLook = true;
604
+ const lookValue = this.emitJsxLookValue(expression);
605
+ if (lookValue)
606
+ lines.push(this.emitMappedJavaScript(attribute.span, () => `__velarLookBind(${element}, () => ${lookValue}, ${scope});`));
607
+ }
608
+ continue;
609
+ }
610
+ if (attribute.name.startsWith("style:")) {
611
+ if (!emittedStyle) {
612
+ emittedStyle = true;
613
+ const styleValue = this.emitJsxStyleValue(expression);
614
+ if (styleValue)
615
+ lines.push(this.emitMappedJavaScript(attribute.span, () => `__velarStyleBind(${element}, () => (${styleValue}), ${scope});`));
616
+ }
617
+ continue;
618
+ }
619
+ if (attribute.name === "style")
620
+ continue;
621
+ lines.push(this.emitMappedJavaScript(attribute.span, () => {
622
+ const value = attribute.value;
623
+ if (attribute.name === "ref" && value && typeof value !== "string" && value.kind === "IdentifierExpression") {
624
+ return `${value.name} = ${element}; __velarAppendOwned(${scope}.cleanups, () => { if (${value.name} === ${element}) ${value.name} = null; });`;
625
+ }
626
+ if (attribute.name.startsWith("on:") && value && typeof value !== "string") {
627
+ const [event, ...modifiers] = attribute.name.slice(3).split(".");
628
+ return `__velarOn(${element}, ${JSON.stringify(event)}, () => (${this.emitMappedExpression(value)}), ${scope}, ${JSON.stringify(modifiers)});`;
629
+ }
630
+ if (attribute.name === "bind:value" && value && typeof value !== "string") {
631
+ const numeric = expression.tag === "input" && expression.attributes.some((item) => item.name === "type" && item.value === "number");
632
+ const enumName = this.hints.enumValueBindings.get(attribute.span.start);
633
+ return `__velarBindValue(${element}, ${this.emitBindTarget(value)}, ${scope}, ${numeric}${enumName ? `, ${enumName}.parse` : ""});`;
634
+ }
635
+ if (attribute.name === "bind:checked" && value && typeof value !== "string") {
636
+ return `__velarBindChecked(${element}, ${this.emitBindTarget(value)}, ${scope});`;
637
+ }
638
+ if (attribute.name === "bind:group" && value && typeof value !== "string") {
639
+ const multiple = expression.attributes.some((item) => item.name === "type" && item.value === "checkbox");
640
+ const enumName = this.hints.enumValueBindings.get(attribute.span.start);
641
+ return `__velarBindGroup(${element}, ${this.emitBindTarget(value)}, ${scope}, ${multiple}${enumName ? `, ${enumName}.parse` : ""});`;
642
+ }
643
+ if (attribute.name.startsWith("class:") && value && typeof value !== "string") {
644
+ return `__velarClass(${element}, ${JSON.stringify(attribute.name.slice(6))}, () => ${this.emitMappedExpression(value)}, ${scope});`;
645
+ }
646
+ if (attribute.name === "host")
647
+ return `${element}.__velarHost = true;`;
648
+ if (attribute.name === "class" && value && typeof value !== "string") {
649
+ return `__velarClassBind(${element}, () => ${this.emitMappedExpression(value)}, ${scope});`;
650
+ }
651
+ if (attribute.name === "unsafe:html") {
652
+ const html = typeof value === "string" ? JSON.stringify(value) : value === null ? '""' : this.emitMappedExpression(value);
653
+ return `__velarHtml(${element}, () => ${html}, ${scope});`;
654
+ }
655
+ if (typeof value === "string" || value === null) {
656
+ return `__velarStaticAttr(${element}, ${JSON.stringify(attribute.name)}, ${value === null ? "true" : JSON.stringify(value)});`;
657
+ }
658
+ return `__velarAttr(${element}, ${JSON.stringify(attribute.name)}, () => ${this.emitMappedExpression(value)}, ${scope});`;
659
+ }));
660
+ }
661
+ for (const child of expression.children) {
662
+ if (child.kind === "JSXText") {
663
+ const text = normalizeJsxText(child.value);
664
+ if (text)
665
+ lines.push(this.emitMappedJavaScript(child.span, () => `__velarDomAppend(${element}, __velarDomCreateTextNode(${JSON.stringify(text)}));`));
666
+ }
667
+ else if (child.kind === "ExtensionExpression:web:jsx") {
668
+ lines.push(this.emitMappedJavaScript(child.span, () => `__velarAppend(${element}, ${this.emitJsx(child, scope, true, childNamespace)});`));
669
+ }
670
+ else {
671
+ lines.push(this.emitMappedJavaScript(child.expression.span, () => this.emitDynamicChild(element, child.expression, scope, childNamespace)));
672
+ }
673
+ }
674
+ lines.push(`return ${element};`);
675
+ return `(() => { ${lines.join(" ")} })()`;
676
+ }
677
+ emitJsxChildren(children, scope, namespace) {
678
+ const fragmentSpan = children[0]?.span ?? { start: 0, end: 0 };
679
+ const fragment = { kind: "ExtensionExpression:web:jsx", tag: "", tagSpan: { start: fragmentSpan.start, end: fragmentSpan.start }, attributes: [], children, span: fragmentSpan };
680
+ return this.emitJsx(fragment, scope, true, namespace);
681
+ }
682
+ emitDynamicChild(parent, expression, scope, namespace) {
683
+ const leaves = dynamicChildLeaves(expression);
684
+ const previousScope = this.currentScope;
685
+ const previousJsxNamespace = this.currentJsxNamespace;
686
+ this.currentScope = "__velarChildScope";
687
+ this.currentJsxNamespace = namespace;
688
+ // A conditional splits into one region per branch leaf only when a keyed
689
+ // list is somewhere among them; each region gates itself on the shared
690
+ // branch conditions, so at most one region renders content at a time and
691
+ // the keyed list keeps identity-preserving children across the branch flip.
692
+ // Without a keyed leaf the interpolation stays one dynamic region.
693
+ const statements = leaves.some((leaf) => leaf.list?.key)
694
+ ? leaves.map((leaf) => this.emitDynamicChildLeaf(parent, leaf, scope, namespace))
695
+ : [`__velarDynamic(${parent}, (__velarChildScope) => ${this.emitMappedExpression(expression)}, ${scope});`];
696
+ this.currentScope = previousScope;
697
+ this.currentJsxNamespace = previousJsxNamespace;
698
+ return statements.join(" ");
699
+ }
700
+ emitDynamicChildLeaf(parent, leaf, scope, namespace) {
701
+ const list = leaf.list;
702
+ if (list?.key) {
703
+ const source = this.emitGuardedExpression(leaf.guards, this.emitMappedExpression(list.source), "[]");
704
+ const parameter = list.arrow.parameters[0].name;
705
+ const key = this.emitJsxAttributeValue(list.key);
706
+ const render = this.emitJsx(list.arrow.body, "__velarChildScope", true, namespace);
707
+ return `__velarKeyed(${parent}, () => ${source}, (${parameter}) => ${key}, (${parameter}, __velarChildScope) => ${render}, ${scope});`;
708
+ }
709
+ const value = this.emitGuardedExpression(leaf.guards, this.emitMappedExpression(leaf.expression), "null");
710
+ return `__velarDynamic(${parent}, (__velarChildScope) => ${value}, ${scope});`;
711
+ }
712
+ // Wraps a leaf's expression in its branch conditions, innermost last, so the
713
+ // leaf evaluates only while its branch is active and yields the inactive
714
+ // placeholder ('[]' for keyed reads, 'null' for dynamic regions) otherwise.
715
+ emitGuardedExpression(guards, inner, inactive) {
716
+ let output = inner;
717
+ for (let index = guards.length - 1; index >= 0; index -= 1) {
718
+ const guard = guards[index];
719
+ const condition = this.emitMappedExpression(guard.condition);
720
+ output = guard.thenBranch
721
+ ? `(${condition}) ? (${output}) : ${inactive}`
722
+ : `(${condition}) ? ${inactive} : (${output})`;
723
+ }
724
+ return output;
725
+ }
726
+ /**
727
+ * D47 rule 84(A): a bind target is a state cell, or a writable reactive
728
+ * location inside one. A member/index path lowers to the get/set pair the
729
+ * binding helpers already expect, so a field of state reads and writes through
730
+ * exactly the same statements the author would have written by hand.
731
+ */
732
+ emitBindTarget(value) {
733
+ if (value.kind === "IdentifierExpression")
734
+ return value.name;
735
+ const next = { kind: "IdentifierExpression", name: "__velarBindNext", span: value.span };
736
+ const read = this.emitMappedExpression(value);
737
+ const assignment = { kind: "AssignmentStatement", target: value, value: next, operator: "=", span: value.span };
738
+ const write = this.emitStatement(assignment, 0).trim();
739
+ return `{ get: () => (${read}), set: (__velarBindNext) => { ${write} } }`;
740
+ }
741
+ emitJsxAttributeValue(attribute) {
742
+ if (attribute.value === null)
743
+ return "true";
744
+ if (typeof attribute.value === "string")
745
+ return JSON.stringify(attribute.value);
746
+ return this.emitMappedExpression(attribute.value);
747
+ }
748
+ emitJsxLookValue(expression) {
749
+ const base = expression.attributes.find((attribute) => attribute.name === "look");
750
+ const inline = expression.attributes.filter((attribute) => attribute.name.startsWith("look:"));
751
+ const baseValue = base?.value && typeof base.value !== "string" ? this.emitMappedExpression(base.value) : null;
752
+ if (inline.length === 0)
753
+ return baseValue;
754
+ const rules = inline.map((attribute) => {
755
+ const property = cssPropertyName(attribute.name.slice("look:".length));
756
+ const token = lookToken([], "", property);
757
+ const value = attribute.value === null ? "null"
758
+ : typeof attribute.value === "string" ? JSON.stringify(attribute.value)
759
+ : this.emitMappedExpression(attribute.value);
760
+ return `${JSON.stringify(token)}: ${value}`;
761
+ });
762
+ const anonymous = `{ rules: { ${rules.join(", ")} } }`;
763
+ return `__velarLook([${[baseValue, anonymous].filter(Boolean).join(", ")}])`;
764
+ }
765
+ emitJsxStyleValue(expression) {
766
+ const inline = expression.attributes.filter((attribute) => attribute.name.startsWith("style:"));
767
+ if (inline.length === 0)
768
+ return null;
769
+ const properties = inline.map((attribute) => {
770
+ const property = cssPropertyName(attribute.name.slice("style:".length));
771
+ const value = attribute.value === null ? "null"
772
+ : typeof attribute.value === "string" ? JSON.stringify(attribute.value)
773
+ : this.emitMappedExpression(attribute.value);
774
+ return `${JSON.stringify(property)}: ${value}`;
775
+ });
776
+ return `{ ${properties.join(", ")} }`;
777
+ }
778
+ prepareLooks(program) {
779
+ const rules = new Map();
780
+ const keyframeRules = new Map();
781
+ this.keyframeNames.clear();
782
+ const visit = (value) => {
783
+ if (!value || typeof value !== "object")
784
+ return;
785
+ const record = value;
786
+ if (record.kind === "ExtensionExpression:web:jsx") {
787
+ const element = record;
788
+ for (const attribute of element.attributes) {
789
+ if (!attribute.name.startsWith("look:"))
790
+ continue;
791
+ const name = attribute.name.slice("look:".length);
792
+ if (!LOOK_PROPERTIES.has(name))
793
+ continue;
794
+ const property = cssPropertyName(name);
795
+ const token = lookToken([], "", property);
796
+ rules.set(token, { token, property, target: "", staticAtoms: [] });
797
+ }
798
+ }
799
+ if (record.kind === "ExtensionExpression:web:look") {
800
+ const collect = (entries, contexts = [EMPTY_LOOK_TERM], target = "") => {
801
+ for (const entry of entries) {
802
+ if (entry.kind === "LookProperty") {
803
+ const property = cssPropertyName(entry.name);
804
+ for (const context of contexts) {
805
+ const token = lookToken(context.staticAtoms, target, property);
806
+ rules.set(token, { token, property, target, staticAtoms: context.staticAtoms });
807
+ }
808
+ }
809
+ else if (entry.kind === "LookIf") {
810
+ collect(entry.thenEntries, combineLookTerms(contexts, lookConditionTerms(entry.condition, false, this.lookStaticValues)), target);
811
+ collect(entry.elseEntries, combineLookTerms(contexts, lookConditionTerms(entry.condition, true, this.lookStaticValues)), target);
812
+ }
813
+ else if (entry.kind === "LookTarget") {
814
+ collect(entry.entries, contexts, entry.name);
815
+ }
816
+ }
817
+ };
818
+ collect(record.entries);
819
+ }
820
+ if (record.kind === "ExtensionExpression:web:keyframes") {
821
+ const expression = record;
822
+ const canonical = keyframesCanonical(expression, this.lookStaticValues);
823
+ const name = keyframesName(canonical);
824
+ this.keyframeNames.set(spanIdentity(expression.span), name);
825
+ if (!keyframeRules.has(name)) {
826
+ const stops = [...expression.stops]
827
+ .sort((left, right) => Math.min(...left.offsets) - Math.min(...right.offsets))
828
+ .map((stop) => {
829
+ const selectors = [...stop.offsets].sort((left, right) => left - right)
830
+ .map((offset) => offset === 0 ? "from" : offset === 100 ? "to" : `${offset}%`)
831
+ .join(",");
832
+ const declarations = stop.entries.map((entry) => {
833
+ const css = keyframeCssValue(entry.value, this.lookStaticValues);
834
+ return css === null ? "" : `${cssPropertyName(entry.name)}:${css}`;
835
+ }).filter(Boolean).join(";");
836
+ return `${selectors}{${declarations}}`;
837
+ }).join("");
838
+ keyframeRules.set(name, `@keyframes ${name}{${stops}}`);
839
+ }
840
+ }
841
+ for (const child of Object.values(record)) {
842
+ if (Array.isArray(child))
843
+ child.forEach(visit);
844
+ else
845
+ visit(child);
846
+ }
847
+ };
848
+ visit(program);
849
+ const lookCss = [];
850
+ for (const rule of rules.values()) {
851
+ const hookAtoms = rule.staticAtoms.filter((atom) => atom.kind === "hook");
852
+ const mediaAtoms = rule.staticAtoms.filter((atom) => atom.kind === "media" || atom.kind === "scheme" || atom.kind === "motion");
853
+ const base = `[data-velar-look~=${JSON.stringify(rule.token)}]${rule.staticAtoms.length > 0 ? "[data-velar-look]" : ""}`;
854
+ const selectors = lookSelectors(base, hookAtoms, rule.target);
855
+ const css = `${selectors.join(",")}{${lookDeclaration(rule.token, rule.property)}}`;
856
+ const query = mediaAtoms.map(lookMediaQuery).join(" and ");
857
+ lookCss.push(query ? `@media ${query}{${css}}` : css);
858
+ }
859
+ const before = [];
860
+ const after = [];
861
+ for (const statement of program.body) {
862
+ if (!isWebStatement(statement) || statement.kind !== "ExtensionStatement:web:unsafe-css")
863
+ continue;
864
+ const source = statement.source.kind === "inline"
865
+ ? statement.source.css
866
+ : this.resourceContents.get(statement.source.path) ?? "";
867
+ (statement.placement === "after" ? after : before).push(source.trim());
868
+ }
869
+ this.cssSegments = {
870
+ before: before.filter(Boolean).join("\n\n"),
871
+ controlled: [...keyframeRules.values(), ...lookCss].filter(Boolean).join("\n\n"),
872
+ after: after.filter(Boolean).join("\n\n"),
873
+ };
874
+ this.cssOutput = [this.cssSegments.before, this.cssSegments.controlled, this.cssSegments.after].filter(Boolean).join("\n\n");
875
+ if (this.cssOutput)
876
+ this.cssOutput += "\n";
877
+ }
878
+ }
879
+ function normalizeJsxText(value) {
880
+ const normalized = value.replace(/\s+/gu, " ");
881
+ if (!value.includes("\n"))
882
+ return normalized;
883
+ return (/^\s*\n/u.test(value) ? normalized.trimStart() : normalized).replace(/\n\s*$/u.test(value) ? /\s+$/u : /$^/u, "");
884
+ }
885
+ function hasMeaningfulChildren(children) {
886
+ return children.some((child) => child.kind !== "JSXText" || child.value.trim().length > 0);
887
+ }
888
+ // The keyed-children fast path is syntactic: an interpolation leaf must be
889
+ // exactly `source.map(single-parameter arrow returning JSX)`, keyed when the
890
+ // arrow's root element carries a `key` attribute. The analyzer mirrors this
891
+ // recognizer through dynamicChildLeaves, so anything the emitter demotes to a
892
+ // rebuild-all dynamic region is diagnosed rather than silently forfeited.
893
+ export function jsxKeyedList(expression) {
894
+ if (expression.kind !== "CallExpression" || expression.callee.kind !== "MemberExpression" || expression.callee.property !== "map")
895
+ return null;
896
+ const callback = expression.arguments[0];
897
+ if (!callback || callback.kind !== "ArrowFunctionExpression" || callback.asynchronous || callback.parameters.length !== 1 || callback.body.kind !== "ExtensionExpression:web:jsx")
898
+ return null;
899
+ const arrow = callback;
900
+ const key = arrow.body.attributes.find((attribute) => attribute.name === "key") ?? null;
901
+ return { source: expression.callee.object, arrow, key };
902
+ }
903
+ // Flattens an interpolation into render leaves. A conditional contributes its
904
+ // branch leaves, each remembering the chain of branch conditions that keeps it
905
+ // active, so an empty-state ternary around a keyed list still reaches the
906
+ // keyed fast path instead of demoting every child to rebuild-all updates.
907
+ export function dynamicChildLeaves(expression, guards = []) {
908
+ const list = jsxKeyedList(expression);
909
+ if (list)
910
+ return [{ expression, list, guards }];
911
+ if (expression.kind === "ConditionalExpression") {
912
+ return [
913
+ ...dynamicChildLeaves(expression.thenValue, [...guards, { condition: expression.condition, thenBranch: true }]),
914
+ ...dynamicChildLeaves(expression.elseValue, [...guards, { condition: expression.condition, thenBranch: false }]),
915
+ ];
916
+ }
917
+ return [{ expression, list: null, guards }];
918
+ }
919
+ const EMPTY_LOOK_TERM = Object.freeze({ staticAtoms: [], runtimeAtoms: [] });
920
+ const LOOK_CONDITION_TERM_LIMIT = 32;
921
+ function lookConditionTerms(expression, negated = false, staticValues = new Map()) {
922
+ if (expression.kind === "UnaryExpression" && expression.operator === "not")
923
+ return lookConditionTerms(expression.operand, !negated, staticValues);
924
+ if (expression.kind === "BinaryExpression" && (expression.operator === "and" || expression.operator === "or")) {
925
+ const conjunction = (expression.operator === "and") !== negated;
926
+ const left = lookConditionTerms(expression.left, negated, staticValues);
927
+ const right = lookConditionTerms(expression.right, negated, staticValues);
928
+ return conjunction ? combineLookTerms(left, right) : [...left, ...right].slice(0, LOOK_CONDITION_TERM_LIMIT);
929
+ }
930
+ if (isWebExpression(expression) && expression.kind === "ExtensionExpression:web:look-hook") {
931
+ return [{ staticAtoms: [{ kind: "hook", name: expression.name, negated }], runtimeAtoms: [] }];
932
+ }
933
+ const media = viewportAtom(expression, negated, staticValues) ?? schemeAtom(expression, negated);
934
+ if (media)
935
+ return [{ staticAtoms: [media], runtimeAtoms: [] }];
936
+ return [{ staticAtoms: [], runtimeAtoms: [{ expression, negated }] }];
937
+ }
938
+ function viewportAtom(expression, negated, staticValues) {
939
+ if (expression.kind !== "BinaryExpression" || !["<", "<=", ">", ">="].includes(expression.operator))
940
+ return null;
941
+ if (expression.left.kind !== "MemberExpression" || expression.left.object.kind !== "IdentifierExpression" || expression.left.object.name !== "viewport")
942
+ return null;
943
+ if (expression.left.property !== "width" && expression.left.property !== "height")
944
+ return null;
945
+ const threshold = evaluateLookStaticExpression(expression.right, staticValues);
946
+ if (threshold?.kind !== "unit" || !LOOK_MEDIA_LENGTH_UNITS.has(threshold.unit))
947
+ return null;
948
+ return {
949
+ kind: "media",
950
+ name: expression.left.property,
951
+ operator: expression.operator,
952
+ value: lookStaticCss(threshold),
953
+ negated,
954
+ };
955
+ }
956
+ // 'scheme.dark' / 'scheme.light' lower to prefers-color-scheme media atoms.
957
+ // The two subjects are complementary, so negation flips to the other scheme
958
+ // and the atom itself stays canonical.
959
+ function schemeAtom(expression, negated) {
960
+ if (expression.kind !== "MemberExpression" || expression.object.kind !== "IdentifierExpression")
961
+ return null;
962
+ // LOK-U3: 'motion.reduced' joins the media subjects. prefers-reduced-motion is
963
+ // complementary in the same way the schemes are, so negation names the other
964
+ // side of the query rather than wrapping it.
965
+ if (expression.object.name === "motion") {
966
+ return expression.property === "reduced" ? { kind: "motion", name: negated ? "no-preference" : "reduce", negated: false } : null;
967
+ }
968
+ if (expression.object.name !== "scheme")
969
+ return null;
970
+ if (expression.property !== "dark" && expression.property !== "light")
971
+ return null;
972
+ const scheme = negated ? (expression.property === "dark" ? "light" : "dark") : expression.property;
973
+ return { kind: "scheme", name: scheme, negated: false };
974
+ }
975
+ function combineLookTerms(left, right) {
976
+ const combined = [];
977
+ for (const first of left) {
978
+ for (const second of right) {
979
+ combined.push({
980
+ staticAtoms: [...first.staticAtoms, ...second.staticAtoms],
981
+ runtimeAtoms: [...first.runtimeAtoms, ...second.runtimeAtoms],
982
+ });
983
+ if (combined.length >= LOOK_CONDITION_TERM_LIMIT)
984
+ return combined;
985
+ }
986
+ }
987
+ return combined;
988
+ }
989
+ function lookToken(atoms, target, property) {
990
+ const conditions = atoms.map((atom) => {
991
+ if (atom.kind === "hook")
992
+ return `${atom.negated ? "not-" : ""}${kebab(atom.name)}`;
993
+ if (atom.kind === "scheme")
994
+ return `scheme-${atom.name}`;
995
+ if (atom.kind === "motion")
996
+ return `motion-${atom.name}`;
997
+ return `viewport-${atom.name}-${atom.negated ? "not-" : ""}${lookOperatorName(atom.operator)}-${atom.value}`;
998
+ }).sort();
999
+ const prefix = [target ? kebab(target) : "", conditions.length > 0 ? conditions.join("+") : "base"].filter(Boolean).join(":");
1000
+ return `${prefix}:${property}`;
1001
+ }
1002
+ function lookVariable(token) {
1003
+ return `--velar-look-${token.replace(/[^A-Za-z0-9_-]+/gu, "-")}`;
1004
+ }
1005
+ function lookDeclaration(token, property) {
1006
+ const value = `var(${lookVariable(token)})`;
1007
+ return `${property}:${value}`;
1008
+ }
1009
+ function lookOperatorName(operator) {
1010
+ return operator === "<" ? "lt" : operator === "<=" ? "lte" : operator === ">" ? "gt" : "gte";
1011
+ }
1012
+ function lookMediaQuery(atom) {
1013
+ if (atom.kind === "scheme")
1014
+ return `(prefers-color-scheme: ${atom.name})`;
1015
+ if (atom.kind === "motion")
1016
+ return `(prefers-reduced-motion: ${atom.name})`;
1017
+ const operator = atom.negated
1018
+ ? atom.operator === "<" ? ">=" : atom.operator === "<=" ? ">" : atom.operator === ">" ? "<=" : "<"
1019
+ : atom.operator;
1020
+ return `(${atom.name} ${operator} ${atom.value})`;
1021
+ }
1022
+ function lookSelectors(base, atoms, target) {
1023
+ let selectors = [base];
1024
+ for (const atom of atoms) {
1025
+ const states = lookHookSelectors(atom.name);
1026
+ if (atom.negated) {
1027
+ const condition = states.map((state) => `:not(${state})`).join("");
1028
+ selectors = selectors.map((selector) => `${selector}:where(${condition})`);
1029
+ }
1030
+ else {
1031
+ selectors = selectors.flatMap((selector) => states.map((state) => `${selector}:where(${state})`));
1032
+ }
1033
+ }
1034
+ const suffix = target ? LOOK_TARGET_SELECTORS.get(target) ?? `::${kebab(target)}` : "";
1035
+ return selectors.map((selector) => `${selector}${suffix}`);
1036
+ }
1037
+ function lookHookSelectors(name) {
1038
+ if (name === "focusVisible")
1039
+ return [":focus-visible"];
1040
+ if (name === "current")
1041
+ return ["[aria-current=\"page\"]"];
1042
+ if (name === "disabled")
1043
+ return [":disabled", "[aria-disabled=\"true\"]"];
1044
+ if (name === "checked")
1045
+ return [":checked", "[aria-checked=\"true\"]"];
1046
+ if (name === "invalid")
1047
+ return [":invalid", "[aria-invalid=\"true\"]"];
1048
+ if (name === "open")
1049
+ return [":open", "[open]", "[aria-expanded=\"true\"]"];
1050
+ return [`:${kebab(name)}`];
1051
+ }
1052
+ const LOOK_TARGET_SELECTORS = new Map([
1053
+ ["before", "::before"], ["after", "::after"], ["backdrop", "::backdrop"], ["placeholder", "::placeholder"], ["selection", "::selection"],
1054
+ ["marker", "::marker"], ["fileSelectorButton", "::file-selector-button"],
1055
+ ]);
1056
+ function kebab(value) {
1057
+ return value.replace(/[A-Z]/gu, (character) => `-${character.toLowerCase()}`);
1058
+ }
1059
+ function visitLookExpressions(entries, visit) {
1060
+ for (const entry of entries) {
1061
+ if (entry.kind === "LookProperty" || entry.kind === "LookSpread")
1062
+ visit(entry.value);
1063
+ else if (entry.kind === "LookIf") {
1064
+ visit(entry.condition);
1065
+ visitLookExpressions(entry.thenEntries, visit);
1066
+ visitLookExpressions(entry.elseEntries, visit);
1067
+ }
1068
+ else
1069
+ visitLookExpressions(entry.entries, visit);
1070
+ }
1071
+ }
1072
+ function containsUnitLiteral(value) {
1073
+ if (!value || typeof value !== "object")
1074
+ return false;
1075
+ const record = value;
1076
+ if (record.kind === "ExtensionExpression:web:unit")
1077
+ return true;
1078
+ for (const child of Object.values(record)) {
1079
+ if (Array.isArray(child)) {
1080
+ if (child.some(containsUnitLiteral))
1081
+ return true;
1082
+ }
1083
+ else if (containsUnitLiteral(child))
1084
+ return true;
1085
+ }
1086
+ return false;
1087
+ }
1088
+ function containsWebSyntax(value) {
1089
+ if (!value || typeof value !== "object")
1090
+ return false;
1091
+ const record = value;
1092
+ if (record.kind === "ExtensionStatement:web:component" || record.kind === "ExtensionStatement:web:expose" || record.kind === "ExtensionStatement:web:unsafe-css" || record.kind === "ExtensionExpression:web:look" || record.kind === "ExtensionExpression:web:keyframes" || record.kind === "ExtensionExpression:web:jsx"
1093
+ || record.kind === "ExtensionStatement:web:state" || record.kind === "ExtensionStatement:web:computed" || record.kind === "ExtensionStatement:web:resource" || record.kind === "ExtensionStatement:web:action" || record.kind === "ExtensionStatement:web:watch")
1094
+ return true;
1095
+ if (record.kind === "IdentifierExpression" && (record.name === "mount" || record.name === "tick" || record.name === "cached"))
1096
+ return true;
1097
+ return Object.values(record).some((child) => Array.isArray(child) ? child.some(containsWebSyntax) : containsWebSyntax(child));
1098
+ }
1099
+ const LOOK_ARITHMETIC_RUNTIME = String.raw `
1100
+ function __velarLookDimension(value) {
1101
+ if (typeof value !== "string") return null;
1102
+ const match = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(px|rem|em|vw|vh|vmin|vmax|%|fr|ms|s|deg|turn)$/.exec(value);
1103
+ if (!match) return null;
1104
+ const number = Number(match[1]);
1105
+ return Number.isFinite(number) ? { number, unit: match[2] } : null;
1106
+ }
1107
+
1108
+ function __velarLookNumber(value, label) {
1109
+ if (typeof value !== "number" || !Number.isFinite(value)) throw new TypeError(label + " must be a finite number");
1110
+ return value;
1111
+ }
1112
+
1113
+ function __velarLookDimensionResult(number, unit) {
1114
+ if (!Number.isFinite(number)) throw new RangeError("Look arithmetic must produce a finite value");
1115
+ return String(Object.is(number, -0) ? 0 : number) + unit;
1116
+ }
1117
+
1118
+ function __velarLookConvertibleDimension(value) {
1119
+ if (value.unit === "s") return { number: value.number * 1000, unit: "ms" };
1120
+ if (value.unit === "turn") return { number: value.number * 360, unit: "deg" };
1121
+ return value;
1122
+ }
1123
+
1124
+ function __velarLookUnary(operator, value) {
1125
+ if (typeof value === "number") return operator === "-" ? -__velarLookNumber(value, "Look operand") : __velarLookNumber(value, "Look operand");
1126
+ if (typeof value !== "string") throw new TypeError("Look unit arithmetic requires a number or typed visual value");
1127
+ if (operator === "+") return value;
1128
+ const dimension = __velarLookDimension(value);
1129
+ if (dimension) return __velarLookDimensionResult(-dimension.number, dimension.unit);
1130
+ return "calc(-1 * (" + value + "))";
1131
+ }
1132
+
1133
+ function __velarLookMath(operator, left, right) {
1134
+ if (typeof left === "number" && typeof right === "number") {
1135
+ const first = __velarLookNumber(left, "Left Look operand");
1136
+ const second = __velarLookNumber(right, "Right Look operand");
1137
+ if (operator === "/" && second === 0) throw new RangeError("Look division cannot use zero");
1138
+ const result = operator === "+" ? first + second : operator === "-" ? first - second : operator === "*" ? first * second : first / second;
1139
+ return __velarLookNumber(result, "Look arithmetic result");
1140
+ }
1141
+ const leftDimension = __velarLookDimension(left);
1142
+ const rightDimension = __velarLookDimension(right);
1143
+ if ((operator === "+" || operator === "-") && leftDimension && rightDimension) {
1144
+ const first = __velarLookConvertibleDimension(leftDimension);
1145
+ const second = __velarLookConvertibleDimension(rightDimension);
1146
+ if (first.unit === second.unit) {
1147
+ return __velarLookDimensionResult(operator === "+" ? first.number + second.number : first.number - second.number, first.unit);
1148
+ }
1149
+ }
1150
+ if (operator === "*" && leftDimension && typeof right === "number") {
1151
+ return __velarLookDimensionResult(leftDimension.number * __velarLookNumber(right, "Right Look operand"), leftDimension.unit);
1152
+ }
1153
+ if (operator === "*" && typeof left === "number" && rightDimension) {
1154
+ return __velarLookDimensionResult(__velarLookNumber(left, "Left Look operand") * rightDimension.number, rightDimension.unit);
1155
+ }
1156
+ if (operator === "/" && leftDimension && typeof right === "number") {
1157
+ const divisor = __velarLookNumber(right, "Right Look operand");
1158
+ if (divisor === 0) throw new RangeError("Look unit division cannot use zero");
1159
+ return __velarLookDimensionResult(leftDimension.number / divisor, leftDimension.unit);
1160
+ }
1161
+ if ((typeof left !== "string" && typeof left !== "number") || (typeof right !== "string" && typeof right !== "number")) {
1162
+ throw new TypeError("Look unit arithmetic requires numbers or typed visual values");
1163
+ }
1164
+ return "calc(" + left + " " + operator + " " + right + ")";
1165
+ }
1166
+ `.trimStart();
1167
+ const WEB_RUNTIME_BODY = String.raw `
1168
+ function __velarReport(value, phase, scope = null, detail = "", unhandled = true) {
1169
+ return __velarRuntime.report(value, { phase, detail, component: scope ? scope.component : "", unhandled });
1170
+ }
1171
+
1172
+ function __velarReportEvent(value, scope, detail) {
1173
+ if (__velarIsError(value) && __velarGraphWeakSetRemove(__velarRuntime.actionFailures, value)) return null;
1174
+ return __velarReport(value, "event", scope, detail);
1175
+ }
1176
+
1177
+ const __velarWebIterateKey = Symbol.for("velar.reactive.iterate.v1");
1178
+ const __velarWebNativeJson = globalThis.JSON;
1179
+ const __velarWebJsonText = Object.getOwnPropertyDescriptor(__velarWebNativeJson, "stringify")?.value;
1180
+ const __velarEventReflectApply = Object.getOwnPropertyDescriptor(Reflect, "apply")?.value;
1181
+ const __velarEventConstructorDescriptor = Object.getOwnPropertyDescriptor(globalThis, "Event");
1182
+ const __velarEventConstructor = __velarEventConstructorDescriptor && "value" in __velarEventConstructorDescriptor ? __velarEventConstructorDescriptor.value : null;
1183
+ const __velarEventPrototype = typeof __velarEventConstructor === "function" ? Object.getOwnPropertyDescriptor(__velarEventConstructor, "prototype")?.value : null;
1184
+ const __velarEventTargetGetter = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "target")?.get;
1185
+ const __velarEventPreventDefault = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "preventDefault")?.value;
1186
+ const __velarEventStopPropagation = __velarEventPrototype && Object.getOwnPropertyDescriptor(__velarEventPrototype, "stopPropagation")?.value;
1187
+ const __velarEventMissingField = __velarGraphFreeze({});
1188
+ function __velarQuotedText(value) {
1189
+ return __velarGraphApply(__velarWebJsonText, __velarWebNativeJson, [value], "JSON.stringify");
1190
+ }
1191
+ function __velarAppendOwned(values, value) {
1192
+ values[values.length] = value;
1193
+ return value;
1194
+ }
1195
+ function __velarHasName(values, name) {
1196
+ for (let index = 0; index < values.length; index += 1) if (values[index] === name) return true;
1197
+ return false;
1198
+ }
1199
+ function __velarEventField(value, name, nativeGetter) {
1200
+ if (typeof nativeGetter === "function" && typeof __velarEventReflectApply === "function") {
1201
+ try { return __velarEventReflectApply(nativeGetter, value, []); } catch {}
1202
+ }
1203
+ if (value === null || (typeof value !== "object" && typeof value !== "function")) return __velarEventMissingField;
1204
+ const descriptor = __velarGraphOwnDescriptor(value, name);
1205
+ return descriptor?.enumerable && "value" in descriptor ? descriptor.value : __velarEventMissingField;
1206
+ }
1207
+ function __velarEventCall(value, name, nativeMethod) {
1208
+ if (typeof nativeMethod === "function" && typeof __velarEventReflectApply === "function") {
1209
+ try { return __velarEventReflectApply(nativeMethod, value, []); } catch {}
1210
+ }
1211
+ const method = __velarEventField(value, name, null);
1212
+ if (typeof method !== "function" || typeof __velarEventReflectApply !== "function") throw new TypeError("DOM event does not expose native " + name);
1213
+ return __velarEventReflectApply(method, value, []);
1214
+ }
1215
+
1216
+ // This scheduler has a twin inside the runtime registry (runtime.schedule in
1217
+ // packages/web/src/runtime-foundation.ts) so registry-owned computed
1218
+ // observers schedule correctly no matter which module stamped the registry.
1219
+ // Both sides drain the same shared queues under the shared flushPending flag;
1220
+ // their budgets and overflow behavior must stay identical.
1221
+ function __velarSchedule(observer) {
1222
+ const queue = observer.mode === "watch" ? __velarRuntime.watchQueue : __velarRuntime.domQueue;
1223
+ if (!__velarGraphSetContains(queue, observer) && __velarGraphSetCount(queue) >= 100000) throw new RangeError("VelarScript reactive queues cannot exceed 100000 observers");
1224
+ __velarGraphSetInsert(queue, observer);
1225
+ if (!__velarRuntime.flushPending) {
1226
+ __velarRuntime.flushPending = true;
1227
+ __velarEnqueue(__velarFlush);
1228
+ }
1229
+ }
1230
+
1231
+ // Both queues are drained live: an observer that re-schedules itself or another
1232
+ // observer is picked up by the same walk. Two observers that invalidate each
1233
+ // other therefore never leave this function, which froze the page with nothing
1234
+ // on the error channel. The per-flush budget gives that case the same owned
1235
+ // ending as the single-observer cap: stop the observers still queued, report
1236
+ // once through velar/app, and let the turn finish.
1237
+ function __velarFlushOverflow() {
1238
+ const stalled = [];
1239
+ for (const observer of __velarGraphSetItems(__velarRuntime.domQueue)) stalled[stalled.length] = observer;
1240
+ for (const observer of __velarGraphSetItems(__velarRuntime.watchQueue)) stalled[stalled.length] = observer;
1241
+ __velarGraphSetEmpty(__velarRuntime.domQueue);
1242
+ __velarGraphSetEmpty(__velarRuntime.watchQueue);
1243
+ for (let index = 0; index < stalled.length; index += 1) {
1244
+ const observer = stalled[index];
1245
+ if (typeof observer.stop === "function") observer.stop();
1246
+ else observer.stopped = true;
1247
+ }
1248
+ __velarReport(new RangeError("Reactive updates cannot run more than 100000 observers in one flush"), "update", null);
1249
+ }
1250
+
1251
+ function __velarFlush() {
1252
+ __velarRuntime.flushPending = false;
1253
+ let budget = 100000;
1254
+ for (const observer of __velarGraphSetItems(__velarRuntime.domQueue)) {
1255
+ __velarGraphSetRemove(__velarRuntime.domQueue, observer);
1256
+ if ((budget -= 1) < 0) { __velarFlushOverflow(); return; }
1257
+ observer.run();
1258
+ }
1259
+ for (const observer of __velarGraphSetItems(__velarRuntime.watchQueue)) {
1260
+ __velarGraphSetRemove(__velarRuntime.watchQueue, observer);
1261
+ if ((budget -= 1) < 0) { __velarFlushOverflow(); return; }
1262
+ observer.run();
1263
+ }
1264
+ if (__velarGraphSetCount(__velarRuntime.domQueue) || __velarGraphSetCount(__velarRuntime.watchQueue)) __velarScheduleFlush();
1265
+ }
1266
+
1267
+ function __velarScheduleFlush() {
1268
+ if (!__velarRuntime.flushPending) { __velarRuntime.flushPending = true; __velarEnqueue(__velarFlush); }
1269
+ }
1270
+
1271
+ function __velarTrack(subscribers) {
1272
+ __velarRuntime.trackSubscribers(subscribers);
1273
+ }
1274
+
1275
+ function __velarToRaw(value) { return __velarRuntime.toRaw(value); }
1276
+ function __velarReactive(value, parent = null) { return __velarRuntime.reactive(value, parent); }
1277
+
1278
+ function __velarWebListPop(value, requested = -1) {
1279
+ return __velarReactive(__velarListPop(value, requested));
1280
+ }
1281
+
1282
+ function __velarUntracked(read) {
1283
+ const previous = __velarRuntime.activeObserver;
1284
+ __velarRuntime.activeObserver = null;
1285
+ try { return read(); } finally { __velarRuntime.activeObserver = previous; }
1286
+ }
1287
+
1288
+ function __velarCleanupObserver(observer) {
1289
+ __velarRuntime.cleanupObserver(observer);
1290
+ }
1291
+
1292
+ function __velarObserver(read, mode, scope) {
1293
+ // The first run of a DOM observer executes while its JSX position is being
1294
+ // constructed, and construction is transactional: the failure must reach
1295
+ // the surrounding owner (the mount transaction at the root, the containing
1296
+ // child position otherwise) so the promised fatal state or contained
1297
+ // placeholder appears instead of a silently empty region. Later runs are
1298
+ // updates; their failures are reported and the last valid DOM survives.
1299
+ let initial = mode === "dom";
1300
+ const observer = {
1301
+ mode,
1302
+ stopped: false,
1303
+ running: false,
1304
+ selfInvalidations: 0,
1305
+ dependencies: __velarGraphCreateSet(),
1306
+ run() {
1307
+ if (observer.stopped) return;
1308
+ observer.running = true;
1309
+ try { __velarRuntime.runTracked(observer, read); }
1310
+ catch (error) {
1311
+ if (initial) throw error;
1312
+ __velarReport(error, mode === "watch" ? "watch" : "render", scope);
1313
+ }
1314
+ finally {
1315
+ observer.running = false;
1316
+ initial = false;
1317
+ }
1318
+ },
1319
+ notify() {
1320
+ if (observer.stopped) return;
1321
+ if (observer.running) {
1322
+ observer.selfInvalidations += 1;
1323
+ if (observer.selfInvalidations > 100) {
1324
+ observer.stop();
1325
+ __velarReport(new RangeError("A reactive " + (mode === "watch" ? "watch" : "render") + " cannot invalidate itself more than 100 times"), mode === "watch" ? "watch" : "render", scope);
1326
+ return;
1327
+ }
1328
+ } else {
1329
+ observer.selfInvalidations = 0;
1330
+ }
1331
+ __velarSchedule(observer);
1332
+ },
1333
+ stop() { observer.stopped = true; __velarCleanupObserver(observer); },
1334
+ };
1335
+ __velarAppendOwned(scope.cleanups, () => observer.stop());
1336
+ observer.run();
1337
+ return observer;
1338
+ }
1339
+
1340
+ // D70 rule 180: a reactive source read during component setup and stored in a
1341
+ // plain binding is frozen. That is what const means, and a snapshot is a
1342
+ // legitimate thing to want -- so the report fires when the source *diverges*
1343
+ // from the snapshot, never when the snapshot is taken. A warning that fires on
1344
+ // correct code is a warning people learn to ignore; one that fires only after
1345
+ // the value on screen has actually gone stale cannot be wrong about that.
1346
+ //
1347
+ // The whole mechanism is installed only when the development host published its
1348
+ // hooks, so a production build pays nothing for it: no map, no stack capture,
1349
+ // and one already-false constant on the read path.
1350
+ // One module's copy of this runtime cannot own the state: a component in one
1351
+ // module reads a cell created in another, so the setup stack and the recorded
1352
+ // reads live on the shared hooks object every copy sees.
1353
+ const __velarFrozenHooks = (() => {
1354
+ const hooks = globalThis.__velarDevelopmentHooks;
1355
+ if (!hooks || typeof hooks.frozenRead !== "function") return null;
1356
+ if (hooks.setupScopes === undefined) {
1357
+ hooks.setupScopes = [];
1358
+ hooks.reads = __velarGraphCreateWeakMap();
1359
+ hooks.derived = [];
1360
+ hooks.internalDepth = 0;
1361
+ }
1362
+ return hooks;
1363
+ })();
1364
+ const __velarFrozenReadLimit = 32;
1365
+
1366
+ function __velarSetupBegin(scope) {
1367
+ if (__velarFrozenHooks) __velarAppendOwned(__velarFrozenHooks.setupScopes, scope);
1368
+ return scope;
1369
+ }
1370
+
1371
+ function __velarSetupEnd(value) {
1372
+ if (__velarFrozenHooks && __velarFrozenHooks.setupScopes.length > 0) __velarFrozenHooks.setupScopes.length -= 1;
1373
+ return value;
1374
+ }
1375
+
1376
+ // The framework's own reads on the author's behalf -- checking a prop is
1377
+ // present, capturing the one-time snapshot a runtime component documents,
1378
+ // reading a handler thunk. None of them freezes anything the author wrote: the
1379
+ // prop handle behind them stays live. Reporting them would be the false-positive
1380
+ // flood D70 rule 180 rejected, in its most literal form.
1381
+ function __velarInternalRead(read) {
1382
+ if (!__velarFrozenHooks) return __velarUntracked(read);
1383
+ __velarFrozenHooks.internalDepth += 1;
1384
+ try { return __velarUntracked(read); } finally { __velarFrozenHooks.internalDepth -= 1; }
1385
+ }
1386
+
1387
+ function __velarRecordFrozenRead(cell, value) {
1388
+ if (!__velarFrozenHooks) return;
1389
+ if (__velarFrozenHooks.setupScopes.length === 0 || __velarFrozenHooks.internalDepth > 0) return;
1390
+ if (__velarRuntime.activeObserver !== null) return;
1391
+ // Only a value the reader can show is worth naming in the report; an object
1392
+ // read out of setup is followed through the deep graph, not frozen by this
1393
+ // read, so recording it would produce a report about the wrong thing.
1394
+ if (value !== null && typeof value === "object") return;
1395
+ const scope = __velarFrozenHooks.setupScopes[__velarFrozenHooks.setupScopes.length - 1];
1396
+ const existing = __velarGraphWeakMapRead(__velarFrozenHooks.reads, cell);
1397
+ if (existing) {
1398
+ if (existing.length >= __velarFrozenReadLimit) return;
1399
+ __velarAppendOwned(existing, { value, scope, site: new Error("velar frozen read") });
1400
+ return;
1401
+ }
1402
+ __velarGraphWeakMapWrite(__velarFrozenHooks.reads, cell, [{ value, scope, site: new Error("velar frozen read") }]);
1403
+ }
1404
+
1405
+ // A derived value frozen during setup has no cell to hang a report on, and a
1406
+ // read that left no subscriber is a read the cache never tells anything about.
1407
+ // So the entries are kept in one dev-mode list and re-read after a state write
1408
+ // -- the only thing that can move a derived value -- which is the same
1409
+ // "report on divergence" rule the cells follow, reached the only way it can be.
1410
+ function __velarRecordFrozenDerived(access, value) {
1411
+ if (!__velarFrozenHooks) return;
1412
+ if (__velarFrozenHooks.setupScopes.length === 0 || __velarFrozenHooks.internalDepth > 0) return;
1413
+ if (__velarRuntime.activeObserver !== null) return;
1414
+ if (value !== null && typeof value === "object") return;
1415
+ if (__velarFrozenHooks.derived.length >= __velarFrozenReadLimit * 4) return;
1416
+ const scope = __velarFrozenHooks.setupScopes[__velarFrozenHooks.setupScopes.length - 1];
1417
+ __velarAppendOwned(__velarFrozenHooks.derived, { access, value, scope, site: new Error("velar frozen read") });
1418
+ }
1419
+
1420
+ function __velarReportFrozenDerived() {
1421
+ if (!__velarFrozenHooks || __velarFrozenHooks.derived.length === 0) return;
1422
+ const entries = __velarFrozenHooks.derived;
1423
+ const remaining = [];
1424
+ for (let index = 0; index < entries.length; index += 1) {
1425
+ const entry = entries[index];
1426
+ let current = entry.value;
1427
+ let failed = false;
1428
+ try { current = __velarUntracked(entry.access); }
1429
+ catch { failed = true; }
1430
+ if (failed || __velarGraphSame(entry.value, current)) { remaining[remaining.length] = entry; continue; }
1431
+ __velarPublishFrozenRead(entry, current);
1432
+ }
1433
+ __velarFrozenHooks.derived = remaining;
1434
+ }
1435
+
1436
+ function __velarReportFrozenReads(cell, next) {
1437
+ if (!__velarFrozenHooks) return;
1438
+ __velarReportFrozenDerived();
1439
+ const entries = __velarGraphWeakMapRead(__velarFrozenHooks.reads, cell);
1440
+ if (!entries) return;
1441
+ __velarGraphWeakMapRemove(__velarFrozenHooks.reads, cell);
1442
+ for (let index = 0; index < entries.length; index += 1) {
1443
+ if (__velarGraphSame(entries[index].value, next)) continue;
1444
+ __velarPublishFrozenRead(entries[index], next);
1445
+ }
1446
+ }
1447
+
1448
+ function __velarPublishFrozenRead(entry, next) {
1449
+ const component = entry.scope && entry.scope.component ? entry.scope.component : "a component";
1450
+ __velarFrozenHooks.frozenRead({
1451
+ message: "A reactive value read while " + component + " was being built was frozen at "
1452
+ + __velarFrozenText(entry.value) + ", and the source has now changed to " + __velarFrozenText(next)
1453
+ + ". Whatever was built from that read still shows the old value. If it is meant to follow, declare it with 'computed name = <expression>'; if the snapshot was intended, nothing here needs changing.",
1454
+ stack: __velarDomString(entry.site && entry.site.stack ? entry.site.stack : ""),
1455
+ });
1456
+ }
1457
+
1458
+ function __velarFrozenText(value) {
1459
+ return typeof value === "string" ? __velarQuotedText(value) : __velarDomString(value);
1460
+ }
1461
+
1462
+ function __velarState(initial) {
1463
+ let value = __velarToRaw(initial);
1464
+ const subscribers = __velarGraphCreateSet();
1465
+ const cell = {
1466
+ // Named rather than shorthand so a captured stack shows a compiler frame
1467
+ // here: D70's report walks past its own frames to find the reading line,
1468
+ // and every JavaScript engine spells an anonymous getter differently.
1469
+ get: function __velarCellRead() {
1470
+ __velarTrack(subscribers);
1471
+ const current = __velarReactive(value, cell);
1472
+ __velarRecordFrozenRead(cell, current);
1473
+ return current;
1474
+ },
1475
+ set(next) {
1476
+ next = __velarToRaw(next);
1477
+ if (__velarGraphSame(value, next)) return next;
1478
+ const previous = value;
1479
+ value = next;
1480
+ __velarReportFrozenReads(cell, next);
1481
+ // Keep deep-change bubbling attached only to the value currently owned
1482
+ // by this cell. Otherwise every replaced object remains linked to the
1483
+ // state cell and continues to occupy the parent graph indefinitely.
1484
+ __velarRuntime.collectionUnlink(cell, previous);
1485
+ __velarReactive(value, cell);
1486
+ for (const observer of __velarGraphSetItems(subscribers)) observer.notify();
1487
+ return next;
1488
+ },
1489
+ };
1490
+ __velarReactive(value, cell);
1491
+ return cell;
1492
+ }
1493
+
1494
+ // D71 rule 182: a declared derived value reads bare, so it presents the same
1495
+ // .get() face a state cell does. The cache underneath is the same one
1496
+ // the cached reader returns; only the way it is read differs.
1497
+ function __velarComputed(read) {
1498
+ const access = __velarRuntime.computed(read);
1499
+ if (!__velarFrozenHooks) return __velarGraphFreeze({ get: access });
1500
+ return __velarGraphFreeze({
1501
+ get: function __velarDerivedRead() {
1502
+ const value = access();
1503
+ __velarRecordFrozenDerived(access, value);
1504
+ return value;
1505
+ },
1506
+ });
1507
+ }
1508
+
1509
+ const __velarManagedAsyncNativePromise = globalThis.Promise;
1510
+ const __velarManagedAsyncPromisePrototype = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "prototype")?.value;
1511
+ const __velarManagedAsyncResolveOperation = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "resolve")?.value;
1512
+ const __velarManagedAsyncRejectOperation = __velarGraphOwnDescriptor(__velarManagedAsyncNativePromise, "reject")?.value;
1513
+ const __velarManagedAsyncThenOperation = __velarManagedAsyncPromisePrototype
1514
+ ? __velarGraphOwnDescriptor(__velarManagedAsyncPromisePrototype, "then")?.value
1515
+ : null;
1516
+ function __velarManagedAsyncResolve(value) {
1517
+ return __velarGraphApply(__velarManagedAsyncResolveOperation, __velarManagedAsyncNativePromise, [value], "Promise.resolve");
1518
+ }
1519
+ function __velarManagedAsyncReject(error) {
1520
+ return __velarGraphApply(__velarManagedAsyncRejectOperation, __velarManagedAsyncNativePromise, [error], "Promise.reject");
1521
+ }
1522
+ function __velarManagedAsyncThen(value, fulfilled, rejected) {
1523
+ return __velarGraphApply(__velarManagedAsyncThenOperation, value, [fulfilled, rejected], "Promise.then");
1524
+ }
1525
+ function __velarManagedAsyncCreate(executor) {
1526
+ if (typeof __velarManagedAsyncNativePromise !== "function") throw new TypeError("The JavaScript Promise API is unavailable");
1527
+ return new __velarManagedAsyncNativePromise(executor);
1528
+ }
1529
+
1530
+ function __velarResource(load, scope, name) {
1531
+ const value = __velarState(null);
1532
+ const loading = __velarState(true);
1533
+ const ready = __velarState(false);
1534
+ const error = __velarState(null);
1535
+ let generation = 0;
1536
+ let started = false;
1537
+ let disposed = false;
1538
+
1539
+ const reload = () => {
1540
+ if (disposed) return __velarManagedAsyncResolve(null);
1541
+ started = true;
1542
+ const current = ++generation;
1543
+ loading.set(true);
1544
+ error.set(null);
1545
+ return __velarManagedAsyncThen(__velarManagedAsyncThen(__velarManagedAsyncResolve(), load),
1546
+ (next) => {
1547
+ if (disposed || current !== generation) return null;
1548
+ value.set(next);
1549
+ ready.set(true);
1550
+ loading.set(false);
1551
+ return null;
1552
+ },
1553
+ (failure) => {
1554
+ if (disposed || current !== generation) return null;
1555
+ const report = __velarRuntime.report(failure, { phase: "resource", detail: name, component: scope.component, unhandled: false });
1556
+ error.set(report.error);
1557
+ ready.set(true);
1558
+ loading.set(false);
1559
+ return null;
1560
+ },
1561
+ );
1562
+ };
1563
+
1564
+ __velarAppendOwned(scope.mounts, () => started ? null : reload());
1565
+ __velarAppendOwned(scope.cleanups, () => { disposed = true; generation += 1; });
1566
+ return __velarGraphFreeze({
1567
+ get value() { return value.get(); },
1568
+ get loading() { return loading.get(); },
1569
+ get ready() { return ready.get(); },
1570
+ get error() { return error.get(); },
1571
+ reload,
1572
+ });
1573
+ }
1574
+
1575
+ function __velarAction(execute, scope, name) {
1576
+ const pending = __velarState(false);
1577
+ const error = __velarState(null);
1578
+ let active = 0;
1579
+ let generation = 0;
1580
+ let disposed = false;
1581
+
1582
+ const run = (...arguments_) => {
1583
+ if (disposed) return __velarManagedAsyncReject(__velarNormalizeError(
1584
+ "Action '" + name + "' cannot run after its component is destroyed",
1585
+ ));
1586
+ const current = ++generation;
1587
+ active += 1;
1588
+ pending.set(true);
1589
+ error.set(null);
1590
+ return __velarManagedAsyncThen(__velarManagedAsyncThen(__velarManagedAsyncResolve(), () => __velarGraphApply(execute, null, arguments_, "action body")),
1591
+ (value) => {
1592
+ active -= 1;
1593
+ if (!disposed) pending.set(active > 0);
1594
+ return value;
1595
+ },
1596
+ (failure) => {
1597
+ active -= 1;
1598
+ let actionError = __velarNormalizeError(failure);
1599
+ if (!disposed) {
1600
+ pending.set(active > 0);
1601
+ // Every action failure reports exactly once, through the action
1602
+ // phase, carrying the action's name as its detail -- including a
1603
+ // failure superseded by a newer call. Only the newest generation
1604
+ // owns the public error field. The actionFailures mark lets the
1605
+ // event and detached observers of the same rejection skip an
1606
+ // already-reported failure instead of reporting it a second time.
1607
+ const report = __velarRuntime.report(failure, { phase: "action", detail: name, component: scope.component, unhandled: false });
1608
+ actionError = report.error;
1609
+ __velarGraphWeakSetInsert(__velarRuntime.actionFailures, actionError);
1610
+ if (current === generation) error.set(report.error);
1611
+ }
1612
+ throw actionError;
1613
+ },
1614
+ );
1615
+ };
1616
+
1617
+ __velarGraphDefine(run, "pending", { enumerable: true, get: () => pending.get() });
1618
+ __velarGraphDefine(run, "error", { enumerable: true, get: () => error.get() });
1619
+ __velarAppendOwned(scope.cleanups, () => { disposed = true; generation += 1; });
1620
+ return __velarGraphFreeze(run);
1621
+ }
1622
+
1623
+ function __velarScope(component = "") {
1624
+ return { cleanups: [], mounts: [], mounted: false, component };
1625
+ }
1626
+
1627
+ const __velarGlobalScope = __velarScope();
1628
+
1629
+ function __velarMountScope(scope) {
1630
+ if (scope.mounted) return;
1631
+ scope.mounted = true;
1632
+ for (let index = 0; index < scope.mounts.length; index += 1) {
1633
+ try {
1634
+ const result = __velarUntracked(scope.mounts[index]);
1635
+ __velarObservePromise(result, (error) => __velarReport(error, "mounted", scope));
1636
+ } catch (error) { __velarReport(error, "mounted", scope); }
1637
+ }
1638
+ }
1639
+
1640
+ function __velarDestroyScope(scope) {
1641
+ for (let index = scope.cleanups.length - 1; index >= 0; index -= 1) {
1642
+ // A reentrant destroy can empty the list underneath this walk; a missing
1643
+ // slot means the step already ran and must not run again.
1644
+ const cleanup = scope.cleanups[index];
1645
+ if (typeof cleanup !== "function") continue;
1646
+ try {
1647
+ const result = __velarUntracked(cleanup);
1648
+ __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
1649
+ } catch (error) { __velarReport(error, "cleanup", scope); }
1650
+ }
1651
+ scope.cleanups.length = 0;
1652
+ }
1653
+
1654
+ function __velarCleanupStep(run, scope) {
1655
+ try {
1656
+ const result = __velarUntracked(run);
1657
+ __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
1658
+ } catch (error) { __velarReport(error, "cleanup", scope); }
1659
+ }
1660
+
1661
+ function __velarWatch(read, callback, scope) {
1662
+ let current;
1663
+ let currentVersion = 0;
1664
+ let initialized = false;
1665
+ __velarObserver(() => {
1666
+ const next = read();
1667
+ __velarRuntime.trackDeep(next);
1668
+ const nextVersion = __velarRuntime.versionOf(next);
1669
+ if (initialized && (!__velarGraphSame(next, current) || nextVersion !== currentVersion)) callback(next, current);
1670
+ current = next;
1671
+ currentVersion = nextVersion;
1672
+ initialized = true;
1673
+ }, "watch", scope);
1674
+ }
1675
+
1676
+ function __velarComponentHandle(value, componentName) {
1677
+ if (value === null || typeof value !== "object") throw new TypeError("Component " + componentName + " must expose an ordinary Handle record");
1678
+ const prototype = __velarGraphPrototype(value);
1679
+ if (prototype !== __velarGraphPrototype({}) && prototype !== null) throw new TypeError("Component " + componentName + " must expose an ordinary Handle record");
1680
+ const output = {};
1681
+ let active = true;
1682
+ const names = __velarGraphOwnNames(value);
1683
+ for (let index = 0; index < names.length; index += 1) {
1684
+ const name = names[index];
1685
+ const descriptor = __velarGraphOwnDescriptor(value, name);
1686
+ if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) throw new TypeError("Component " + componentName + " Handle fields must be enumerable data values");
1687
+ const member = typeof descriptor.value === "function"
1688
+ ? (...arguments_) => {
1689
+ if (!active) throw new Error("Component " + componentName + " Handle is no longer active");
1690
+ return __velarGraphApply(descriptor.value, null, arguments_, "component Handle method");
1691
+ }
1692
+ : descriptor.value;
1693
+ __velarGraphDefine(output, name, { enumerable: true, value: member });
1694
+ }
1695
+ return __velarGraphFreeze({
1696
+ value: __velarGraphFreeze(output),
1697
+ revoke() { active = false; },
1698
+ });
1699
+ }
1700
+
1701
+ function __velarComponent(node, scope, mounted, cleanup, handleState) {
1702
+ let destroyed = false;
1703
+ const refCleanups = [];
1704
+ const ownedNodes = node && __velarDomNodeType(node) === 11 ? __velarDomChildNodes(node) : [node];
1705
+ if (mounted) __velarAppendOwned(scope.mounts, mounted);
1706
+ return {
1707
+ __velarComponent: true,
1708
+ node,
1709
+ __bindRef(setRef) {
1710
+ if (!handleState) throw new TypeError("This component does not expose a Handle");
1711
+ const handle = handleState.value;
1712
+ let bound = true;
1713
+ setRef(handle, undefined);
1714
+ __velarAppendOwned(refCleanups, () => {
1715
+ if (!bound) return;
1716
+ bound = false;
1717
+ setRef(null, handle);
1718
+ });
1719
+ return null;
1720
+ },
1721
+ mount(target, before = null) {
1722
+ if (destroyed) throw new Error("Cannot mount a destroyed VelarScript component");
1723
+ if (scope.mounted) throw new Error("Cannot mount a VelarScript component more than once");
1724
+ const parent = typeof target === "string" ? __velarDomQuerySelector(target) : target;
1725
+ if (!parent) throw new Error("VelarScript mount target was not found");
1726
+ __velarDomInsertBefore(parent, node, before);
1727
+ __velarMountScope(scope);
1728
+ return null;
1729
+ },
1730
+ __mount() { if (!destroyed) __velarMountScope(scope); },
1731
+ destroy(remove = true) {
1732
+ if (destroyed) return null;
1733
+ destroyed = true;
1734
+ for (let index = refCleanups.length - 1; index >= 0; index -= 1) refCleanups[index]();
1735
+ refCleanups.length = 0;
1736
+ if (handleState) handleState.revoke();
1737
+ if (cleanup) {
1738
+ try {
1739
+ const result = __velarUntracked(cleanup);
1740
+ __velarObservePromise(result, (error) => __velarReport(error, "cleanup", scope));
1741
+ } catch (error) { __velarReport(error, "cleanup", scope); }
1742
+ }
1743
+ __velarDestroyScope(scope);
1744
+ if (remove) for (let index = 0; index < ownedNodes.length; index += 1) __velarDomRemove(ownedNodes[index]);
1745
+ return null;
1746
+ },
1747
+ };
1748
+ }
1749
+
1750
+ function __velarScopeComponentRoot(node, attribute) {
1751
+ if (!attribute || !node) return;
1752
+ if (__velarDomNodeType(node) === 1) {
1753
+ __velarDomSetAttribute(node, attribute, "");
1754
+ return;
1755
+ }
1756
+ if (__velarDomNodeType(node) === 11) {
1757
+ const children = __velarDomChildNodes(node);
1758
+ for (let index = 0; index < children.length; index += 1) {
1759
+ if (__velarDomNodeType(children[index]) === 1) __velarDomSetAttribute(children[index], attribute, "");
1760
+ }
1761
+ }
1762
+ }
1763
+
1764
+ function __velarUseComponent(instance, scope, parentStyleScope = "") {
1765
+ __velarScopeComponentRoot(instance.node, parentStyleScope);
1766
+ __velarAppendOwned(scope.mounts, () => instance.__mount());
1767
+ __velarAppendOwned(scope.cleanups, () => instance.destroy(false));
1768
+ return instance.node;
1769
+ }
1770
+
1771
+ function __velarFatal(parent, error) {
1772
+ const fallback = __velarDomCreateElement("section");
1773
+ __velarDomSetAttribute(fallback, "role", "alert");
1774
+ __velarDomSetAttribute(fallback, "data-velar-fatal", "");
1775
+ __velarDomSetText(fallback, "The application could not start: " + error.message);
1776
+ __velarDomReplaceChildren(parent, fallback);
1777
+ }
1778
+
1779
+ function __velarMount(evaluate, fallbackTarget = null) {
1780
+ let values;
1781
+ try {
1782
+ values = evaluate();
1783
+ } catch (failure) {
1784
+ const report = __velarReport(failure, "mount", null);
1785
+ if (fallbackTarget !== null) {
1786
+ try {
1787
+ const fallback = __velarDomQuerySelector(fallbackTarget);
1788
+ if (fallback) __velarFatal(fallback, report.error);
1789
+ } catch {}
1790
+ }
1791
+ return null;
1792
+ }
1793
+ const value = values[0];
1794
+ const target = values[1];
1795
+ const parent = typeof target === "string" ? __velarDomQuerySelector(target) : target;
1796
+ if (!parent) {
1797
+ // A missing mount target must keep the no-blank-page promise in every
1798
+ // build: the failure is reported through velar/app and the fatal state
1799
+ // renders into the document body, since the requested target is exactly
1800
+ // what does not exist.
1801
+ const report = __velarReport(new Error("VelarScript mount target was not found"), "mount", null);
1802
+ try {
1803
+ const body = __velarDomQuerySelector("body");
1804
+ if (body) __velarFatal(body, report.error);
1805
+ } catch {}
1806
+ return null;
1807
+ }
1808
+ try {
1809
+ if (value && value.__velarComponent) {
1810
+ const result = value.mount(parent);
1811
+ if (__velarGraphIsList(globalThis.__velarHotDisposers)) __velarAppendOwned(globalThis.__velarHotDisposers, () => value.destroy());
1812
+ return result;
1813
+ }
1814
+ __velarAppend(parent, value);
1815
+ __velarMountScope(__velarGlobalScope);
1816
+ return null;
1817
+ } catch (failure) {
1818
+ const report = __velarReport(failure, "mount", null);
1819
+ __velarFatal(parent, report.error);
1820
+ return null;
1821
+ }
1822
+ }
1823
+
1824
+ const __velarSvgNamespace = "http://www.w3.org/2000/svg";
1825
+ const __velarXlinkNamespace = "http://www.w3.org/1999/xlink";
1826
+ const __velarXmlNamespace = "http://www.w3.org/XML/1998/namespace";
1827
+
1828
+ function __velarCreateElement(tag, namespace) {
1829
+ return namespace === "svg" || tag === "svg"
1830
+ ? __velarDomCreateElementNS(__velarSvgNamespace, tag)
1831
+ : __velarDomCreateElement(tag);
1832
+ }
1833
+
1834
+ function __velarListSnapshot(value, name) {
1835
+ value = __velarToRaw(value);
1836
+ __velarRuntime.collectionRead(value, __velarWebIterateKey, undefined);
1837
+ return __velarDomListSnapshot(value, name);
1838
+ }
1839
+
1840
+ function __velarAppend(parent, value, state = null) {
1841
+ state ??= { active: __velarDomCreateSet(), depth: 0, values: 0, text: 0 };
1842
+ if (value == null || value === false || value === true) return;
1843
+ state.values += 1;
1844
+ if (state.values > 1000000) throw new RangeError("JSX cannot render more than 1000000 values");
1845
+ if (typeof value === "string") {
1846
+ state.text += value.length;
1847
+ if (state.text > 16 * 1024 * 1024) throw new RangeError("JSX text cannot exceed 16 MiB");
1848
+ __velarDomAppend(parent, __velarDomCreateTextNode(value));
1849
+ return;
1850
+ }
1851
+ if (typeof value === "number") {
1852
+ if (!__velarDomIsFinite(value)) throw new TypeError("JSX numbers must be finite");
1853
+ __velarDomAppend(parent, __velarDomCreateTextNode(__velarDomString(value)));
1854
+ return;
1855
+ }
1856
+ if (__velarDomIsNode(value)) { __velarDomAppend(parent, value); return; }
1857
+ if (__velarDomIsArray(value)) {
1858
+ if (state.depth >= 128) throw new RangeError("JSX Lists cannot exceed 128 nested levels");
1859
+ if (__velarDomSetContains(state.active, value)) throw new TypeError("JSX cannot render a cyclic List");
1860
+ const values = __velarListSnapshot(value, "JSX children");
1861
+ __velarDomSetInsert(state.active, value);
1862
+ state.depth += 1;
1863
+ try {
1864
+ for (let index = 0; index < values.length; index += 1) __velarAppend(parent, values[index], state);
1865
+ } finally {
1866
+ state.depth -= 1;
1867
+ __velarDomSetRemove(state.active, value);
1868
+ }
1869
+ return;
1870
+ }
1871
+ throw new TypeError("JSX can render only text, finite numbers, bool, enums, WebNode values, and Lists of those values");
1872
+ }
1873
+
1874
+ function __velarDynamic(parent, read, scope, rootState = null) {
1875
+ const start = __velarDomCreateComment("velar:start");
1876
+ const end = __velarDomCreateComment("velar:end");
1877
+ __velarDomAppend(parent, start, end);
1878
+ let nodes = [];
1879
+ let childScope = null;
1880
+ __velarAppendOwned(scope.mounts, () => { if (childScope) __velarMountScope(childScope); });
1881
+ __velarObserver(() => {
1882
+ const nextScope = __velarScope(scope.component);
1883
+ const fragment = __velarDomCreateFragment();
1884
+ let nextHost = null;
1885
+ try {
1886
+ __velarAppend(fragment, read(nextScope));
1887
+ if (rootState) nextHost = __velarRootHost(fragment, "dynamic component");
1888
+ }
1889
+ catch (error) { __velarDestroyScope(nextScope); throw error; }
1890
+ const nextNodes = __velarDomChildNodes(fragment);
1891
+ if (childScope) __velarDestroyScope(childScope);
1892
+ for (let index = 0; index < nodes.length; index += 1) __velarDomRemove(nodes[index]);
1893
+ __velarDomBefore(end, fragment);
1894
+ childScope = nextScope;
1895
+ nodes = nextNodes;
1896
+ if (rootState) {
1897
+ rootState.host = nextHost;
1898
+ for (const listener of __velarGraphSetItems(rootState.listeners)) listener(nextHost);
1899
+ }
1900
+ if (scope.mounted) __velarMountScope(nextScope);
1901
+ }, "dom", scope);
1902
+ __velarAppendOwned(scope.cleanups, () => {
1903
+ if (childScope) __velarDestroyScope(childScope);
1904
+ for (let index = 0; index < nodes.length; index += 1) __velarDomRemove(nodes[index]);
1905
+ nodes = [];
1906
+ if (rootState) {
1907
+ rootState.host = null;
1908
+ for (const listener of __velarGraphSetItems(rootState.listeners)) listener(null);
1909
+ }
1910
+ });
1911
+ }
1912
+
1913
+ function __velarDynamicComponent(read, scope) {
1914
+ const fragment = __velarDomCreateFragment();
1915
+ const rootState = { host: null, listeners: __velarGraphCreateSet() };
1916
+ __velarGraphDefine(fragment, "__velarDynamicRoot", { value: rootState });
1917
+ __velarDynamic(fragment, read, scope, rootState);
1918
+ return fragment;
1919
+ }
1920
+
1921
+ function __velarKeyed(parent, read, keyOf, render, scope) {
1922
+ const start = __velarDomCreateComment("velar:keyed-start");
1923
+ const end = __velarDomCreateComment("velar:keyed-end");
1924
+ __velarDomAppend(parent, start, end);
1925
+ let entries = __velarGraphCreateMap();
1926
+ __velarAppendOwned(scope.mounts, () => { for (const entry of __velarGraphMapItems(entries)) __velarMountScope(entry.scope); });
1927
+ __velarObserver(() => {
1928
+ const source = __velarToRaw(read() ?? []);
1929
+ const values = __velarListSnapshot(source, "Keyed JSX");
1930
+ const next = __velarGraphCreateMap();
1931
+ const created = [];
1932
+ try {
1933
+ for (let index = 0; index < values.length; index += 1) {
1934
+ const rawValue = __velarToRaw(values[index]);
1935
+ // The keyed source may be a fresh derived List on every render. A row
1936
+ // is observed directly by its child scope, so linking it to that
1937
+ // ephemeral container only retains dead Lists and slows later writes.
1938
+ const trackedValue = __velarReactive(rawValue);
1939
+ const key = __velarKey(keyOf(trackedValue));
1940
+ if (__velarGraphMapContains(next, key)) throw new Error("Duplicate JSX key '" + (typeof key === "string" ? key : __velarDomString(key)) + "'");
1941
+ let entry = __velarGraphMapRead(entries, key);
1942
+ if (entry && !__velarGraphSame(entry.value, rawValue)) entry = undefined;
1943
+ if (!entry) {
1944
+ const childScope = __velarScope(scope.component);
1945
+ const fragment = __velarDomCreateFragment();
1946
+ try { __velarAppend(fragment, render(trackedValue, childScope)); }
1947
+ catch (error) { __velarDestroyScope(childScope); throw error; }
1948
+ entry = { value: rawValue, scope: childScope, nodes: __velarDomChildNodes(fragment), fragment };
1949
+ created[created.length] = entry;
1950
+ }
1951
+ __velarGraphMapWrite(next, key, entry);
1952
+ }
1953
+ } catch (error) {
1954
+ for (let index = 0; index < created.length; index += 1) __velarDestroyScope(created[index].scope);
1955
+ throw error;
1956
+ }
1957
+ for (const key of __velarGraphMapKeyItems(entries)) {
1958
+ const entry = __velarGraphMapRead(entries, key);
1959
+ if (__velarGraphMapRead(next, key) === entry) continue;
1960
+ __velarDestroyScope(entry.scope);
1961
+ for (let index = 0; index < entry.nodes.length; index += 1) __velarDomRemove(entry.nodes[index]);
1962
+ }
1963
+ // A row already standing in its final position must not be detached and
1964
+ // reattached: that moves focus off a live <input>, ends IME composition,
1965
+ // and resets transient subtree state. The cursor walks the surviving nodes
1966
+ // in order and only moves a node that is not already where it belongs.
1967
+ let cursor = __velarDomNextSibling(start);
1968
+ for (const entry of __velarGraphMapItems(next)) {
1969
+ if (entry.fragment) {
1970
+ __velarDomBefore(cursor === null ? end : cursor, entry.fragment);
1971
+ entry.fragment = null;
1972
+ if (scope.mounted) __velarMountScope(entry.scope);
1973
+ continue;
1974
+ }
1975
+ for (let index = 0; index < entry.nodes.length; index += 1) {
1976
+ const node = entry.nodes[index];
1977
+ if (node === cursor) cursor = __velarDomNextSibling(cursor);
1978
+ else __velarDomBefore(cursor === null ? end : cursor, node);
1979
+ }
1980
+ }
1981
+ entries = next;
1982
+ }, "dom", scope);
1983
+ __velarAppendOwned(scope.cleanups, () => {
1984
+ for (const entry of __velarGraphMapItems(entries)) __velarDestroyScope(entry.scope);
1985
+ __velarGraphMapEmpty(entries);
1986
+ });
1987
+ }
1988
+
1989
+ // ARIA states are literal 'true'/'false' tokens, not HTML boolean attributes.
1990
+ // Presence/absence is how 'disabled' and 'checked' mean; an ARIA attribute set
1991
+ // to the empty string is an invalid token that the user agent reads as the
1992
+ // attribute's default -- which for aria-busy, aria-pressed, aria-expanded, and
1993
+ // their kin is false. So a false bool must stay on the element as the literal
1994
+ // text rather than being removed (D61 rule 155).
1995
+ function __velarAriaState(name) {
1996
+ return name.length > 5 && name.charCodeAt(0) === 97 && name.slice(0, 5) === "aria-";
1997
+ }
1998
+
1999
+ function __velarStaticAttr(element, name, value) {
2000
+ if (value === false && __velarAriaState(name)) { __velarSetAttribute(element, name, "false"); return; }
2001
+ if (value === false || value == null) return;
2002
+ __velarSetAttribute(element, name, __velarAttributeValue(value, name));
2003
+ }
2004
+
2005
+ function __velarAttr(element, name, read, scope) {
2006
+ __velarObserver(() => {
2007
+ const value = read();
2008
+ if (value === false && __velarAriaState(name)) __velarSetAttribute(element, name, "false");
2009
+ else if (value == null || value === false) __velarRemoveAttribute(element, name);
2010
+ else __velarSetAttribute(element, name, __velarAttributeValue(value, name));
2011
+ }, "dom", scope);
2012
+ }
2013
+
2014
+ function __velarAttributeValue(value, name) {
2015
+ if (value === true) return __velarAriaState(name) ? "true" : "";
2016
+ if (typeof value === "number") {
2017
+ if (!__velarDomIsFinite(value)) throw new TypeError("JSX attribute '" + name + "' requires a finite number");
2018
+ return __velarDomString(value);
2019
+ }
2020
+ if (typeof value !== "string") throw new TypeError("JSX attribute '" + name + "' requires text, a finite number, bool, an enum, or null");
2021
+ if (value.length > 1024 * 1024) throw new RangeError("JSX attribute '" + name + "' cannot exceed 1 MiB");
2022
+ return value;
2023
+ }
2024
+
2025
+ function __velarKey(value) {
2026
+ if (typeof value === "number") {
2027
+ if (!__velarDomIsFinite(value)) throw new TypeError("A JSX key number must be finite");
2028
+ return value;
2029
+ }
2030
+ if (typeof value !== "string") throw new TypeError("A JSX key must be a string, string-backed enum, or finite number");
2031
+ if (value.length > 65536) throw new RangeError("A JSX key cannot exceed 65536 characters");
2032
+ return value;
2033
+ }
2034
+
2035
+ function __velarSetAttribute(element, name, value) {
2036
+ if (name.startsWith("xlink:")) __velarDomSetAttributeNS(element, __velarXlinkNamespace, name, value);
2037
+ else if (name.startsWith("xml:")) __velarDomSetAttributeNS(element, __velarXmlNamespace, name, value);
2038
+ else __velarDomSetAttribute(element, name, value);
2039
+ }
2040
+
2041
+ function __velarRemoveAttribute(element, name) {
2042
+ if (name.startsWith("xlink:")) __velarDomRemoveAttributeNS(element, __velarXlinkNamespace, name.slice(6));
2043
+ else if (name.startsWith("xml:")) __velarDomRemoveAttributeNS(element, __velarXmlNamespace, name.slice(4));
2044
+ else __velarDomRemoveAttribute(element, name);
2045
+ }
2046
+
2047
+ function __velarClass(element, name, read, scope) {
2048
+ __velarClassBind(element, () => read() ? name : null, scope);
2049
+ }
2050
+
2051
+ function __velarMergeRules(rules, source) {
2052
+ const names = __velarGraphOwnNames(source);
2053
+ for (let index = 0; index < names.length; index += 1) {
2054
+ const descriptor = __velarGraphOwnDescriptor(source, names[index]);
2055
+ if (!descriptor || !("value" in descriptor)) continue;
2056
+ if (descriptor.value == null) delete rules[names[index]];
2057
+ else rules[names[index]] = descriptor.value;
2058
+ }
2059
+ }
2060
+
2061
+ function __velarLook(parts) {
2062
+ const rules = __velarGraphCreateRecord();
2063
+ const add = (part) => {
2064
+ if (part == null || part === false) return;
2065
+ if (__velarGraphIsList(part)) { for (let index = 0; index < part.length; index += 1) add(part[index]); return; }
2066
+ if (part.__velarLook === true || (part.rules && typeof part.rules === "object")) {
2067
+ __velarMergeRules(rules, part.rules);
2068
+ return;
2069
+ }
2070
+ throw new TypeError("look composition accepts only Look, Look?, or lists of Look values");
2071
+ };
2072
+ add(parts);
2073
+ return __velarGraphFreeze({ __velarLook: true, rules: __velarGraphFreeze(rules) });
2074
+ }
2075
+
2076
+ function __velarKeyframesValue(name) {
2077
+ if (typeof name !== "string" || !/^velar-kf-[0-9a-f]{8}$/.test(name)) throw new TypeError("Generated keyframes name is invalid");
2078
+ return __velarGraphFreeze({ __velarKeyframes: true, name });
2079
+ }
2080
+
2081
+ function __velarLookVariable(token) {
2082
+ return "--velar-look-" + token.replace(/[^A-Za-z0-9_-]+/g, "-");
2083
+ }
2084
+
2085
+ function __velarLookValue(token, value) {
2086
+ if (token.endsWith(":animation")) return __velarAnimationLookValue(value);
2087
+ if (typeof value === "number") {
2088
+ if (!__velarDomIsFinite(value)) throw new TypeError("Look properties require finite numbers");
2089
+ return __velarDomString(value);
2090
+ }
2091
+ if (typeof value !== "string") throw new TypeError("Look properties require text, finite numbers, typed visual values, or null");
2092
+ if (value.length > 1024 * 1024) throw new RangeError("A Look property value cannot exceed 1 MiB");
2093
+ if (token.endsWith(":content") && typeof value === "string" && value !== "none" && value !== "normal") return __velarQuotedText(value);
2094
+ return value;
2095
+ }
2096
+
2097
+ function __velarAnimationLookValue(value) {
2098
+ const parts = [];
2099
+ const add = (item) => {
2100
+ if (__velarGraphIsList(item)) {
2101
+ for (let index = 0; index < item.length; index += 1) add(item[index]);
2102
+ return;
2103
+ }
2104
+ const marker = item && (typeof item === "object" || typeof item === "function")
2105
+ ? __velarGraphOwnDescriptor(item, "__velarAnimation") : null;
2106
+ const css = item && (typeof item === "object" || typeof item === "function")
2107
+ ? __velarGraphOwnDescriptor(item, "css") : null;
2108
+ if (!marker || !("value" in marker) || marker.value !== true || !css || !("value" in css) || typeof css.value !== "string") {
2109
+ throw new TypeError("Look animation requires Animation or a List of Animation values from animate()");
2110
+ }
2111
+ __velarAppendOwned(parts, css.value);
2112
+ };
2113
+ add(value);
2114
+ if (parts.length === 0) throw new TypeError("A Look animation list cannot be empty");
2115
+ let output = parts[0];
2116
+ for (let index = 1; index < parts.length; index += 1) output += ", " + parts[index];
2117
+ return output;
2118
+ }
2119
+
2120
+ const __velarInlineStyleProperties = __velarGraphCreateSet(${JSON.stringify([...LOOK_PROPERTIES].map(cssPropertyName))});
2121
+
2122
+ function __velarStyleDeclarations(value) {
2123
+ if (!value || typeof value !== "object" || __velarGraphIsList(value)
2124
+ || (__velarGraphPrototype(value) !== __velarGraphNativeObject.prototype && __velarGraphPrototype(value) !== null)
2125
+ || __velarWebErrorOwnSymbols(value).length > 0) {
2126
+ throw new TypeError("style:* requires compiler-owned inline declarations");
2127
+ }
2128
+ const names = __velarGraphOwnNames(value);
2129
+ if (names.length > ${LOOK_PROPERTIES.size}) throw new RangeError("An inline Style has too many properties");
2130
+ const output = {};
2131
+ for (let index = 0; index < names.length; index += 1) {
2132
+ const property = names[index];
2133
+ if (!__velarGraphSetContains(__velarInlineStyleProperties, property)) throw new TypeError("Unknown inline Style property '" + property + "'");
2134
+ const descriptor = __velarGraphOwnDescriptor(value, property);
2135
+ if (!descriptor || !descriptor.enumerable || !("value" in descriptor)) throw new TypeError("Inline Style declarations cannot use accessors");
2136
+ __velarGraphDefine(output, property, { value: descriptor.value, enumerable: true, configurable: false, writable: false });
2137
+ }
2138
+ return __velarGraphFreeze(output);
2139
+ }
2140
+
2141
+ function __velarInlineStyleState(element) {
2142
+ const current = __velarGraphOwnDescriptor(element, "__velarInlineStyleState");
2143
+ if (current) {
2144
+ if (!("value" in current) || current.enumerable || current.configurable || current.writable
2145
+ || !current.value || typeof current.value !== "object") throw new TypeError("Inline Style ownership is invalid");
2146
+ return current.value;
2147
+ }
2148
+ const state = __velarGraphFreeze({ base: __velarGraphCreateMap(), managed: __velarGraphCreateSet() });
2149
+ __velarGraphDefine(element, "__velarInlineStyleState", { value: state });
2150
+ return state;
2151
+ }
2152
+
2153
+ function __velarAttachSource(registry, element, source) {
2154
+ let sources = __velarGraphWeakMapRead(registry, element);
2155
+ if (!sources) { sources = __velarGraphCreateSet(); __velarGraphWeakMapWrite(registry, element, sources); }
2156
+ __velarGraphSetInsert(sources, source);
2157
+ return sources;
2158
+ }
2159
+
2160
+ function __velarDetachSource(registry, element, source) {
2161
+ const sources = __velarGraphWeakMapRead(registry, element);
2162
+ if (!sources) return;
2163
+ __velarGraphSetRemove(sources, source);
2164
+ if (__velarGraphSetCount(sources) === 0) __velarGraphWeakMapRemove(registry, element);
2165
+ }
2166
+
2167
+ function __velarApplyStyles(element) {
2168
+ const sources = __velarGraphWeakMapRead(__velarRuntime.lookSources, element);
2169
+ const merged = __velarGraphCreateMap();
2170
+ if (sources) {
2171
+ for (const source of __velarGraphSetItems(sources)) {
2172
+ if (!source.styles) continue;
2173
+ const names = __velarGraphOwnNames(source.styles);
2174
+ for (let index = 0; index < names.length; index += 1) {
2175
+ __velarGraphMapWrite(merged, names[index], __velarGraphOwnDescriptor(source.styles, names[index]).value);
2176
+ }
2177
+ }
2178
+ }
2179
+ const state = __velarInlineStyleState(element);
2180
+ const next = __velarGraphCreateSet(__velarGraphMapKeyItems(merged));
2181
+ for (const property of __velarGraphSetItems(next)) {
2182
+ if (__velarGraphSetContains(state.managed, property)) continue;
2183
+ __velarGraphMapWrite(state.base, property, {
2184
+ value: __velarDomStyleValue(element, property),
2185
+ priority: __velarDomStylePriority(element, property),
2186
+ });
2187
+ }
2188
+ for (const property of __velarGraphSetItems(state.managed)) {
2189
+ if (__velarGraphSetContains(next, property)) continue;
2190
+ const base = __velarGraphMapRead(state.base, property);
2191
+ if (!base || (base.value === "" && base.priority === "")) __velarDomStyleClear(element, property);
2192
+ else __velarDomStyleWrite(element, property, base.value, base.priority);
2193
+ __velarGraphMapRemove(state.base, property);
2194
+ }
2195
+ for (const property of __velarGraphSetItems(next)) {
2196
+ const value = __velarGraphMapRead(merged, property);
2197
+ if (value == null) __velarDomStyleClear(element, property);
2198
+ else __velarDomStyleWrite(element, property, __velarLookValue("base:" + property, value));
2199
+ }
2200
+ __velarGraphSetEmpty(state.managed);
2201
+ for (const property of __velarGraphSetItems(next)) __velarGraphSetInsert(state.managed, property);
2202
+ }
2203
+
2204
+ function __velarStyleBind(element, read, scope) {
2205
+ const source = { rules: __velarGraphCreateRecord(), styles: {} };
2206
+ __velarAttachSource(__velarRuntime.lookSources, element, source);
2207
+ __velarObserver(() => {
2208
+ source.styles = __velarStyleDeclarations(read());
2209
+ __velarApplyStyles(element);
2210
+ }, "dom", scope);
2211
+ __velarAppendOwned(scope.cleanups, () => {
2212
+ __velarDetachSource(__velarRuntime.lookSources, element, source);
2213
+ __velarApplyStyles(element);
2214
+ });
2215
+ }
2216
+
2217
+ function __velarMoveStyleSource(source, previous, next) {
2218
+ if (previous) {
2219
+ __velarDetachSource(__velarRuntime.lookSources, previous, source);
2220
+ __velarApplyStyles(previous);
2221
+ }
2222
+ if (next) {
2223
+ __velarAttachSource(__velarRuntime.lookSources, next, source);
2224
+ __velarApplyStyles(next);
2225
+ }
2226
+ }
2227
+
2228
+ // The dynamic-root marker sits on a fragment the emitter created, but the
2229
+ // fragment is still a host object: a planted prototype getter would otherwise
2230
+ // hand look/class/style application a forged host element.
2231
+ function __velarDynamicRootState(root) {
2232
+ if (root === null || root === undefined) return null;
2233
+ const descriptor = __velarGraphOwnDescriptor(root, "__velarDynamicRoot");
2234
+ return descriptor && "value" in descriptor && descriptor.value && typeof descriptor.value === "object"
2235
+ ? descriptor.value
2236
+ : null;
2237
+ }
2238
+
2239
+ function __velarStyleBindRoot(root, read, scope) {
2240
+ const dynamic = __velarDynamicRootState(root);
2241
+ if (!dynamic) {
2242
+ __velarStyleBind(__velarRootHost(root, "style"), read, scope);
2243
+ return;
2244
+ }
2245
+ const source = { rules: __velarGraphCreateRecord(), styles: {} };
2246
+ let host = null;
2247
+ const move = (next) => {
2248
+ __velarMoveStyleSource(source, host, next);
2249
+ host = next;
2250
+ };
2251
+ __velarGraphSetInsert(dynamic.listeners, move);
2252
+ move(dynamic.host);
2253
+ __velarObserver(() => {
2254
+ source.styles = __velarStyleDeclarations(read());
2255
+ if (host) __velarApplyStyles(host);
2256
+ }, "dom", scope);
2257
+ __velarAppendOwned(scope.cleanups, () => {
2258
+ __velarGraphSetRemove(dynamic.listeners, move);
2259
+ move(null);
2260
+ });
2261
+ }
2262
+
2263
+ // Look and class ownership lives in one non-enumerable, non-configurable data
2264
+ // property per element, discovered through the captured descriptor ABI exactly
2265
+ // like inline style ownership. An ambient expando read would let a hostile
2266
+ // prototype hand the framework a forged token set.
2267
+ function __velarElementState(element, name, create) {
2268
+ const current = __velarGraphOwnDescriptor(element, name);
2269
+ if (current) {
2270
+ if (!("value" in current) || current.enumerable || current.configurable || current.writable
2271
+ || !current.value || typeof current.value !== "object") throw new TypeError("VelarScript element ownership is invalid");
2272
+ return current.value;
2273
+ }
2274
+ const state = create();
2275
+ __velarGraphDefine(element, name, { value: state });
2276
+ return state;
2277
+ }
2278
+
2279
+ function __velarApplyLooks(element) {
2280
+ const sources = __velarGraphWeakMapRead(__velarRuntime.lookSources, element);
2281
+ const merged = __velarGraphCreateRecord();
2282
+ if (sources) {
2283
+ // A null rule keeps its token: the token drives the generated selector and
2284
+ // only the custom property behind it disappears.
2285
+ for (const source of __velarGraphSetItems(sources)) {
2286
+ const names = __velarGraphOwnNames(source.rules);
2287
+ for (let index = 0; index < names.length; index += 1) {
2288
+ const descriptor = __velarGraphOwnDescriptor(source.rules, names[index]);
2289
+ if (descriptor && "value" in descriptor) merged[names[index]] = descriptor.value;
2290
+ }
2291
+ }
2292
+ }
2293
+ const state = __velarElementState(element, "__velarLookTokens", () => __velarGraphFreeze({ tokens: __velarGraphCreateSet() }));
2294
+ const tokens = __velarGraphOwnNames(merged);
2295
+ const next = __velarGraphCreateSet(tokens);
2296
+ for (const token of __velarGraphSetItems(state.tokens)) {
2297
+ if (!__velarGraphSetContains(next, token)) __velarDomStyleClear(element, __velarLookVariable(token));
2298
+ }
2299
+ let attribute = "";
2300
+ for (let index = 0; index < tokens.length; index += 1) {
2301
+ const token = tokens[index];
2302
+ const value = __velarGraphOwnDescriptor(merged, token)?.value;
2303
+ if (value == null) __velarDomStyleClear(element, __velarLookVariable(token));
2304
+ else __velarDomStyleWrite(element, __velarLookVariable(token), __velarLookValue(token, value));
2305
+ attribute = attribute === "" ? token : attribute + " " + token;
2306
+ }
2307
+ if (tokens.length > 0) __velarDomSetAttribute(element, "data-velar-look", attribute);
2308
+ else __velarDomRemoveAttribute(element, "data-velar-look");
2309
+ __velarGraphSetEmpty(state.tokens);
2310
+ for (let index = 0; index < tokens.length; index += 1) __velarGraphSetInsert(state.tokens, tokens[index]);
2311
+ }
2312
+
2313
+ function __velarLookBind(element, read, scope) {
2314
+ const source = { rules: __velarGraphCreateRecord() };
2315
+ __velarAttachSource(__velarRuntime.lookSources, element, source);
2316
+ __velarObserver(() => {
2317
+ source.rules = __velarLook([read()]).rules;
2318
+ __velarApplyLooks(element);
2319
+ }, "dom", scope);
2320
+ __velarAppendOwned(scope.cleanups, () => {
2321
+ __velarDetachSource(__velarRuntime.lookSources, element, source);
2322
+ __velarApplyLooks(element);
2323
+ });
2324
+ }
2325
+
2326
+ function __velarMoveLookSource(source, previous, next) {
2327
+ if (previous) {
2328
+ __velarDetachSource(__velarRuntime.lookSources, previous, source);
2329
+ __velarApplyLooks(previous);
2330
+ }
2331
+ if (next) {
2332
+ __velarAttachSource(__velarRuntime.lookSources, next, source);
2333
+ __velarApplyLooks(next);
2334
+ }
2335
+ }
2336
+
2337
+ function __velarApplyExternalLook(element, value) {
2338
+ const source = { rules: __velarLook([value]).rules };
2339
+ __velarAttachSource(__velarRuntime.lookSources, element, source);
2340
+ __velarApplyLooks(element);
2341
+ return () => {
2342
+ __velarDetachSource(__velarRuntime.lookSources, element, source);
2343
+ __velarApplyLooks(element);
2344
+ };
2345
+ }
2346
+
2347
+ __velarRuntime.installLook(__velarApplyExternalLook);
2348
+
2349
+ function __velarRootHost(root, capability) {
2350
+ if (root == null) throw new TypeError("A component with multiple roots must mark exactly one native element with 'host'");
2351
+ if (__velarDomNodeType(root) === 1) return root;
2352
+ const elements = [];
2353
+ const children = __velarDomChildNodes(root);
2354
+ for (let index = 0; index < children.length; index += 1) {
2355
+ if (__velarDomNodeType(children[index]) === 1) __velarAppendOwned(elements, children[index]);
2356
+ }
2357
+ const explicit = [];
2358
+ for (let index = 0; index < elements.length; index += 1) {
2359
+ const element = elements[index];
2360
+ if (__velarDomOwnData(element, "__velarHost") === true) __velarAppendOwned(explicit, element);
2361
+ const descendants = __velarDomCollectionSnapshot(__velarDomQuerySelectorAll(element, "*"), "Element.querySelectorAll");
2362
+ for (let child = 0; child < descendants.length; child += 1) {
2363
+ if (__velarDomOwnData(descendants[child], "__velarHost") === true) __velarAppendOwned(explicit, descendants[child]);
2364
+ }
2365
+ }
2366
+ if (explicit.length === 1) return explicit[0];
2367
+ if (explicit.length > 1) throw new TypeError("A component can declare only one host element");
2368
+ if (elements.length === 1) return elements[0];
2369
+ throw new TypeError("A component with multiple roots must mark exactly one native element with 'host'");
2370
+ }
2371
+
2372
+ function __velarLookBindRoot(root, read, scope) {
2373
+ const dynamic = __velarDynamicRootState(root);
2374
+ if (!dynamic) {
2375
+ __velarLookBind(__velarRootHost(root, "look"), read, scope);
2376
+ return;
2377
+ }
2378
+ const source = { rules: __velarGraphCreateRecord() };
2379
+ let host = null;
2380
+ const move = (next) => {
2381
+ __velarMoveLookSource(source, host, next);
2382
+ host = next;
2383
+ };
2384
+ __velarGraphSetInsert(dynamic.listeners, move);
2385
+ move(dynamic.host);
2386
+ __velarObserver(() => {
2387
+ source.rules = __velarLook([read()]).rules;
2388
+ if (host) __velarApplyLooks(host);
2389
+ }, "dom", scope);
2390
+ __velarAppendOwned(scope.cleanups, () => {
2391
+ __velarGraphSetRemove(dynamic.listeners, move);
2392
+ move(null);
2393
+ });
2394
+ }
2395
+
2396
+ function __velarClassBindRoot(root, read, scope) {
2397
+ const dynamic = __velarDynamicRootState(root);
2398
+ if (!dynamic) {
2399
+ __velarClassBind(__velarRootHost(root, "class"), read, scope);
2400
+ return;
2401
+ }
2402
+ const source = { names: [] };
2403
+ let host = null;
2404
+ const move = (next) => {
2405
+ __velarMoveClassSource(source, host, next);
2406
+ host = next;
2407
+ };
2408
+ __velarGraphSetInsert(dynamic.listeners, move);
2409
+ move(dynamic.host);
2410
+ __velarObserver(() => {
2411
+ source.names = __velarClassNames(read());
2412
+ if (host) __velarApplyClasses(host);
2413
+ }, "dom", scope);
2414
+ __velarAppendOwned(scope.cleanups, () => {
2415
+ __velarGraphSetRemove(dynamic.listeners, move);
2416
+ move(null);
2417
+ });
2418
+ }
2419
+
2420
+ function __velarClassNames(value, output = []) {
2421
+ if (value == null || value === false) return output;
2422
+ if (__velarGraphIsList(value)) {
2423
+ for (let index = 0; index < value.length; index += 1) __velarClassNames(value[index], output);
2424
+ return output;
2425
+ }
2426
+ if (typeof value !== "string") throw new TypeError("class accepts strings, string?, or lists of strings");
2427
+ let name = "";
2428
+ for (let index = 0; index < value.length; index += 1) {
2429
+ const character = value[index];
2430
+ if (character === " " || character === "\t" || character === "\n" || character === "\r" || character === "\f" || character === "\v") {
2431
+ if (name !== "") __velarAppendOwned(output, name);
2432
+ name = "";
2433
+ continue;
2434
+ }
2435
+ name += character;
2436
+ }
2437
+ if (name !== "") __velarAppendOwned(output, name);
2438
+ return output;
2439
+ }
2440
+
2441
+ function __velarApplyClasses(element) {
2442
+ const sources = __velarGraphWeakMapRead(__velarRuntime.classSources, element);
2443
+ const next = __velarGraphCreateSet();
2444
+ if (sources) {
2445
+ for (const source of __velarGraphSetItems(sources)) {
2446
+ for (let index = 0; index < source.names.length; index += 1) __velarGraphSetInsert(next, source.names[index]);
2447
+ }
2448
+ }
2449
+ const state = __velarElementState(element, "__velarClassState", () => __velarGraphFreeze({
2450
+ base: __velarGraphCreateSet(__velarDomClassNames(element)),
2451
+ managed: __velarGraphCreateSet(),
2452
+ }));
2453
+ for (const name of __velarGraphSetItems(state.managed)) {
2454
+ if (!__velarGraphSetContains(next, name) && !__velarGraphSetContains(state.base, name)) __velarDomClassRemove(element, name);
2455
+ }
2456
+ for (const name of __velarGraphSetItems(next)) __velarDomClassInsert(element, name);
2457
+ __velarGraphSetEmpty(state.managed);
2458
+ for (const name of __velarGraphSetItems(next)) __velarGraphSetInsert(state.managed, name);
2459
+ }
2460
+
2461
+ function __velarMoveClassSource(source, previous, next) {
2462
+ if (previous) {
2463
+ __velarDetachSource(__velarRuntime.classSources, previous, source);
2464
+ __velarApplyClasses(previous);
2465
+ }
2466
+ if (next) {
2467
+ __velarAttachSource(__velarRuntime.classSources, next, source);
2468
+ __velarApplyClasses(next);
2469
+ }
2470
+ }
2471
+
2472
+ function __velarClassBind(element, read, scope) {
2473
+ const source = { names: [] };
2474
+ __velarAttachSource(__velarRuntime.classSources, element, source);
2475
+ __velarObserver(() => {
2476
+ source.names = __velarClassNames(read());
2477
+ __velarApplyClasses(element);
2478
+ }, "dom", scope);
2479
+ __velarAppendOwned(scope.cleanups, () => {
2480
+ __velarDetachSource(__velarRuntime.classSources, element, source);
2481
+ __velarApplyClasses(element);
2482
+ });
2483
+ }
2484
+
2485
+ function __velarHtml(element, read, scope) {
2486
+ __velarObserver(() => {
2487
+ const value = read();
2488
+ if (value != null && typeof value !== "string") throw new TypeError("unsafe:html requires string or null");
2489
+ if (value?.length > 16 * 1024 * 1024) throw new RangeError("unsafe:html cannot exceed 16 MiB");
2490
+ __velarDomSetHtml(element, value ?? "");
2491
+ }, "dom", scope);
2492
+ }
2493
+
2494
+ function __velarOn(element, event, read, scope, modifiers = []) {
2495
+ if (typeof __velarInternalRead(read) !== "function") throw new TypeError("Event '" + event + "' requires a function");
2496
+ const capture = __velarHasName(modifiers, "capture");
2497
+ const options = { capture, once: __velarHasName(modifiers, "once") };
2498
+ const listener = (value) => {
2499
+ try {
2500
+ if (__velarHasName(modifiers, "self")) {
2501
+ const target = __velarEventField(value, "target", __velarEventTargetGetter);
2502
+ if (target === __velarEventMissingField) throw new TypeError("DOM event does not expose a native target");
2503
+ if (target !== element) return;
2504
+ }
2505
+ if (__velarHasName(modifiers, "prevent")) __velarEventCall(value, "preventDefault", __velarEventPreventDefault);
2506
+ if (__velarHasName(modifiers, "stop")) __velarEventCall(value, "stopPropagation", __velarEventStopPropagation);
2507
+ // The handler expression is re-read per dispatch so handlers routed
2508
+ // through live props always see the current value.
2509
+ const handler = __velarInternalRead(read);
2510
+ if (typeof handler !== "function") throw new TypeError("Event '" + event + "' requires a function");
2511
+ const result = __velarUntracked(() => handler(value));
2512
+ __velarObservePromise(result, (error) => __velarReportEvent(error, scope, event));
2513
+ } catch (error) { __velarReportEvent(error, scope, event); }
2514
+ };
2515
+ __velarDomAddListener(element, event, listener, options);
2516
+ __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, event, listener, capture));
2517
+ }
2518
+
2519
+ function __velarBindValue(element, state, scope, numeric = false, parse = null) {
2520
+ __velarObserver(() => {
2521
+ const value = state.get();
2522
+ if (value == null) __velarDomSetFieldValue(element, "");
2523
+ else if (numeric) {
2524
+ if (typeof value !== "number" || !__velarDomIsFinite(value)) throw new TypeError("Numeric bind:value requires a finite number");
2525
+ __velarDomSetFieldValue(element, __velarDomString(value));
2526
+ } else {
2527
+ if (typeof value !== "string") throw new TypeError("bind:value requires text");
2528
+ __velarDomSetFieldValue(element, value);
2529
+ }
2530
+ }, "dom", scope);
2531
+ const update = () => state.set(numeric ? __velarDomFieldNumber(element) : parse ? parse(__velarDomFieldValue(element)) : __velarDomFieldValue(element));
2532
+ __velarDomAddListener(element, "input", update, false);
2533
+ __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "input", update, false));
2534
+ }
2535
+
2536
+ function __velarBindGroupValues(state, own) {
2537
+ const value = __velarInternalRead(() => state.get());
2538
+ const values = __velarListSnapshot(value, "bind:group state");
2539
+ const output = new __velarDomNativeArray(values.length);
2540
+ let count = 0;
2541
+ for (let index = 0; index < values.length; index += 1) {
2542
+ const item = values[index];
2543
+ if (typeof item !== "string") throw new TypeError("bind:group on a checkbox requires List<string> state");
2544
+ if (item !== own) { output[count] = item; count += 1; }
2545
+ }
2546
+ output.length = count;
2547
+ return output;
2548
+ }
2549
+
2550
+ function __velarBindGroup(element, state, scope, multiple = false, parse = null) {
2551
+ __velarObserver(() => {
2552
+ const own = __velarDomFieldValue(element);
2553
+ const value = state.get();
2554
+ if (!multiple) {
2555
+ if (value != null && typeof value !== "string") throw new TypeError("bind:group requires text state");
2556
+ __velarDomSetFieldChecked(element, value === own);
2557
+ return;
2558
+ }
2559
+ const values = __velarListSnapshot(value, "bind:group state");
2560
+ let present = false;
2561
+ for (let index = 0; index < values.length; index += 1) if (values[index] === own) present = true;
2562
+ __velarDomSetFieldChecked(element, present);
2563
+ }, "dom", scope);
2564
+ const update = () => {
2565
+ const own = __velarDomFieldValue(element);
2566
+ if (!multiple) {
2567
+ if (__velarDomFieldChecked(element)) state.set(parse ? parse(own) : own);
2568
+ return;
2569
+ }
2570
+ const remaining = __velarBindGroupValues(state, own);
2571
+ if (__velarDomFieldChecked(element)) remaining[remaining.length] = own;
2572
+ state.set(remaining);
2573
+ };
2574
+ __velarDomAddListener(element, "change", update, false);
2575
+ __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "change", update, false));
2576
+ }
2577
+
2578
+ function __velarBindChecked(element, state, scope) {
2579
+ __velarObserver(() => {
2580
+ const value = state.get();
2581
+ if (typeof value !== "boolean") throw new TypeError("bind:checked requires bool");
2582
+ __velarDomSetFieldChecked(element, value);
2583
+ }, "dom", scope);
2584
+ const update = () => state.set(__velarDomFieldChecked(element));
2585
+ __velarDomAddListener(element, "change", update, false);
2586
+ __velarAppendOwned(scope.cleanups, () => __velarDomRemoveListener(element, "change", update, false));
2587
+ }
2588
+
2589
+ // Prop handles give a component body live reads over its props store. The
2590
+ // component function still runs exactly once per instance; only reads race
2591
+ // ahead, so state initializers can never re-run on a prop update.
2592
+ function __velarRequiredProp(props, name, component) {
2593
+ if (__velarInternalRead(() => props[name]) === undefined) throw new TypeError("Component " + component + " requires prop " + name);
2594
+ return __velarGraphFreeze({
2595
+ get() {
2596
+ const value = props[name];
2597
+ if (value === undefined) throw new TypeError("Component " + component + " requires prop " + name);
2598
+ return value;
2599
+ },
2600
+ });
2601
+ }
2602
+
2603
+ function __velarProp(props, name, fallback) {
2604
+ const fallbackValue = __velarInternalRead(() => props[name]) === undefined ? fallback() : undefined;
2605
+ return __velarGraphFreeze({
2606
+ get() {
2607
+ const value = props[name];
2608
+ return value === undefined ? fallbackValue : value;
2609
+ },
2610
+ });
2611
+ }
2612
+
2613
+ // Instantiates a component with a live props store: each prop thunk runs in
2614
+ // its own observer that writes a reactive cell, and the props object exposes
2615
+ // tracked getters over those cells. The component call itself is untracked so
2616
+ // construction can never subscribe an enclosing dynamic region to prop reads.
2617
+ function __velarBindComponentRef(instance, setRef) {
2618
+ if (setRef === undefined) return instance;
2619
+ if (!instance || typeof instance.__bindRef !== "function") throw new TypeError("This component does not expose a Handle");
2620
+ instance.__bindRef(setRef);
2621
+ return instance;
2622
+ }
2623
+
2624
+ function __velarInstantiate(component, thunks, children, scope, namespace, setRef) {
2625
+ if (component != null && component.__velarSnapshotProps === true) {
2626
+ // Runtime-implemented components (Head, Router, Link, NavLink) consume a
2627
+ // one-time plain snapshot so their strict record validation still holds.
2628
+ const snapshot = {};
2629
+ const styleRead = thunks.__velarStyle;
2630
+ const snapshotNames = __velarGraphOwnNames(thunks);
2631
+ for (let index = 0; index < snapshotNames.length; index += 1) {
2632
+ if (snapshotNames[index] !== "__velarStyle") snapshot[snapshotNames[index]] = __velarInternalRead(thunks[snapshotNames[index]]);
2633
+ }
2634
+ if (children !== undefined) snapshot.children = __velarInternalRead(children);
2635
+ const instance = __velarUntracked(() => component(snapshot, namespace));
2636
+ if (styleRead !== undefined) __velarStyleBindRoot(instance.node, styleRead, scope);
2637
+ return __velarBindComponentRef(instance, setRef);
2638
+ }
2639
+ const props = {};
2640
+ const propNames = __velarGraphOwnNames(thunks);
2641
+ for (let index = 0; index < propNames.length; index += 1) {
2642
+ const name = propNames[index];
2643
+ const read = thunks[name];
2644
+ const cell = __velarState(undefined);
2645
+ __velarObserver(() => cell.set(read()), "dom", scope);
2646
+ __velarGraphDefine(props, name, { enumerable: true, get: () => cell.get() });
2647
+ }
2648
+ if (children !== undefined) __velarGraphDefine(props, "children", { enumerable: true, value: __velarInternalRead(children) });
2649
+ return __velarBindComponentRef(__velarUntracked(() => component(props, namespace)), setRef);
2650
+ }
2651
+
2652
+ // A component element in child position: one stable instance whose prop
2653
+ // observers live in a dedicated scope, destroyed only when the position
2654
+ // itself unmounts. Construction failures stay contained to the position.
2655
+ function __velarChild(component, thunks, children, scope, namespace, setRef) {
2656
+ const childScope = __velarScope(scope.component);
2657
+ let constructed = false;
2658
+ __velarAppendOwned(scope.mounts, () => { if (constructed) __velarMountScope(childScope); });
2659
+ __velarAppendOwned(scope.cleanups, () => { if (constructed) __velarDestroyScope(childScope); });
2660
+ try {
2661
+ const node = __velarUseComponent(__velarInstantiate(component, thunks, children, childScope, namespace, setRef), childScope);
2662
+ constructed = true;
2663
+ return node;
2664
+ } catch (error) {
2665
+ __velarDestroyScope(childScope);
2666
+ __velarReport(error, "render", scope);
2667
+ return __velarDomCreateComment("velar:component-error");
2668
+ }
2669
+ }
2670
+
2671
+ function __velarSettled() {
2672
+ return __velarManagedAsyncCreate((resolve) => __velarEnqueue(resolve));
2673
+ }
2674
+
2675
+ function __velarTakeUnhandledFailure() {
2676
+ for (const failure of __velarGraphSetItems(__velarRuntime.unhandledFailures)) {
2677
+ __velarGraphSetRemove(__velarRuntime.unhandledFailures, failure);
2678
+ return failure;
2679
+ }
2680
+ return null;
2681
+ }
2682
+
2683
+ // In a non-browser host an unhandled report cannot throw from a microtask
2684
+ // without ending the whole process, so the runtime parks it. tick() is where
2685
+ // an awaiting caller meets the reactive queue, which makes it the owned place
2686
+ // for that parked failure to surface: the test that awaited the flush fails
2687
+ // with the real error and the process -- the test runner -- continues.
2688
+ function __velarTick() {
2689
+ return __velarManagedAsyncThen(__velarSettled(), () => {
2690
+ const failure = __velarTakeUnhandledFailure();
2691
+ if (failure !== null) throw failure;
2692
+ return null;
2693
+ });
2694
+ }
2695
+ `.trim();
2696
+ function webRuntime(foundation) {
2697
+ return `${foundation}\n${WEB_RUNTIME_BODY}`;
2698
+ }
2699
+ //# sourceMappingURL=emitter.js.map