@craft-ts/component 0.7.0-beta.13 → 0.7.0-beta.16

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 (195) hide show
  1. package/package.json +7 -2
  2. package/src/index.d.ts +40 -40
  3. package/src/index.js +35 -35
  4. package/src/lib/a11y-control.d.ts +0 -1
  5. package/src/lib/a11y-control.js +0 -1
  6. package/src/lib/a11y.d.ts +4 -5
  7. package/src/lib/a11y.js +3 -4
  8. package/src/lib/ai/ai-context-menu.d.ts +24 -25
  9. package/src/lib/ai/ai-context-menu.js +2 -3
  10. package/src/lib/ai/ai-send-dialog.d.ts +277 -278
  11. package/src/lib/ai/ai-send-dialog.js +4 -5
  12. package/src/lib/ai/send-context-to-ai.d.ts +1 -2
  13. package/src/lib/ai/send-context-to-ai.js +4 -5
  14. package/src/lib/assert-defined-input.d.ts +1 -2
  15. package/src/lib/assert-defined-input.js +0 -1
  16. package/src/lib/bootstrap.d.ts +4 -3
  17. package/src/lib/bootstrap.js +6 -8
  18. package/src/lib/bridge.d.ts +9 -10
  19. package/src/lib/bridge.js +3 -4
  20. package/src/lib/catch-node.d.ts +35 -0
  21. package/src/lib/{block.js → catch-node.js} +9 -10
  22. package/src/lib/component.d.ts +23 -10
  23. package/src/lib/component.js +5 -6
  24. package/src/lib/composition.d.ts +1 -2
  25. package/src/lib/composition.js +2 -3
  26. package/src/lib/craft-defaults.d.ts +0 -1
  27. package/src/lib/craft-defaults.js +4 -5
  28. package/src/lib/craft-host-tokens.d.ts +0 -1
  29. package/src/lib/craft-host-tokens.js +0 -1
  30. package/src/lib/craft-router-outlet.d.ts +1 -2
  31. package/src/lib/craft-router-outlet.js +1 -2
  32. package/src/lib/css-vars.d.ts +0 -1
  33. package/src/lib/css-vars.js +0 -1
  34. package/src/lib/css-vars.type.d.ts +1 -2
  35. package/src/lib/css-vars.type.js +0 -1
  36. package/src/lib/{defer.d.ts → defer-node.d.ts} +4 -5
  37. package/src/lib/{defer.js → defer-node.js} +1 -2
  38. package/src/lib/directive.d.ts +1 -2
  39. package/src/lib/directive.js +1 -2
  40. package/src/lib/factory-runtime.d.ts +1 -2
  41. package/src/lib/factory-runtime.js +0 -1
  42. package/src/lib/{field-exception-block.d.ts → field-error-node.d.ts} +22 -23
  43. package/src/lib/{field-exception-block.js → field-error-node.js} +8 -9
  44. package/src/lib/for-node.d.ts +28 -0
  45. package/src/lib/{each.js → for-node.js} +4 -5
  46. package/src/lib/for-scheduling.d.ts +58 -0
  47. package/src/lib/{each-scheduling.js → for-scheduling.js} +14 -15
  48. package/src/lib/host-runtime.d.ts +0 -1
  49. package/src/lib/host-runtime.js +0 -1
  50. package/src/lib/hydrate.d.ts +2 -3
  51. package/src/lib/hydrate.js +57 -18
  52. package/src/lib/hyperscript.d.ts +1 -2
  53. package/src/lib/hyperscript.js +1 -2
  54. package/src/lib/if-node.d.ts +7 -0
  55. package/src/lib/{if-block.js → if-node.js} +2 -3
  56. package/src/lib/locator.d.ts +5 -6
  57. package/src/lib/locator.js +1 -2
  58. package/src/lib/{match-block.d.ts → match-node.d.ts} +8 -9
  59. package/src/lib/{match-block.js → match-node.js} +3 -4
  60. package/src/lib/{pending-block.d.ts → pending-node.d.ts} +28 -29
  61. package/src/lib/{pending-block.js → pending-node.js} +12 -13
  62. package/src/lib/project.d.ts +2 -3
  63. package/src/lib/project.js +2 -3
  64. package/src/lib/render/hydration-metadata.d.ts +0 -1
  65. package/src/lib/render/hydration-metadata.js +0 -1
  66. package/src/lib/render/hydration.d.ts +0 -1
  67. package/src/lib/render/hydration.js +0 -1
  68. package/src/lib/render/interpreter.d.ts +9 -8
  69. package/src/lib/render/interpreter.js +156 -81
  70. package/src/lib/render/server-style-collector.d.ts +0 -1
  71. package/src/lib/render/server-style-collector.js +0 -1
  72. package/src/lib/render/ssr-coordinator.d.ts +4 -2
  73. package/src/lib/render/ssr-coordinator.js +14 -3
  74. package/src/lib/render/string-dom.d.ts +0 -1
  75. package/src/lib/render/string-dom.js +48 -7
  76. package/src/lib/render/style-registry.d.ts +3 -2
  77. package/src/lib/render/style-registry.js +3 -2
  78. package/src/lib/render/style-scope.d.ts +0 -1
  79. package/src/lib/render/style-scope.js +0 -1
  80. package/src/lib/render/vnode.d.ts +117 -54
  81. package/src/lib/render/vnode.js +26 -27
  82. package/src/lib/security.d.ts +54 -0
  83. package/src/lib/security.js +502 -0
  84. package/src/lib/server-render.d.ts +12 -3
  85. package/src/lib/server-render.js +76 -17
  86. package/src/lib/start.d.ts +2 -3
  87. package/src/lib/start.js +3 -3
  88. package/src/lib/template-contract.d.ts +22 -23
  89. package/src/lib/template-contract.js +0 -1
  90. package/src/lib/template.d.ts +2 -3
  91. package/src/lib/template.js +2 -3
  92. package/src/lib/testing.d.ts +3 -4
  93. package/src/lib/testing.js +5 -6
  94. package/src/lib/types.d.ts +40 -28
  95. package/src/lib/types.js +3 -4
  96. package/testing/public-api.d.ts +0 -1
  97. package/testing/public-api.js +0 -1
  98. package/src/index.d.ts.map +0 -1
  99. package/src/index.js.map +0 -1
  100. package/src/lib/a11y-control.d.ts.map +0 -1
  101. package/src/lib/a11y-control.js.map +0 -1
  102. package/src/lib/a11y.d.ts.map +0 -1
  103. package/src/lib/a11y.js.map +0 -1
  104. package/src/lib/ai/ai-context-menu.d.ts.map +0 -1
  105. package/src/lib/ai/ai-context-menu.js.map +0 -1
  106. package/src/lib/ai/ai-send-dialog.d.ts.map +0 -1
  107. package/src/lib/ai/ai-send-dialog.js.map +0 -1
  108. package/src/lib/ai/send-context-to-ai.d.ts.map +0 -1
  109. package/src/lib/ai/send-context-to-ai.js.map +0 -1
  110. package/src/lib/assert-defined-input.d.ts.map +0 -1
  111. package/src/lib/assert-defined-input.js.map +0 -1
  112. package/src/lib/block.d.ts +0 -36
  113. package/src/lib/block.d.ts.map +0 -1
  114. package/src/lib/block.js.map +0 -1
  115. package/src/lib/bootstrap.d.ts.map +0 -1
  116. package/src/lib/bootstrap.js.map +0 -1
  117. package/src/lib/bridge.d.ts.map +0 -1
  118. package/src/lib/bridge.js.map +0 -1
  119. package/src/lib/component.d.ts.map +0 -1
  120. package/src/lib/component.js.map +0 -1
  121. package/src/lib/composition.d.ts.map +0 -1
  122. package/src/lib/composition.js.map +0 -1
  123. package/src/lib/craft-defaults.d.ts.map +0 -1
  124. package/src/lib/craft-defaults.js.map +0 -1
  125. package/src/lib/craft-host-tokens.d.ts.map +0 -1
  126. package/src/lib/craft-host-tokens.js.map +0 -1
  127. package/src/lib/craft-router-outlet.d.ts.map +0 -1
  128. package/src/lib/craft-router-outlet.js.map +0 -1
  129. package/src/lib/css-vars.d.ts.map +0 -1
  130. package/src/lib/css-vars.js.map +0 -1
  131. package/src/lib/css-vars.type.d.ts.map +0 -1
  132. package/src/lib/css-vars.type.js.map +0 -1
  133. package/src/lib/defer.d.ts.map +0 -1
  134. package/src/lib/defer.js.map +0 -1
  135. package/src/lib/directive.d.ts.map +0 -1
  136. package/src/lib/directive.js.map +0 -1
  137. package/src/lib/each-scheduling.d.ts +0 -59
  138. package/src/lib/each-scheduling.d.ts.map +0 -1
  139. package/src/lib/each-scheduling.js.map +0 -1
  140. package/src/lib/each.d.ts +0 -29
  141. package/src/lib/each.d.ts.map +0 -1
  142. package/src/lib/each.js.map +0 -1
  143. package/src/lib/factory-runtime.d.ts.map +0 -1
  144. package/src/lib/factory-runtime.js.map +0 -1
  145. package/src/lib/field-exception-block.d.ts.map +0 -1
  146. package/src/lib/field-exception-block.js.map +0 -1
  147. package/src/lib/host-runtime.d.ts.map +0 -1
  148. package/src/lib/host-runtime.js.map +0 -1
  149. package/src/lib/hydrate.d.ts.map +0 -1
  150. package/src/lib/hydrate.js.map +0 -1
  151. package/src/lib/hyperscript.d.ts.map +0 -1
  152. package/src/lib/hyperscript.js.map +0 -1
  153. package/src/lib/if-block.d.ts +0 -8
  154. package/src/lib/if-block.d.ts.map +0 -1
  155. package/src/lib/if-block.js.map +0 -1
  156. package/src/lib/locator.d.ts.map +0 -1
  157. package/src/lib/locator.js.map +0 -1
  158. package/src/lib/match-block.d.ts.map +0 -1
  159. package/src/lib/match-block.js.map +0 -1
  160. package/src/lib/pending-block.d.ts.map +0 -1
  161. package/src/lib/pending-block.js.map +0 -1
  162. package/src/lib/project.d.ts.map +0 -1
  163. package/src/lib/project.js.map +0 -1
  164. package/src/lib/render/hydration-metadata.d.ts.map +0 -1
  165. package/src/lib/render/hydration-metadata.js.map +0 -1
  166. package/src/lib/render/hydration.d.ts.map +0 -1
  167. package/src/lib/render/hydration.js.map +0 -1
  168. package/src/lib/render/interpreter.d.ts.map +0 -1
  169. package/src/lib/render/interpreter.js.map +0 -1
  170. package/src/lib/render/server-style-collector.d.ts.map +0 -1
  171. package/src/lib/render/server-style-collector.js.map +0 -1
  172. package/src/lib/render/ssr-coordinator.d.ts.map +0 -1
  173. package/src/lib/render/ssr-coordinator.js.map +0 -1
  174. package/src/lib/render/string-dom.d.ts.map +0 -1
  175. package/src/lib/render/string-dom.js.map +0 -1
  176. package/src/lib/render/style-registry.d.ts.map +0 -1
  177. package/src/lib/render/style-registry.js.map +0 -1
  178. package/src/lib/render/style-scope.d.ts.map +0 -1
  179. package/src/lib/render/style-scope.js.map +0 -1
  180. package/src/lib/render/vnode.d.ts.map +0 -1
  181. package/src/lib/render/vnode.js.map +0 -1
  182. package/src/lib/server-render.d.ts.map +0 -1
  183. package/src/lib/server-render.js.map +0 -1
  184. package/src/lib/start.d.ts.map +0 -1
  185. package/src/lib/start.js.map +0 -1
  186. package/src/lib/template-contract.d.ts.map +0 -1
  187. package/src/lib/template-contract.js.map +0 -1
  188. package/src/lib/template.d.ts.map +0 -1
  189. package/src/lib/template.js.map +0 -1
  190. package/src/lib/testing.d.ts.map +0 -1
  191. package/src/lib/testing.js.map +0 -1
  192. package/src/lib/types.d.ts.map +0 -1
  193. package/src/lib/types.js.map +0 -1
  194. package/testing/public-api.d.ts.map +0 -1
  195. package/testing/public-api.js.map +0 -1
@@ -4,8 +4,10 @@ export class CraftSsrCoordinator {
4
4
  listeners = new Set();
5
5
  failure;
6
6
  decideResource;
7
- constructor(decideResource) {
7
+ defaultTimeoutMs;
8
+ constructor(decideResource, defaultTimeoutMs) {
8
9
  this.decideResource = decideResource;
10
+ this.defaultTimeoutMs = defaultTimeoutMs;
9
11
  }
10
12
  suspend(token, source, mode, options = {}) {
11
13
  if (mode === undefined) {
@@ -14,7 +16,7 @@ export class CraftSsrCoordinator {
14
16
  this.decideResource?.(source, mode);
15
17
  if (mode !== 'block')
16
18
  return;
17
- const timeoutMs = options.timeoutMs;
19
+ const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;
18
20
  const timer = timeoutMs !== undefined
19
21
  ? setTimeout(() => {
20
22
  this.failure ??= new CraftSsrTimeoutError(timeoutMs, [source]);
@@ -61,6 +63,15 @@ export class CraftSsrCoordinator {
61
63
  ...new Set([...this.pending.values()].map((entry) => entry.source)),
62
64
  ];
63
65
  }
66
+ /** Releases source timers and waiters when the request is aborted. */
67
+ dispose() {
68
+ for (const entry of this.pending.values()) {
69
+ if (entry.timer)
70
+ clearTimeout(entry.timer);
71
+ }
72
+ this.pending.clear();
73
+ this.listeners.clear();
74
+ }
64
75
  throwFailure() {
65
76
  if (this.failure === undefined)
66
77
  return;
@@ -76,6 +87,7 @@ export class CraftSsrCoordinator {
76
87
  };
77
88
  const aborted = () => {
78
89
  cleanup();
90
+ this.dispose();
79
91
  reject(signal?.reason ?? new DOMException('Aborted', 'AbortError'));
80
92
  };
81
93
  const timer = setTimeout(() => {
@@ -96,4 +108,3 @@ export class CraftSsrCoordinator {
96
108
  });
97
109
  }
98
110
  }
99
- //# sourceMappingURL=ssr-coordinator.js.map
@@ -6,4 +6,3 @@ export type StringDom = Readonly<{
6
6
  serialize(node: Node): string;
7
7
  }>;
8
8
  export declare function createStringDomAdapter(): StringDom;
9
- //# sourceMappingURL=string-dom.d.ts.map
@@ -1,4 +1,5 @@
1
- import { hydrationKeyOf } from './hydration-metadata';
1
+ import { hydrationKeyOf } from './hydration-metadata.js';
2
+ import { assertCraftAttributeName as assertAttributeName, assertCraftTagName as assertTagName, CraftDomSecurityError, } from '../security.js';
2
3
  class StringNode {
3
4
  parentNode = null;
4
5
  ownerDocument;
@@ -115,6 +116,21 @@ class StringComment extends StringNode {
115
116
  this.data = value ?? '';
116
117
  }
117
118
  }
119
+ /** Markup already approved by the security layer, emitted as-is. */
120
+ class StringRawHtml extends StringNode {
121
+ nodeType = 3;
122
+ html;
123
+ constructor(ownerDocument, html) {
124
+ super(ownerDocument);
125
+ this.html = html;
126
+ }
127
+ get textContent() {
128
+ return this.html;
129
+ }
130
+ set textContent(value) {
131
+ this.html = value ?? '';
132
+ }
133
+ }
118
134
  class StringDocumentFragment extends StringParentNode {
119
135
  nodeType = 11;
120
136
  }
@@ -132,7 +148,7 @@ class StringElement extends StringParentNode {
132
148
  open = false;
133
149
  constructor(ownerDocument, tag) {
134
150
  super(ownerDocument);
135
- this.localName = tag.toLowerCase();
151
+ this.localName = assertTagName(tag).toLowerCase();
136
152
  this.tagName = this.localName.toUpperCase();
137
153
  this.style = createStyleDeclaration((css) => {
138
154
  if (css)
@@ -142,7 +158,18 @@ class StringElement extends StringParentNode {
142
158
  });
143
159
  }
144
160
  setAttribute(name, value) {
145
- this.attributes.set(name, String(value));
161
+ this.attributes.set(assertAttributeName(name), String(value));
162
+ }
163
+ /**
164
+ * Replaces the children with pre-approved markup. Only the interpreter's
165
+ * audited HTML path reaches this, and the value is emitted verbatim, so it
166
+ * must already have gone through sanitizedHtml or an explicit exception.
167
+ */
168
+ ɵsetTrustedHtml(html) {
169
+ for (const child of this.childNodes)
170
+ child.parentNode = null;
171
+ this.childNodes.length = 0;
172
+ this.appendChild(new StringRawHtml(this.ownerDocument, html));
146
173
  }
147
174
  getAttribute(name) {
148
175
  return this.attributes.get(name) ?? null;
@@ -254,6 +281,16 @@ function asParent(node) {
254
281
  return node;
255
282
  }
256
283
  function setStringProperty(element, name, value) {
284
+ if (name === '__proto__' || name === 'constructor') {
285
+ throw new CraftDomSecurityError('CRAFT_DOM_PROPERTY_BLOCKED', `"${name}" cannot be set as a DOM property.`);
286
+ }
287
+ // Raw markup has no attribute equivalent: without this branch the server
288
+ // would emit an escaped `innerHTML="…"` attribute and the content would only
289
+ // appear once the browser hydrated, diverging from the server output.
290
+ if (name === 'innerHTML') {
291
+ element.ɵsetTrustedHtml(value === null || value === undefined ? '' : String(value));
292
+ return;
293
+ }
257
294
  Reflect.set(element, name, value);
258
295
  const attribute = name === 'htmlFor' ? 'for' : name;
259
296
  if (typeof value === 'boolean') {
@@ -337,6 +374,9 @@ const VOID_ELEMENTS = new Set([
337
374
  'wbr',
338
375
  ]);
339
376
  function serializeNode(node) {
377
+ if (node instanceof StringRawHtml) {
378
+ return node.html;
379
+ }
340
380
  if (node instanceof StringText) {
341
381
  const text = escapeText(node.nodeValue);
342
382
  const key = hydrationKeyOf(node);
@@ -350,9 +390,11 @@ function serializeNode(node) {
350
390
  if (node instanceof StringElement) {
351
391
  const attributes = [...node.attributes]
352
392
  .sort(([left], [right]) => left.localeCompare(right))
353
- .map(([name, value]) => value === '' ? ` ${name}` : ` ${name}="${escapeAttribute(value)}"`)
393
+ .map(([name, value]) => value === ''
394
+ ? ` ${assertAttributeName(name)}`
395
+ : ` ${assertAttributeName(name)}="${escapeAttribute(value)}"`)
354
396
  .join('');
355
- const open = `<${node.localName}${attributes}>`;
397
+ const open = `<${assertTagName(node.localName)}${attributes}>`;
356
398
  if (VOID_ELEMENTS.has(node.localName))
357
399
  return open;
358
400
  return `${open}${node.childNodes.map(serializeNode).join('')}</${node.localName}>`;
@@ -369,9 +411,8 @@ function escapeText(value) {
369
411
  .replaceAll('>', '&gt;');
370
412
  }
371
413
  function escapeAttribute(value) {
372
- return escapeText(value).replaceAll('"', '&quot;');
414
+ return escapeText(value).replaceAll('"', '&quot;').replaceAll("'", '&#39;');
373
415
  }
374
416
  function escapeComment(value) {
375
417
  return value.replaceAll('--', '- -');
376
418
  }
377
- //# sourceMappingURL=string-dom.js.map
@@ -3,7 +3,9 @@ type StyleRoot = Document | ShadowRoot;
3
3
  export type CraftStyleRegistry = {
4
4
  acquire(root: StyleRoot, key: string, css: string, order: number): () => void;
5
5
  };
6
- export declare function createCraftStyleRegistry(): CraftStyleRegistry;
6
+ export declare function createCraftStyleRegistry(options?: Readonly<{
7
+ nonce?: string;
8
+ }>): CraftStyleRegistry;
7
9
  export declare const CRAFT_STYLE_REGISTRY: import("@craft-ts/core").CraftToken<CraftStyleRegistry>;
8
10
  export declare const ɵfallbackCraftStyleRegistry: CraftStyleRegistry;
9
11
  export type GenDeps_CraftStyleRegistry = GetDeps<{
@@ -11,4 +13,3 @@ export type GenDeps_CraftStyleRegistry = GetDeps<{
11
13
  provided: {};
12
14
  }>;
13
15
  export {};
14
- //# sourceMappingURL=style-registry.d.ts.map
@@ -3,7 +3,7 @@ const supportsAdoptedStyleSheets = typeof CSSStyleSheet === 'function' &&
3
3
  typeof Document !== 'undefined' &&
4
4
  'adoptedStyleSheets' in Document.prototype &&
5
5
  'replaceSync' in CSSStyleSheet.prototype;
6
- export function createCraftStyleRegistry() {
6
+ export function createCraftStyleRegistry(options = {}) {
7
7
  const roots = new WeakMap();
8
8
  function acquire(root, key, css, order) {
9
9
  let entries = roots.get(root);
@@ -26,6 +26,8 @@ export function createCraftStyleRegistry() {
26
26
  const document = root instanceof Document ? root : root.ownerDocument;
27
27
  const element = document.createElement('style');
28
28
  element.setAttribute('data-craft-sheet', key);
29
+ if (options.nonce)
30
+ element.setAttribute('nonce', options.nonce);
29
31
  element.textContent = css;
30
32
  if (root instanceof Document) {
31
33
  (root.head ?? root.documentElement).appendChild(element);
@@ -76,4 +78,3 @@ export function createCraftStyleRegistry() {
76
78
  }
77
79
  export const CRAFT_STYLE_REGISTRY = craftToken('CraftStyleRegistry');
78
80
  export const ɵfallbackCraftStyleRegistry = createCraftStyleRegistry();
79
- //# sourceMappingURL=style-registry.js.map
@@ -27,4 +27,3 @@ export interface CssScopeOptions {
27
27
  readonly limitSelector?: string;
28
28
  }
29
29
  export declare function scopeCss(scopeId: string, css: string, options?: CssScopeOptions): string;
30
- //# sourceMappingURL=style-scope.d.ts.map
@@ -258,4 +258,3 @@ export function scopeCss(scopeId, css, options = {}) {
258
258
  : '';
259
259
  return [hoisted, body].filter(Boolean).join('\n');
260
260
  }
261
- //# sourceMappingURL=style-scope.js.map
@@ -1,11 +1,11 @@
1
- import type { AnyCraftException, CraftNodeDirective, CraftLazyLoadHelpers, CatchTagExhaustiveCodesCheck, CraftSettledCodesOf, CraftSettledSourcesOf, ExtractCraftGenExceptions, ExtractCraftPendingSources, FieldValidationCasesOf, SsrMode } from '@craft-ts/core';
2
- import type { CraftComponent, CraftDirectiveTemplateDependencies, ComponentInitializationExceptionsOf, ComponentFieldExceptionsOf, CraftTemplate, ContentStylePolicy, InputValue } from '../types';
3
- import { type CraftDirective } from '../types';
4
- import type { CssVarContract, EmptyCssVarContract } from '../css-vars.type';
5
- import { CATCH_BLOCK_DIRECTIVE, type CatchBlockDirective, type CatchBlockHandlerChildren, type CatchBlockHandlers, type CatchBlockPosition } from '../block';
6
- import { type PendingBlockDirective, type PendingBlockHandlers, type PendingBlockPosition, type PendingFallback, type PendingBlockExhaustiveCheck, type PendingBlockResidualSources } from '../pending-block';
7
- import { type FieldExceptionBlockDirective, type FieldExceptionBlockExhaustiveCheck, type FieldExceptionBlockPartialCheck, type FieldExceptionBlockOptions, type FieldExceptionHandlerFieldExceptions, type FieldExceptionHandlerChildren, type FieldExceptionHandlers, type FieldValidationHandledIdentities, type FieldValidationHandledIdentitiesCarrier, type ResidualFieldValidationCases, type UnhandledFieldValidationCases } from '../field-exception-block';
8
- import type { EachSchedulePolicy, ScheduleEachDirective } from '../each-scheduling';
1
+ import type { AnyCraftException, CraftChannels, CraftChannelsCarrier, CRAFT_CHANNELS, EmptyChannels, MergeChannelUnion, CraftNodeDirective, CraftLazyLoadHelpers, CatchTagExhaustiveCodesCheck, CraftSettledCodesOf, CraftSettledSourcesOf, ExtractCraftGenExceptions, ExtractCraftPendingSources, FieldValidationCasesOf, SsrMode } from '@craft-ts/core';
2
+ import type { CraftComponent, CraftDirectiveTemplateDependencies, ComponentInitializationExceptionsOf, ComponentFieldExceptionsOf, CraftTemplate, ContentStylePolicy, InputValue } from '../types.js';
3
+ import { type CraftDirective } from '../types.js';
4
+ import type { CssVarContract, EmptyCssVarContract } from '../css-vars.type.js';
5
+ import { CATCH_NODE_DIRECTIVE, type CatchDirective, type CatchHandlerChildren, type CatchHandlers, type CatchPosition } from '../catch-node.js';
6
+ import { type PendingDirective, type PendingHandlers, type PendingPosition, type PendingFallback, type PendingExhaustiveCheck, type PendingResidualSources } from '../pending-node.js';
7
+ import { type FieldErrorDirective, type FieldErrorExhaustiveCheck, type FieldErrorPartialCheck, type FieldErrorOptions, type FieldExceptionHandlerFieldExceptions, type FieldExceptionHandlerChildren, type FieldExceptionHandlers, type FieldValidationHandledIdentities, type FieldValidationHandledIdentitiesCarrier, type ResidualFieldValidationCases, type UnhandledFieldValidationCases } from '../field-error-node.js';
8
+ import type { ForSchedulePolicy, ScheduleForDirective } from '../for-scheduling.js';
9
9
  export type CraftHostInjector = unknown;
10
10
  type HostInjector = CraftHostInjector & any;
11
11
  type CraftHostType<T> = Function & {
@@ -46,7 +46,7 @@ export type CraftNodeFieldExceptionsCarrier<Cases = never> = {
46
46
  * `yield* settled(...)`).
47
47
  *
48
48
  * It is the pending twin of {@link CraftNodeExceptionsCarrier}: sources bubble up
49
- * from children to parents until a `pendingBlock` boundary clears them, and any
49
+ * from children to parents until a `pendingNode` boundary clears them, and any
50
50
  * source still uncovered when the template reaches `craftComponent(...)` is a
51
51
  * compile error.
52
52
  */
@@ -61,8 +61,8 @@ export type CraftNodePendingCarrier<Sources extends string = string> = {
61
61
  * They travel apart from {@link CraftNodeExceptionsCarrier} on purpose:
62
62
  * `RequireCaughtComponentExceptions` fires on the children of the tag helper
63
63
  * that receives them, and a text binding has no place to host a boundary
64
- * (`span(userName)` would demand a `catchBlock` inside `span`'s own children).
65
- * These bubble silently instead, are cleared by any ancestor `catchBlock`, and
64
+ * (`span(userName)` would demand a `catchNode` inside `span`'s own children).
65
+ * These bubble silently instead, are cleared by any ancestor `catchNode`, and
66
66
  * are checked once at `craftComponent(...)`.
67
67
  */
68
68
  export type CraftNodeSettledExceptionsCarrier<Codes extends string = string> = {
@@ -100,6 +100,49 @@ export type CraftNodeChildrenCssVars<Value> = [CraftNodeChildren] extends [
100
100
  readonly nonInherited: CssVarField<CraftNodeChildrenCssVarsOf<Value>, 'nonInherited'>;
101
101
  readonly unknownCss: true extends CssVarField<CraftNodeChildrenCssVarsOf<Value>, 'unknownCss'> ? true : false;
102
102
  };
103
+ /**
104
+ * Every channel set reachable from a value the tree holds — children, or a prop
105
+ * that carries one. Recursive over arrays, since children arrive nested as
106
+ * often as flat; distributive over unions, so siblings come back as a union of
107
+ * channel sets rather than a single collapsed one.
108
+ *
109
+ * Kept raw (un-merged) on purpose: merging is what cancels obligations against
110
+ * discharges, and that must happen once, at the node that contains both sides,
111
+ * not at every level of array nesting on the way there.
112
+ */
113
+ type CraftNodeRawChannelsOf<Value, Depth extends unknown[] = []> = Depth['length'] extends 8 ? never : IsAny<Value> extends true ? never : Value extends readonly (infer Child)[] ? CraftNodeRawChannelsOf<Child, [...Depth, unknown]> : DeclaredChannelsOf<Value>;
114
+ /**
115
+ * The channel a value declares, `never` if it declares none.
116
+ *
117
+ * The `keyof` guard is load-bearing: the carrier property is optional, so a
118
+ * bare `extends CraftChannelsCarrier<infer C>` matches every type, and for a
119
+ * plain `string` child TypeScript falls back to the constraint and yields
120
+ * `CraftChannels` — whose `discharges` is `unknown`, which then erases every
121
+ * obligation in the tree through `Exclude`. Same guard the deps carrier uses.
122
+ */
123
+ type DeclaredChannelsOf<Value> = Value extends object ? typeof CRAFT_CHANNELS extends keyof Value ? Value extends CraftChannelsCarrier<infer Channels extends CraftChannels> ? Channels : never : never : never;
124
+ /** The single channel set a children list hands its parent. */
125
+ export type CraftNodeChildrenChannels<Value> = MergeChannelUnion<CraftNodeRawChannelsOf<Value>>;
126
+ /**
127
+ * What an element contributes: its own channel, its children's, and the ones
128
+ * riding on its props. Props matter because that is where a style class and a
129
+ * `provides(...)` arrive — an element that answers its child's demand does so
130
+ * through a prop, and the answer has to meet the demand here.
131
+ */
132
+ type ElementNodeChannels<Props extends object, Children extends CraftNodeChildren> = MergeChannelUnion<CraftNodeRawChannelsOf<Children> | CraftNodeRawChannelsOf<Props[keyof Props]>>;
133
+ declare const CHANNEL_PROP: unique symbol;
134
+ /**
135
+ * Props that carry a channel nothing else can reach.
136
+ *
137
+ * Only `PipedCraftNodeDirective` needs this: piping a node directive erases the
138
+ * node's props and children, so the demands it had collected would vanish. A
139
+ * phantom prop puts them back on the one path where deriving them is not
140
+ * possible — and, being keyed by a `unique symbol`, it cannot collide with an
141
+ * actual DOM property.
142
+ */
143
+ type ChannelCarryingProps<Channels extends CraftChannels> = Readonly<Record<string, unknown>> & {
144
+ readonly [CHANNEL_PROP]?: CraftChannelsCarrier<Channels>;
145
+ };
103
146
  export type CraftTextValue = string | number | bigint | boolean;
104
147
  /**
105
148
  * A text binding. Two shapes, both already supported by the renderer:
@@ -111,13 +154,13 @@ export type CraftTextValue = string | number | bigint | boolean;
111
154
  export type CraftTextBinding = (() => CraftTextValue | null | undefined) | (() => Generator<any, CraftTextValue | null | undefined, any>);
112
155
  type ElementNodeExceptions<Children extends CraftNodeChildren, Exceptions extends string> = string extends CraftNodeChildrenExceptions<Children> ? Exceptions : CraftNodeChildrenExceptions<Children>;
113
156
  /**
114
- * The async sources an element still needs a `pendingBlock` for: the ones read
157
+ * The async sources an element still needs a `pendingNode` for: the ones read
115
158
  * by its children, the ones bound to its own props, plus any inherited from a
116
159
  * node it was piped from.
117
160
  */
118
161
  type ElementNodePendingSources<Props extends object, Children extends CraftNodeChildren, PendingSources extends string> = PendingSources | CraftNodeChildrenPendingSources<Children> | CraftNodeChildrenPendingSources<Props[keyof Props]>;
119
162
  type ElementNodeSettledExceptions<Props extends object, Children extends CraftNodeChildren, SettledExceptions extends string> = SettledExceptions | CraftNodeChildrenSettledExceptions<Children> | CraftNodeChildrenSettledExceptions<Props[keyof Props]>;
120
- export interface ElementNodeBase<Dependencies extends object = {}, Tag extends string = string, Props extends object = Readonly<Record<string, unknown>>, Children extends CraftNodeChildren = CraftNodeChildren, LocalName extends string | undefined = string | undefined, Exceptions extends string = string, HandledExceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<ElementNodeExceptions<Children, Exceptions>>, CraftNodeHandledExceptionsCarrier<HandledExceptions>, CraftNodePendingCarrier<ElementNodePendingSources<Props, Children, PendingSources>>, CraftNodeSettledExceptionsCarrier<ElementNodeSettledExceptions<Props, Children, SettledExceptions>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<Children>>, CraftNodeFieldExceptionsCarrier<FieldExceptions | CraftNodeChildrenRawFieldExceptions<Children>> {
163
+ export interface ElementNodeBase<Dependencies extends object = {}, Tag extends string = string, Props extends object = Readonly<Record<string, unknown>>, Children extends CraftNodeChildren = CraftNodeChildren, LocalName extends string | undefined = string | undefined, Exceptions extends string = string, HandledExceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<ElementNodeExceptions<Children, Exceptions>>, CraftChannelsCarrier<ElementNodeChannels<Props, Children>>, CraftNodeHandledExceptionsCarrier<HandledExceptions>, CraftNodePendingCarrier<ElementNodePendingSources<Props, Children, PendingSources>>, CraftNodeSettledExceptionsCarrier<ElementNodeSettledExceptions<Props, Children, SettledExceptions>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<Children>>, CraftNodeFieldExceptionsCarrier<FieldExceptions | CraftNodeChildrenRawFieldExceptions<Children>> {
121
164
  readonly kind: 'element';
122
165
  readonly tag: Tag;
123
166
  readonly localName?: LocalName;
@@ -128,30 +171,30 @@ export interface ElementNodeBase<Dependencies extends object = {}, Tag extends s
128
171
  export interface ElementNode<Dependencies extends object = {}, Tag extends string = string, Props extends object = Readonly<Record<string, unknown>>, Children extends CraftNodeChildren = CraftNodeChildren, LocalName extends string | undefined = string | undefined, Exceptions extends string = string, HandledExceptions extends string = string, FieldExceptions = never, CssVars extends CssVarContract = EmptyCssVarContract, PendingSources extends string = never, SettledExceptions extends string = never> extends ElementNodeBase<Dependencies, Tag, Props, Children, LocalName, Exceptions, HandledExceptions, FieldExceptions, PendingSources, SettledExceptions>, CraftNodeCssVarsCarrier<CssVars> {
129
172
  readonly [CRAFT_NODE_EXCEPTIONS]: ElementNodeExceptions<Children, Exceptions>;
130
173
  readonly [CRAFT_NODE_FIELD_EXCEPTIONS]: FieldExceptions | CraftNodeChildrenRawFieldExceptions<Children>;
131
- readonly pipe: CraftNodePipe<Dependencies, ElementNodeExceptions<Children, Exceptions>, FieldExceptions | CraftNodeChildrenRawFieldExceptions<Children>, ElementNodePendingSources<Props, Children, PendingSources>, ElementNodeSettledExceptions<Props, Children, SettledExceptions>>;
174
+ readonly pipe: CraftNodePipe<Dependencies, ElementNodeExceptions<Children, Exceptions>, FieldExceptions | CraftNodeChildrenRawFieldExceptions<Children>, ElementNodePendingSources<Props, Children, PendingSources>, ElementNodeSettledExceptions<Props, Children, SettledExceptions>, ElementNodeChannels<Props, Children>>;
132
175
  }
133
- type PipedNode<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftDirective, PendingSources extends string = never, SettledExceptions extends string = never> = Directive extends PendingBlockDirective<infer Handlers extends PendingBlockHandlers | undefined, infer FallbackChildren extends CraftNodeChildren> ? PendingBlockNode<Dependencies | CraftNodeChildrenDependencies<FallbackChildren>, Exceptions | CraftNodeChildrenExceptions<FallbackChildren>, FieldExceptions | CraftNodeChildrenRawFieldExceptions<FallbackChildren>, PendingBlockResidualSources<PendingSources, Handlers> | CraftNodeChildrenPendingSources<FallbackChildren>, SettledExceptions | CraftNodeChildrenSettledExceptions<FallbackChildren>> : PipedNodeWithoutPending<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions>;
134
- type PipedNodeWithoutPending<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftDirective, PendingSources extends string, SettledExceptions extends string> = Directive extends FieldExceptionBlockDirective<infer FieldHandlers extends FieldExceptionHandlers, boolean> ? FieldExceptionBlockNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exceptions | CraftNodeChildrenExceptions<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>, ResidualFieldValidationCases<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> | FieldExceptionHandlerFieldExceptions<FieldHandlers> | Extract<FieldExceptions, FieldValidationHandledIdentitiesCarrier<any>> | FieldValidationHandledIdentitiesCarrier<FieldValidationHandledIdentities<FieldExceptions, FieldHandlers>>, FieldHandlers, PendingSources | CraftNodeChildrenPendingSources<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>, SettledExceptions | CraftNodeChildrenSettledExceptions<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>> : Directive extends CatchBlockDirective<infer Handlers extends CatchBlockHandlers> ? CatchBlockNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exclude<Exceptions, Extract<keyof Handlers, string>> | CraftNodeChildrenExceptions<CatchBlockHandlerChildren<Handlers[keyof Handlers]>>, Handlers, Directive[typeof CATCH_BLOCK_DIRECTIVE]['position'], FieldExceptions, PendingSources | CraftNodeChildrenPendingSources<CatchBlockHandlerChildren<Handlers[keyof Handlers]>>, Exclude<SettledExceptions, Extract<keyof Handlers, string>> | CraftNodeChildrenSettledExceptions<CatchBlockHandlerChildren<Handlers[keyof Handlers]>>> : CraftDirectiveNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exceptions, FieldExceptions, PendingSources, SettledExceptions>;
135
- type PipedCraftNodeDirective<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftNodeDirective<any>, PendingSources extends string = never, SettledExceptions extends string = never> = ElementNode<Dependencies, string, Readonly<Record<string, unknown>>, CraftNodeChildren, string | undefined, Exceptions, string, FieldExceptions | FieldValidationCasesOf<Directive>, EmptyCssVarContract, PendingSources, SettledExceptions>;
136
- export type CraftNodePipe<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, PendingSources extends string = never, SettledExceptions extends string = never> = {
137
- <Directive extends CraftDirective>(directive: (Directive extends ScheduleEachDirective ? never : Directive) & (Directive extends PendingBlockDirective<infer PendingHandlers extends PendingBlockHandlers | undefined, CraftNodeChildren> ? PendingHandlers extends PendingBlockHandlers ? PendingBlockExhaustiveCheck<PendingSources, PendingHandlers> : unknown : Directive extends CatchBlockDirective<infer Handlers extends CatchBlockHandlers> ? CatchTagExhaustiveCodesCheck<Exceptions | SettledExceptions, Record<Extract<keyof Handlers, string>, unknown>> : Directive extends FieldExceptionBlockDirective<infer FieldHandlers extends FieldExceptionHandlers, infer Exhaustive extends boolean> ? Exhaustive extends true ? [UnhandledFieldValidationCases<FieldExceptions>] extends [never] ? unknown : FieldExceptionBlockExhaustiveCheck<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> : [UnhandledFieldValidationCases<FieldExceptions>] extends [never] ? unknown : FieldExceptionBlockPartialCheck<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> : unknown)): PipedNode<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions>;
138
- <Directive extends CraftNodeDirective<any>>(directive: Directive): PipedCraftNodeDirective<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions>;
176
+ type PipedNode<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftDirective, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> = Directive extends PendingDirective<infer Handlers extends PendingHandlers | undefined, infer FallbackChildren extends CraftNodeChildren> ? PendingNode<Dependencies | CraftNodeChildrenDependencies<FallbackChildren>, Exceptions | CraftNodeChildrenExceptions<FallbackChildren>, FieldExceptions | CraftNodeChildrenRawFieldExceptions<FallbackChildren>, PendingResidualSources<PendingSources, Handlers> | CraftNodeChildrenPendingSources<FallbackChildren>, SettledExceptions | CraftNodeChildrenSettledExceptions<FallbackChildren>, MergeChannelUnion<Channels | CraftNodeRawChannelsOf<FallbackChildren>>> : PipedNodeWithoutPending<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions, Channels>;
177
+ type PipedNodeWithoutPending<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftDirective, PendingSources extends string, SettledExceptions extends string, Channels extends CraftChannels> = Directive extends FieldErrorDirective<infer FieldHandlers extends FieldExceptionHandlers, boolean> ? FieldErrorNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exceptions | CraftNodeChildrenExceptions<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>, ResidualFieldValidationCases<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> | FieldExceptionHandlerFieldExceptions<FieldHandlers> | Extract<FieldExceptions, FieldValidationHandledIdentitiesCarrier<any>> | FieldValidationHandledIdentitiesCarrier<FieldValidationHandledIdentities<FieldExceptions, FieldHandlers>>, FieldHandlers, PendingSources | CraftNodeChildrenPendingSources<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>, SettledExceptions | CraftNodeChildrenSettledExceptions<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>, MergeChannelUnion<Channels | CraftNodeRawChannelsOf<FieldExceptionHandlerChildren<FieldHandlers[keyof FieldHandlers]>>>> : Directive extends CatchDirective<infer Handlers extends CatchHandlers> ? CatchNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exclude<Exceptions, Extract<keyof Handlers, string>> | CraftNodeChildrenExceptions<CatchHandlerChildren<Handlers[keyof Handlers]>>, Handlers, Directive[typeof CATCH_NODE_DIRECTIVE]['position'], FieldExceptions, PendingSources | CraftNodeChildrenPendingSources<CatchHandlerChildren<Handlers[keyof Handlers]>>, Exclude<SettledExceptions, Extract<keyof Handlers, string>> | CraftNodeChildrenSettledExceptions<CatchHandlerChildren<Handlers[keyof Handlers]>>, MergeChannelUnion<Channels | CraftNodeRawChannelsOf<CatchHandlerChildren<Handlers[keyof Handlers]>>>> : CraftDirectiveNode<Dependencies | CraftDirectiveTemplateDependencies<Directive>, Exceptions, FieldExceptions, PendingSources, SettledExceptions, Channels>;
178
+ type PipedCraftNodeDirective<Dependencies extends object, Exceptions extends string, FieldExceptions, Directive extends CraftNodeDirective<any>, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> = ElementNode<Dependencies, string, ChannelCarryingProps<Channels>, CraftNodeChildren, string | undefined, Exceptions, string, FieldExceptions | FieldValidationCasesOf<Directive>, EmptyCssVarContract, PendingSources, SettledExceptions>;
179
+ export type CraftNodePipe<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> = {
180
+ <Directive extends CraftDirective>(directive: (Directive extends ScheduleForDirective ? never : Directive) & (Directive extends PendingDirective<infer Handlers extends PendingHandlers | undefined, CraftNodeChildren> ? Handlers extends PendingHandlers ? PendingExhaustiveCheck<PendingSources, Handlers> : unknown : Directive extends CatchDirective<infer Handlers extends CatchHandlers> ? CatchTagExhaustiveCodesCheck<Exceptions | SettledExceptions, Record<Extract<keyof Handlers, string>, unknown>> : Directive extends FieldErrorDirective<infer FieldHandlers extends FieldExceptionHandlers, infer Exhaustive extends boolean> ? Exhaustive extends true ? [UnhandledFieldValidationCases<FieldExceptions>] extends [never] ? unknown : FieldErrorExhaustiveCheck<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> : [UnhandledFieldValidationCases<FieldExceptions>] extends [never] ? unknown : FieldErrorPartialCheck<UnhandledFieldValidationCases<FieldExceptions>, FieldHandlers> : unknown)): PipedNode<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions, Channels>;
181
+ <Directive extends CraftNodeDirective<any>>(directive: Directive): PipedCraftNodeDirective<Dependencies, Exceptions, FieldExceptions, Directive, PendingSources, SettledExceptions, Channels>;
139
182
  (directive: CraftHostType<unknown>): CraftNode;
140
183
  };
141
- export type EachNodePipe<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, PendingSources extends string = never, SettledExceptions extends string = never, Item = unknown, Key = unknown, SourceName extends string | undefined = string | undefined, ItemChildren extends CraftNodeChildren = CraftNodeChildren, EmptyChildren extends CraftNodeChildren = CraftNodeChildren, Schedule extends EachSchedulePolicy | undefined = EachSchedulePolicy | undefined> = CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions> & {
142
- <Policy extends EachSchedulePolicy>(directive: ScheduleEachDirective<Policy>): EachNode<Item, Key, Dependencies, SourceName, ItemChildren, EmptyChildren, Policy>;
184
+ export type ForNodePipe<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, PendingSources extends string = never, SettledExceptions extends string = never, Item = unknown, Key = unknown, SourceName extends string | undefined = string | undefined, ItemChildren extends CraftNodeChildren = CraftNodeChildren, EmptyChildren extends CraftNodeChildren = CraftNodeChildren, Schedule extends ForSchedulePolicy | undefined = ForSchedulePolicy | undefined> = CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions> & {
185
+ <Policy extends ForSchedulePolicy>(directive: ScheduleForDirective<Policy>): ForNode<Item, Key, Dependencies, SourceName, ItemChildren, EmptyChildren, Policy>;
143
186
  };
144
187
  export interface AppliedCraftNodeDirective {
145
188
  readonly directive: CraftNodeDirective<any>;
146
189
  readonly inputs: Readonly<Record<string, unknown>>;
147
190
  }
148
- export interface CraftDirectiveNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
191
+ export interface CraftDirectiveNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftChannelsCarrier<Channels>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
149
192
  readonly [CRAFT_NODE_EXCEPTIONS]: Exceptions;
150
193
  readonly [CRAFT_NODE_FIELD_EXCEPTIONS]: FieldExceptions;
151
194
  readonly kind: 'directive';
152
195
  readonly node: CraftNode;
153
196
  readonly directives: readonly CraftDirective[];
154
- readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions>;
197
+ readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions, Channels>;
155
198
  }
156
199
  export interface TextNode {
157
200
  readonly kind: 'text';
@@ -166,7 +209,7 @@ export interface ReactiveTextNode {
166
209
  readonly kind: 'reactive-text';
167
210
  readonly binding: CraftTextBinding;
168
211
  }
169
- export interface ComponentNode<Props extends object = object, ComponentDeps extends object = {}, Component extends CraftComponent<any, ComponentDeps, any, any, any, any, any, any, any> = CraftComponent<any, ComponentDeps, any, any, any, any, any, any, any>, ContentDependencies extends object = ContentDependenciesFromProps<Props>, InputExceptions extends string = never, CssVars extends CssVarContract = EmptyCssVarContract, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<ComponentDeps & ContentDependencies>, CraftNodeCssVarsCarrier<CssVars>, CraftNodeExceptionsCarrier<ComponentInitializationExceptionsOf<Component> | InputExceptions>, CraftNodePendingCarrier<PendingSources | ContentPendingSourcesFromProps<Props>>, CraftNodeSettledExceptionsCarrier<SettledExceptions | ContentSettledExceptionsFromProps<Props>>, CraftNodeHeadingNeedCarrier<RemapToChildHeadingNeed<ComponentHeadingNeedOf<Component> | ContentHeadingNeedFromProps<Props>>>, CraftNodeFieldExceptionsCarrier<ComponentFieldExceptionsOf<Component> | ContentFieldExceptionsFromProps<Props>> {
212
+ export interface ComponentNode<Props extends object = object, ComponentDeps extends object = {}, Component extends CraftComponent<any, ComponentDeps, any, any, any, any, any, any, any> = CraftComponent<any, ComponentDeps, any, any, any, any, any, any, any>, ContentDependencies extends object = ContentDependenciesFromProps<Props>, InputExceptions extends string = never, CssVars extends CssVarContract = EmptyCssVarContract, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> extends CraftNodeDepsCarrier<ComponentDeps & ContentDependencies>, CraftNodeCssVarsCarrier<CssVars>, CraftChannelsCarrier<ComponentNodeChannels<Props, Channels>>, CraftNodeExceptionsCarrier<ComponentInitializationExceptionsOf<Component> | InputExceptions>, CraftNodePendingCarrier<PendingSources | ContentPendingSourcesFromProps<Props>>, CraftNodeSettledExceptionsCarrier<SettledExceptions | ContentSettledExceptionsFromProps<Props>>, CraftNodeHeadingNeedCarrier<RemapToChildHeadingNeed<ComponentHeadingNeedOf<Component> | ContentHeadingNeedFromProps<Props>>>, CraftNodeFieldExceptionsCarrier<ComponentFieldExceptionsOf<Component> | ContentFieldExceptionsFromProps<Props>> {
170
213
  readonly kind: 'component';
171
214
  readonly component: Component;
172
215
  readonly props: Props;
@@ -175,39 +218,39 @@ export interface ComponentNode<Props extends object = object, ComponentDeps exte
175
218
  readonly declarationContext?: unknown;
176
219
  readonly [CRAFT_NODE_EXCEPTIONS]: ComponentInitializationExceptionsOf<Component> | InputExceptions;
177
220
  readonly [CRAFT_NODE_FIELD_EXCEPTIONS]: ComponentFieldExceptionsOf<Component> | ContentFieldExceptionsFromProps<Props>;
178
- readonly pipe: CraftNodePipe<ComponentDeps & ContentDependencies, ComponentInitializationExceptionsOf<Component> | InputExceptions, ComponentFieldExceptionsOf<Component> | ContentFieldExceptionsFromProps<Props>, PendingSources | ContentPendingSourcesFromProps<Props>, SettledExceptions | ContentSettledExceptionsFromProps<Props>>;
221
+ readonly pipe: CraftNodePipe<ComponentDeps & ContentDependencies, ComponentInitializationExceptionsOf<Component> | InputExceptions, ComponentFieldExceptionsOf<Component> | ContentFieldExceptionsFromProps<Props>, PendingSources | ContentPendingSourcesFromProps<Props>, SettledExceptions | ContentSettledExceptionsFromProps<Props>, ComponentNodeChannels<Props, Channels>>;
179
222
  }
180
- export interface CatchBlockNode<Dependencies extends object = {}, Exceptions extends string = string, Handlers extends CatchBlockHandlers = CatchBlockHandlers, Position extends CatchBlockPosition = CatchBlockPosition, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftNodeHandledExceptionsCarrier<Extract<keyof Handlers, string>>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
181
- readonly kind: 'catch-block';
223
+ export interface CatchNode<Dependencies extends object = {}, Exceptions extends string = string, Handlers extends CatchHandlers = CatchHandlers, Position extends CatchPosition = CatchPosition, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftChannelsCarrier<Channels>, CraftNodeHandledExceptionsCarrier<Extract<keyof Handlers, string>>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
224
+ readonly kind: 'catch';
182
225
  readonly source: CraftNode;
183
226
  readonly handlers: Handlers;
184
227
  readonly position: Position;
185
228
  }
186
- export interface FieldExceptionBlockNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, Handlers extends FieldExceptionHandlers = FieldExceptionHandlers, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
187
- readonly kind: 'field-exception-block';
229
+ export interface FieldErrorNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = never, Handlers extends FieldExceptionHandlers = FieldExceptionHandlers, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftChannelsCarrier<Channels>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
230
+ readonly kind: 'field-error';
188
231
  readonly [CRAFT_NODE_FIELD_EXCEPTIONS]: FieldExceptions;
189
232
  readonly source: CraftNodeChildren;
190
233
  readonly handlers: Handlers;
191
- readonly options: Required<Pick<FieldExceptionBlockOptions, 'mode' | 'position'>> & Pick<FieldExceptionBlockOptions, 'visibility'>;
192
- readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions>;
234
+ readonly options: Required<Pick<FieldErrorOptions, 'mode' | 'position'>> & Pick<FieldErrorOptions, 'visibility'>;
235
+ readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions, Channels>;
193
236
  }
194
- export interface MatchBlockNode<Dependencies extends object = {}, Source extends ((...args: any[]) => unknown) | object = () => object | undefined, Children extends CraftNodeChildren = CraftNodeChildren, HandledExceptions extends string = string> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeHandledExceptionsCarrier<HandledExceptions>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>> {
195
- readonly kind: 'match-block';
237
+ export interface MatchNode<Dependencies extends object = {}, Source extends ((...args: any[]) => unknown) | object = () => object | undefined, Children extends CraftNodeChildren = CraftNodeChildren, HandledExceptions extends string = string> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeHandledExceptionsCarrier<HandledExceptions>, CraftChannelsCarrier<CraftNodeChildrenChannels<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>> {
238
+ readonly kind: 'match';
196
239
  readonly source: Source;
197
240
  readonly key: PropertyKey;
198
241
  readonly handlers: Record<string, (exception: AnyCraftException) => Children>;
199
242
  }
200
- export interface EachNode<Item = unknown, Key = unknown, Dependencies extends object = {}, SourceName extends string | undefined = string | undefined, ItemChildren extends CraftNodeChildren = CraftNodeChildren, EmptyChildren extends CraftNodeChildren = CraftNodeChildren, Schedule extends EachSchedulePolicy | undefined = EachSchedulePolicy | undefined> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<ItemChildren | EmptyChildren>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<ItemChildren> | CraftNodeChildrenPendingSources<EmptyChildren>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<ItemChildren> | CraftNodeChildrenSettledExceptions<EmptyChildren>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<ItemChildren> | CraftNodeChildrenHeadingNeed<EmptyChildren>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<ItemChildren> | CraftNodeChildrenRawFieldExceptions<EmptyChildren>> {
201
- readonly kind: 'each';
243
+ export interface ForNode<Item = unknown, Key = unknown, Dependencies extends object = {}, SourceName extends string | undefined = string | undefined, ItemChildren extends CraftNodeChildren = CraftNodeChildren, EmptyChildren extends CraftNodeChildren = CraftNodeChildren, Schedule extends ForSchedulePolicy | undefined = ForSchedulePolicy | undefined> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<ItemChildren | EmptyChildren>>, CraftChannelsCarrier<CraftNodeChildrenChannels<ItemChildren | EmptyChildren>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<ItemChildren> | CraftNodeChildrenPendingSources<EmptyChildren>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<ItemChildren> | CraftNodeChildrenSettledExceptions<EmptyChildren>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<ItemChildren> | CraftNodeChildrenHeadingNeed<EmptyChildren>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<ItemChildren> | CraftNodeChildrenRawFieldExceptions<EmptyChildren>> {
244
+ readonly kind: 'for';
202
245
  readonly source: readonly Item[] | null | undefined | (() => readonly Item[] | null | undefined) | (() => Generator<unknown, readonly Item[] | null | undefined, unknown>);
203
246
  readonly sourceName?: SourceName;
204
247
  readonly track: (item: Item, index: number) => Key;
205
248
  readonly empty?: () => EmptyChildren;
206
249
  readonly schedule?: Schedule;
207
250
  readonly itemTemplate: (item: InputValue<Item>, index: number) => ItemChildren;
208
- readonly pipe: EachNodePipe<Dependencies, CraftNodeChildrenExceptions<ItemChildren | EmptyChildren>, CraftNodeChildrenRawFieldExceptions<ItemChildren | EmptyChildren>, CraftNodeChildrenPendingSources<ItemChildren> | CraftNodeChildrenPendingSources<EmptyChildren>, CraftNodeChildrenSettledExceptions<ItemChildren | EmptyChildren>, Item, Key, SourceName, ItemChildren, EmptyChildren, Schedule>;
251
+ readonly pipe: ForNodePipe<Dependencies, CraftNodeChildrenExceptions<ItemChildren | EmptyChildren>, CraftNodeChildrenRawFieldExceptions<ItemChildren | EmptyChildren>, CraftNodeChildrenPendingSources<ItemChildren> | CraftNodeChildrenPendingSources<EmptyChildren>, CraftNodeChildrenSettledExceptions<ItemChildren | EmptyChildren>, Item, Key, SourceName, ItemChildren, EmptyChildren, Schedule>;
209
252
  }
210
- export interface IfBlockNode<ConditionName extends string = string, Dependencies extends object = {}, TrueChildren extends CraftNodeChildren = CraftNodeChildren, FalseChildren extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<TrueChildren | FalseChildren>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<TrueChildren> | CraftNodeChildrenPendingSources<FalseChildren>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<TrueChildren> | CraftNodeChildrenSettledExceptions<FalseChildren>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<TrueChildren> | CraftNodeChildrenHeadingNeed<FalseChildren>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<TrueChildren> | CraftNodeChildrenRawFieldExceptions<FalseChildren>> {
253
+ export interface IfNode<ConditionName extends string = string, Dependencies extends object = {}, TrueChildren extends CraftNodeChildren = CraftNodeChildren, FalseChildren extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<TrueChildren | FalseChildren>>, CraftChannelsCarrier<CraftNodeChildrenChannels<TrueChildren | FalseChildren>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<TrueChildren> | CraftNodeChildrenPendingSources<FalseChildren>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<TrueChildren> | CraftNodeChildrenSettledExceptions<FalseChildren>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<TrueChildren> | CraftNodeChildrenHeadingNeed<FalseChildren>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<TrueChildren> | CraftNodeChildrenRawFieldExceptions<FalseChildren>> {
211
254
  readonly kind: 'if';
212
255
  readonly condition: () => boolean;
213
256
  readonly conditionName: ConditionName;
@@ -218,11 +261,11 @@ export interface IfBlockNode<ConditionName extends string = string, Dependencies
218
261
  * Relative heading. The runtime picks `h1`–`h6` from the current outline
219
262
  * level. The node brands the subtree as needing a parent outline.
220
263
  */
221
- export interface HeadingNode<Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren, Props extends object = Readonly<Record<string, unknown>>, Need extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<Need>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
264
+ export interface HeadingNode<Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren, Props extends object = Readonly<Record<string, unknown>>, Need extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftChannelsCarrier<CraftNodeChildrenChannels<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<Need>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
222
265
  readonly kind: 'heading';
223
266
  readonly props: Props;
224
267
  readonly children: Children;
225
- readonly pipe: CraftNodePipe<Dependencies, CraftNodeChildrenExceptions<Children>, CraftNodeChildrenRawFieldExceptions<Children>, CraftNodeChildrenPendingSources<Children>, CraftNodeChildrenSettledExceptions<Children>>;
268
+ readonly pipe: CraftNodePipe<Dependencies, CraftNodeChildrenExceptions<Children>, CraftNodeChildrenRawFieldExceptions<Children>, CraftNodeChildrenPendingSources<Children>, CraftNodeChildrenSettledExceptions<Children>, CraftNodeChildrenChannels<Children>>;
226
269
  }
227
270
  /**
228
271
  * Increments the heading outline for its subtree without a DOM wrapper.
@@ -230,13 +273,13 @@ export interface HeadingNode<Dependencies extends object = {}, Children extends
230
273
  * `reset: true` (`headingRoot`) starts the outline at level 1 instead of
231
274
  * incrementing — used by route pages and skip-link shells.
232
275
  */
233
- export interface HeadingSectionNode<Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<never>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
276
+ export interface HeadingSectionNode<Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftChannelsCarrier<CraftNodeChildrenChannels<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<never>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
234
277
  readonly kind: 'heading-section';
235
278
  readonly reset?: boolean;
236
279
  readonly children: Children;
237
280
  }
238
281
  export type DeferTrigger = 'immediate' | 'idle' | 'viewport' | 'interaction';
239
- export interface DeferNode<Loaded = unknown, Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<Children>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
282
+ export interface DeferNode<Loaded = unknown, Dependencies extends object = {}, Children extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Children>>, CraftChannelsCarrier<CraftNodeChildrenChannels<Children>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Children>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Children>>, CraftNodeHeadingNeedCarrier<CraftNodeChildrenHeadingNeed<Children>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Children>> {
240
283
  readonly kind: 'defer';
241
284
  readonly loader: (helpers: CraftLazyLoadHelpers) => Promise<Loaded>;
242
285
  readonly resolve: (loaded: Loaded) => CraftNodeChildren;
@@ -249,18 +292,18 @@ export interface DeferNode<Loaded = unknown, Dependencies extends object = {}, C
249
292
  * A suspension boundary. Its source subtree stays mounted while it is pending —
250
293
  * hidden, not destroyed — and the fallback is inserted next to it.
251
294
  */
252
- export interface PendingBlockNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
295
+ export interface PendingNode<Dependencies extends object = {}, Exceptions extends string = string, FieldExceptions = unknown, PendingSources extends string = never, SettledExceptions extends string = never, Channels extends CraftChannels = EmptyChannels> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeExceptionsCarrier<Exceptions>, CraftChannelsCarrier<Channels>, CraftNodePendingCarrier<PendingSources>, CraftNodeSettledExceptionsCarrier<SettledExceptions>, CraftNodeFieldExceptionsCarrier<FieldExceptions> {
253
296
  readonly [CRAFT_NODE_EXCEPTIONS]: Exceptions;
254
- readonly kind: 'pending-block';
297
+ readonly kind: 'pending';
255
298
  readonly source: CraftNode;
256
- readonly handlers: PendingBlockHandlers | undefined;
299
+ readonly handlers: PendingHandlers | undefined;
257
300
  readonly fallback: PendingFallback | undefined;
258
301
  readonly reloading: PendingFallback | undefined;
259
- readonly position: PendingBlockPosition;
302
+ readonly position: PendingPosition;
260
303
  readonly ssr: SsrMode | undefined;
261
- readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions>;
304
+ readonly pipe: CraftNodePipe<Dependencies, Exceptions, FieldExceptions, PendingSources, SettledExceptions, Channels>;
262
305
  }
263
- export type CraftNode = ElementNodeBase<any> | TextNode | ReactiveTextNode | ComponentNode<any, any, any, any, any, any> | CraftDirectiveNode<any> | EachNode<any, any, any, any, any, any> | IfBlockNode<any, any, any, any> | HeadingNode<any, any, any> | HeadingSectionNode<any, any> | DeferNode<any, any, any> | CatchBlockNode<any, any> | PendingBlockNode<any, any, any, any> | FieldExceptionBlockNode<any, any, any> | MatchBlockNode<any, any> | ProjectionNode<any, any> | TemplateNode<any, any, any>;
306
+ export type CraftNode = ElementNodeBase<any> | TextNode | ReactiveTextNode | ComponentNode<any, any, any, any, any, any> | CraftDirectiveNode<any> | ForNode<any, any, any, any, any, any> | IfNode<any, any, any, any> | HeadingNode<any, any, any> | HeadingSectionNode<any, any> | DeferNode<any, any, any> | CatchNode<any, any> | PendingNode<any, any, any, any> | FieldErrorNode<any, any, any> | MatchNode<any, any> | ProjectionNode<any, any> | TemplateNode<any, any, any>;
264
307
  export type CraftNodeChild = CraftNode | {
265
308
  readonly kind: CraftNode['kind'];
266
309
  } | CraftTextValue | CraftTextBinding | null | undefined | readonly CraftNodeChild[];
@@ -277,15 +320,36 @@ export type ContentPendingSourcesFromProps<Props extends object> = CraftNodeChil
277
320
  /** Settled exceptions reachable through content a caller projects in. */
278
321
  export type ContentSettledExceptionsFromProps<Props extends object> = CraftNodeChildrenSettledExceptions<ContentChildrenFromProps<Props>>;
279
322
  export type ContentHeadingNeedFromProps<Props extends object> = CraftNodeChildrenHeadingNeed<ContentChildrenFromProps<Props>>;
323
+ /**
324
+ * What a component's own template still demands of whoever renders it — read
325
+ * off the template's return type, the same way the css-var contract is.
326
+ *
327
+ * A component boundary is not a boundary for these: an obligation the template
328
+ * could not answer internally is exactly the one the caller must answer.
329
+ *
330
+ * Computed from `Template`, never from the assembled `CraftComponent`. Going
331
+ * through the component would re-derive the whole component type at every call
332
+ * site, and since a template's children are themselves component nodes, that
333
+ * nests until TypeScript gives up with TS2589. Reading `Template` once — and
334
+ * letting each child node hand back the channel it already carries — keeps the
335
+ * work flat, which is the same reason `ComponentCssVars` is written this way.
336
+ */
337
+ export type ComponentTemplateChannels<Template> = Template extends (...args: any[]) => infer Output ? CraftNodeChildrenChannels<Output> : EmptyChannels;
338
+ /**
339
+ * A component call site merges two sources: what the component's own template
340
+ * still demands, and what the content projected into it demands — the caller
341
+ * wrote those nodes, so they are the caller's problem.
342
+ */
343
+ type ComponentNodeChannels<Props extends object, Channels extends CraftChannels> = MergeChannelUnion<Channels | CraftNodeRawChannelsOf<ContentChildrenFromProps<Props>>>;
280
344
  export type ComponentHeadingNeedOf<Component> = Component extends CraftComponent<any, any, any, any, any, any, infer Template> ? Template extends (...args: any[]) => infer Output ? CraftNodeChildrenHeadingNeed<Output> : never : never;
281
- export interface ProjectionNode<Dependencies extends object = {}, Output extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Output>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Output>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Output>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Output>> {
345
+ export interface ProjectionNode<Dependencies extends object = {}, Output extends CraftNodeChildren = CraftNodeChildren> extends CraftNodeDepsCarrier<Dependencies>, CraftNodeCssVarsCarrier<CraftNodeChildrenCssVars<Output>>, CraftChannelsCarrier<CraftNodeChildrenChannels<Output>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Output>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Output>>, CraftNodeFieldExceptionsCarrier<CraftNodeChildrenRawFieldExceptions<Output>> {
282
346
  readonly kind: 'projection';
283
347
  readonly render: () => Output;
284
348
  readonly slotName?: string;
285
349
  readonly stylePolicy: ContentStylePolicy;
286
350
  readonly declarationContext?: unknown;
287
351
  }
288
- export interface TemplateNode<Context = unknown, Output extends CraftNodeChildren = CraftNodeChildren, Dependencies extends object = CraftNodeChildrenDependencies<Output>> extends CraftNodeDepsCarrier<Dependencies>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Output>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Output>> {
352
+ export interface TemplateNode<Context = unknown, Output extends CraftNodeChildren = CraftNodeChildren, Dependencies extends object = CraftNodeChildrenDependencies<Output>> extends CraftNodeDepsCarrier<Dependencies>, CraftChannelsCarrier<CraftNodeChildrenChannels<Output>>, CraftNodePendingCarrier<CraftNodeChildrenPendingSources<Output>>, CraftNodeSettledExceptionsCarrier<CraftNodeChildrenSettledExceptions<Output>> {
289
353
  readonly __craftNodeCssVars__?: CraftNodeChildrenCssVars<Output>;
290
354
  readonly [CRAFT_NODE_FIELD_EXCEPTIONS]?: CraftNodeChildrenRawFieldExceptions<Output>;
291
355
  readonly kind: 'template';
@@ -312,19 +376,18 @@ type CraftNodeDirectHandledExceptionCodes<Value> = IsAny<Value> extends true ? n
312
376
  export type CraftNodeChildrenHandledExceptionCodes<Value> = Value extends unknown ? Value extends readonly (infer Child)[] ? CraftNodeDirectHandledExceptionCodes<Child> : CraftNodeDirectHandledExceptionCodes<Value> : never;
313
377
  /** A template child is renderable only after its component exceptions are handled. */
314
378
  type RequireCaughtInitializationExceptions<Children extends CraftNodeChildren> = IsAny<CraftNodeChildrenExceptions<Children>> extends true ? unknown : [CraftNodeChildrenExceptions<Children>] extends [never] ? unknown : {
315
- 'catchTag.exhaustive or catchBlock.exhaustive is required before rendering component exceptions': CraftNodeChildrenExceptions<Children>;
379
+ 'catchTag.exhaustive or catchNode.exhaustive is required before rendering component exceptions': CraftNodeChildrenExceptions<Children>;
316
380
  };
317
381
  type DirectComponentFieldExceptions<Value> = IsAny<Value> extends true ? never : Value extends ComponentNode<any, any, infer Component> ? ComponentFieldExceptionsOf<Component> extends infer Cases ? IsAny<Cases> extends true ? never : Cases : never : never;
318
382
  type ComponentFieldExceptionsInChildren<Value> = Value extends readonly (infer Child)[] ? DirectComponentFieldExceptions<Child> : DirectComponentFieldExceptions<Value>;
319
383
  type RequireHandledComponentFieldExceptions<Children extends CraftNodeChildren> = unknown extends ComponentFieldExceptionsInChildren<Children> ? unknown : [ComponentFieldExceptionsInChildren<Children>] extends [never] ? unknown : {
320
- 'fieldExceptionBlock.exhaustive is required before rendering component field exceptions': ComponentFieldExceptionsInChildren<Children>;
384
+ 'fieldErrorNode.exhaustive is required before rendering component field exceptions': ComponentFieldExceptionsInChildren<Children>;
321
385
  };
322
386
  export type RequireCaughtComponentExceptions<Children extends CraftNodeChildren> = RequireCaughtInitializationExceptions<Children> & RequireHandledComponentFieldExceptions<Children>;
323
387
  export declare function isCraftNode(value: unknown): value is CraftNode;
324
- export declare function pipeCraftNode(node: CraftNode, directive: CraftDirective | CraftNodeDirective<any> | ScheduleEachDirective | CraftHostType<unknown>): CraftNode;
388
+ export declare function pipeCraftNode(node: CraftNode, directive: CraftDirective | CraftNodeDirective<any> | ScheduleForDirective | CraftHostType<unknown>): CraftNode;
325
389
  export declare function mergeHostProps(base: Readonly<Record<string, unknown>>, added: Readonly<Record<string, unknown>>): Readonly<Record<string, unknown>>;
326
390
  /** Adds host properties to the first host node produced by a template. */
327
391
  export declare function applyHostPropsToChildren(children: CraftNodeChildren, props: Readonly<Record<string, unknown>> | undefined): CraftNodeChildren;
328
392
  export declare function normalizeChildren(children: CraftNodeChildren): CraftNode[];
329
393
  export {};
330
- //# sourceMappingURL=vnode.d.ts.map