@microsoft/webui-framework 0.0.28 → 0.0.29

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.
@@ -1,6 +1,9 @@
1
1
  let cached;
2
2
  export const STREAMING_BOUNDARY_ACTIVATE = Symbol.for('microsoft.webui.boundaryActivate');
3
- export const PENDING_ROOT_CONNECTED = Symbol.for('microsoft.webui.pendingRootConnected');
3
+ export let resumeStreamingRoot;
4
+ export function registerStreamingRootResume(resume) {
5
+ resumeStreamingRoot = resume;
6
+ }
4
7
  export const STREAMED_HOST_ATTR = 'data-ws';
5
8
  export const ACTIVATION_ACTIVATED = 1;
6
9
  export const ACTIVATION_STATIC_HOST_OPT_OUT = 2;
@@ -0,0 +1,5 @@
1
+ import type { TemplateMeta } from './template-types.js';
2
+ export declare function loadTemplateHostRuntime(): Promise<void> | undefined;
3
+ export declare function prepareTemplateDefinitions(templates: Record<string, TemplateMeta>, names: readonly string[]): Promise<void> | undefined;
4
+ export declare function invalidateTemplateHostRuntime(): void;
5
+ export declare function resetTemplateHostRuntimeForTests(): void;
@@ -0,0 +1,39 @@
1
+ import { templateNeedsStaticHost } from './template-roots.js';
2
+ let generation = 0;
3
+ let installed = false;
4
+ let pending;
5
+ export function loadTemplateHostRuntime() {
6
+ if (installed)
7
+ return;
8
+ if (!pending) {
9
+ const current = generation;
10
+ pending = import('./static-host.js').then(({ installTemplateElementRuntime }) => {
11
+ if (current !== generation) {
12
+ throw new Error('[WebUI] Template-host activation was abandoned.');
13
+ }
14
+ installTemplateElementRuntime();
15
+ installed = true;
16
+ pending = undefined;
17
+ });
18
+ }
19
+ return pending;
20
+ }
21
+ export function prepareTemplateDefinitions(templates, names) {
22
+ const exclusions = window.__webui?.templateHostExclusions;
23
+ for (let i = 0; i < names.length; i++) {
24
+ const tag = names[i];
25
+ if (templateNeedsStaticHost(templates[tag]) &&
26
+ !exclusions?.has(tag) &&
27
+ !customElements.get(tag)) {
28
+ return loadTemplateHostRuntime();
29
+ }
30
+ }
31
+ }
32
+ export function invalidateTemplateHostRuntime() {
33
+ generation++;
34
+ pending = undefined;
35
+ }
36
+ export function resetTemplateHostRuntimeForTests() {
37
+ invalidateTemplateHostRuntime();
38
+ installed = false;
39
+ }
@@ -13,5 +13,6 @@ export interface TemplateStylesheetDescriptor {
13
13
  readonly type: string;
14
14
  }
15
15
  export declare function cloneTemplateContent(meta: TemplateBlockMeta): DocumentFragment;
16
+ export declare function getTemplateFragment(meta: TemplateBlockMeta): DocumentFragment;
16
17
  export declare function getTemplateStylesheets(meta: TemplateBlockMeta): readonly TemplateStylesheetDescriptor[] | undefined;
17
18
  export declare function templateHtmlMayContainLink(html: string): boolean;
@@ -1,8 +1,12 @@
1
+ import { setTemplateContent } from './trusted-types-policy.js';
1
2
  const EMPTY_STYLESHEETS = Object.freeze([]);
2
3
  const NO_LINK_STYLESHEETS = Object.freeze([]);
3
4
  const templateContentCache = new WeakMap();
4
5
  export function cloneTemplateContent(meta) {
5
- return getTemplateContent(meta).fragment.cloneNode(true);
6
+ return getTemplateFragment(meta).cloneNode(true);
7
+ }
8
+ export function getTemplateFragment(meta) {
9
+ return getTemplateContent(meta).fragment;
6
10
  }
7
11
  export function getTemplateStylesheets(meta) {
8
12
  const stylesheets = getTemplateContent(meta, true).stylesheets;
@@ -37,7 +41,7 @@ function getTemplateContent(meta, mayContainLink) {
37
41
  if (cached)
38
42
  return cached;
39
43
  const template = document.createElement('template');
40
- template.innerHTML = meta.h;
44
+ setTemplateContent(template, meta);
41
45
  const fragment = template.content;
42
46
  const stylesheets = (mayContainLink ?? templateHtmlMayContainLink(meta.h))
43
47
  ? collectStylesheetDescriptors(fragment)
@@ -1,7 +1,7 @@
1
1
  import { deferTemplateDefinition, getTemplate } from './template.js';
2
- import { cloneTemplateContent, } from './template-content.js';
2
+ import { cloneTemplateContent, getTemplateFragment, } from './template-content.js';
3
3
  import { hydrationStart, hydrationEnd } from './lifecycle.js';
4
- import { ACTIVATION_ACTIVATED, ACTIVATION_ANCESTOR_BARRIER, ACTIVATION_MISSING_TEMPLATE, ACTIVATION_STATIC_HOST_OPT_OUT, isStreamingHydrationMode, PENDING_ROOT_CONNECTED, STREAMED_HOST_ATTR, STREAMING_BOUNDARY_ACTIVATE, } from './streaming-mode.js';
4
+ import { ACTIVATION_ACTIVATED, ACTIVATION_ANCESTOR_BARRIER, ACTIVATION_MISSING_TEMPLATE, ACTIVATION_STATIC_HOST_OPT_OUT, isStreamingHydrationMode, resumeStreamingRoot, STREAMED_HOST_ATTR, STREAMING_BOUNDARY_ACTIVATE, } from './streaming-mode.js';
5
5
  import { createRepeatKeyState, seedHydratedRepeatKeys, syncRepeat, dotWalk, } from './element/diff.js';
6
6
  import { collectItemMarkers, nextElement, findByOrdinal, buildSSRIndex, collectTemplateElements, MARKER_COND_START, MARKER_COND_END, rawMarker, } from './element/markers.js';
7
7
  import { claimSsrComponentStyles, installComponentStyles, isComponentStyleMarker, } from './element/styles.js';
@@ -10,7 +10,6 @@ import { ATTR_KIND_BOOLEAN, ATTR_KIND_COMPLEX, ATTR_KIND_TEMPLATE, hasNativeLive
10
10
  import { templateHasRoot, templateRootForAttribute } from './template-roots.js';
11
11
  const DEV = typeof __WEBUI_DEV__ === 'undefined' || __WEBUI_DEV__;
12
12
  const rootTagCache = new WeakMap();
13
- const templateDOMCache = new WeakMap();
14
13
  const tplOrdinalCache = new WeakMap();
15
14
  const textMarkerBoundaryCache = new WeakMap();
16
15
  const NO_TEXT_MARKER_BOUNDARIES = new Int32Array(0);
@@ -149,15 +148,6 @@ function childNodesArray(parent) {
149
148
  result[i] = children[i];
150
149
  return result;
151
150
  }
152
- function getTemplateDom(meta) {
153
- let cached = templateDOMCache.get(meta);
154
- if (cached)
155
- return cached;
156
- const div = document.createElement('div');
157
- div.innerHTML = meta.h;
158
- templateDOMCache.set(meta, div);
159
- return div;
160
- }
161
151
  function installTemplateObservedAttributes(ctor, tagName, meta = getTemplate(tagName)) {
162
152
  if (!meta)
163
153
  return;
@@ -295,11 +285,7 @@ export class TemplateElement extends HTMLElement {
295
285
  this.$hasAncestorBoundaryState = undefined;
296
286
  }
297
287
  $resumeRetainedRoot() {
298
- const resume = this[PENDING_ROOT_CONNECTED];
299
- if (typeof resume !== 'function')
300
- return false;
301
- resume.call(this);
302
- return true;
288
+ return resumeStreamingRoot?.(this) ?? false;
303
289
  }
304
290
  static define(tagName) {
305
291
  const ctor = this;
@@ -448,7 +434,7 @@ export class TemplateElement extends HTMLElement {
448
434
  this.$applyPendingParentState(isSSR);
449
435
  }
450
436
  if (isSSR) {
451
- this.$root = this.$hydrate(root, meta, getTemplateDom(meta));
437
+ this.$root = this.$hydrate(root, meta, getTemplateFragment(meta));
452
438
  }
453
439
  else {
454
440
  clientRoot = this.$createStagingRoot(meta);
@@ -1054,31 +1040,47 @@ export class TemplateElement extends HTMLElement {
1054
1040
  this.$pendingFlush = false;
1055
1041
  return;
1056
1042
  }
1057
- if (!this.$pathIndex)
1058
- this.$buildPathIndex();
1059
- if (!this.$pathIndex)
1060
- return;
1061
- while (this.$dirtyPaths && this.$dirtyPaths.size > 0) {
1062
- const dirty = this.$dirtyPaths;
1063
- this.$dirtyPaths = null;
1064
- for (const path of dirty) {
1043
+ try {
1044
+ if (!this.$pathIndex)
1045
+ this.$buildPathIndex();
1046
+ if (!this.$pathIndex)
1047
+ return;
1048
+ while (this.$dirtyPaths && this.$dirtyPaths.size > 0) {
1049
+ const dirty = this.$dirtyPaths;
1050
+ this.$dirtyPaths = null;
1051
+ const paths = dirty.values();
1052
+ try {
1053
+ for (const path of paths) {
1054
+ if (!this.$pathIndex)
1055
+ this.$buildPathIndex();
1056
+ const entry = this.$pathIndex?.get(path);
1057
+ if (entry) {
1058
+ this.$updateBindings(entry.texts, entry.attrs, entry.conds, entry.repeats, requireKnownState);
1059
+ }
1060
+ }
1061
+ }
1062
+ catch (error) {
1063
+ for (const path of paths)
1064
+ (this.$dirtyPaths ??= new Set()).add(path);
1065
+ throw error;
1066
+ }
1065
1067
  if (!this.$pathIndex)
1066
1068
  this.$buildPathIndex();
1067
- const entry = this.$pathIndex?.get(path);
1068
- if (entry) {
1069
- this.$updateBindings(entry.texts, entry.attrs, entry.conds, entry.repeats, requireKnownState);
1069
+ if (this.$wildcardBindings) {
1070
+ const wc = this.$wildcardBindings;
1071
+ this.$updateBindings(wc.texts, wc.attrs, wc.conds, wc.repeats, requireKnownState);
1070
1072
  }
1073
+ if (!this.$pathIndex)
1074
+ this.$buildPathIndex();
1071
1075
  }
1072
- if (!this.$pathIndex)
1073
- this.$buildPathIndex();
1074
- if (this.$wildcardBindings) {
1075
- const wc = this.$wildcardBindings;
1076
- this.$updateBindings(wc.texts, wc.attrs, wc.conds, wc.repeats, requireKnownState);
1076
+ }
1077
+ finally {
1078
+ this.$pendingFlush = false;
1079
+ if (this.$dirtyPaths?.size) {
1080
+ this.$pendingFlush = true;
1081
+ queueMicrotask(() => this.$flush());
1077
1082
  }
1078
- if (!this.$pathIndex)
1079
- this.$buildPathIndex();
1080
1083
  }
1081
- this.$pendingFlush = false;
1082
1084
  }
1083
1085
  $recordPreReadyWrite(path) {
1084
1086
  if (!this.$preReadyWrites)
@@ -1391,7 +1393,7 @@ export class TemplateElement extends HTMLElement {
1391
1393
  const marker = repMarkers ? repMarkers[i] : null;
1392
1394
  const ssrParent = (marker ? marker.parentNode : ssrElements[parentIndex]) ?? ssrRoot;
1393
1395
  const blockMeta = this.$block(blockIndex);
1394
- const blockTplDom = blockMeta ? getTemplateDom(blockMeta) : null;
1396
+ const blockTplDom = blockMeta ? getTemplateFragment(blockMeta) : null;
1395
1397
  const rootTag = blockMeta
1396
1398
  && blockTplDom?.childNodes.length === 1
1397
1399
  && blockTplDom.children.length === 1
@@ -1540,7 +1542,7 @@ export class TemplateElement extends HTMLElement {
1540
1542
  }
1541
1543
  $hydrateCondContent(condAnchor, blockMeta, scope) {
1542
1544
  const rootTag = this.$rootTag(blockMeta);
1543
- const tplDom = getTemplateDom(blockMeta);
1545
+ const tplDom = getTemplateFragment(blockMeta);
1544
1546
  if (rootTag && tplDom.children.length === 1 && !this.$hasRootStructuralSlot(blockMeta)) {
1545
1547
  const el = nextElement(condAnchor);
1546
1548
  if (el) {
@@ -1871,11 +1873,11 @@ export class TemplateElement extends HTMLElement {
1871
1873
  const range = document.createRange();
1872
1874
  range.setStartAfter(b.node);
1873
1875
  range.setEndBefore(b.rawEnd);
1876
+ const fragment = val !== '' ? range.createContextualFragment(val) : undefined;
1874
1877
  range.deleteContents();
1875
1878
  let rawNodes;
1876
1879
  const rawOwner = b.rawOwner;
1877
- if (val !== '') {
1878
- const fragment = range.createContextualFragment(val);
1880
+ if (fragment) {
1879
1881
  if (rawOwner && b.node.parentNode === rawOwner.container) {
1880
1882
  rawNodes = childNodesArray(fragment);
1881
1883
  }
@@ -0,0 +1,29 @@
1
+ export type { CompiledAttrGroupMeta, CompiledAttrMeta, CompiledAttrPart, CompiledCondition, CompiledConditionFn, CompiledConditionalMeta, CompiledEventArg, CompiledEventArgs, CompiledEventBindingMeta, CompiledEventGroupMeta, SerializedCompiledCondition, TemplateCondition, CompiledTextRunMeta, TemplateBlockMeta, TemplateMeta, TemplateNodeIndex, TemplateSlot, } from './template-types.js';
2
+ import { type ComponentStyles } from './element/style-catalog.js';
3
+ import type { CompiledConditionFn, TemplateMeta } from './template-types.js';
4
+ declare let prepareResources: ((templates: Record<string, TemplateMeta>) => Promise<void> | undefined) | undefined;
5
+ type DefinitionPreparation = (templates: Record<string, TemplateMeta>, names: readonly string[]) => Promise<void> | undefined;
6
+ export declare function installTemplateResourcePreparation(prepare: NonNullable<typeof prepareResources>): void;
7
+ export declare function installTemplateDefinitionPreparation(prepare: DefinitionPreparation | null): void;
8
+ declare global {
9
+ interface WebUIRuntimeGlobal {
10
+ state?: Record<string, unknown>;
11
+ templates?: Record<string, TemplateMeta>;
12
+ templateFns?: Record<string, CompiledConditionFn[]>;
13
+ componentAssetStyles?: Record<string, readonly string[]>;
14
+ templateHostExclusions?: Set<string>;
15
+ componentStyles?: ComponentStyles;
16
+ [key: string]: unknown;
17
+ }
18
+ interface Window {
19
+ __webui?: WebUIRuntimeGlobal;
20
+ __webuiRegisterComponentStyles?: (value: unknown) => Promise<void> | undefined;
21
+ }
22
+ }
23
+ export declare function getTemplate(name: string): TemplateMeta | undefined;
24
+ export declare function getTemplateRegistry(): Record<string, TemplateMeta> | undefined;
25
+ export declare function registerTemplateData(templates: Record<string, TemplateMeta>, templateFns?: Record<string, CompiledConditionFn[]>, componentStylesValue?: ComponentStyles | unknown): void;
26
+ export declare function prepareAssetTemplateData(templates: Record<string, TemplateMeta>, templateFns?: Record<string, CompiledConditionFn[]>): void;
27
+ export declare function deferTemplateDefinition(tagName: string, ctor: Function, define: () => void): void;
28
+ export declare function releaseSSRBootstrapState(): void;
29
+ export declare function releaseNonRoutedSSRBootstrapState(): void;
@@ -0,0 +1,228 @@
1
+ import { dispatchTemplatesRegistered, templateRegistrationDetail, TEMPLATES_REGISTERED_EVENT, } from './template-events.js';
2
+ import { prepareComponentStyles, registerComponentStyles, registerPreparedComponentStyles, validateComponentStylesRegistration, } from './element/style-catalog.js';
3
+ import { registerTrustedTemplateBlock } from './trusted-types-policy.js';
4
+ const WEBUI_DATA_ID = 'webui-data';
5
+ const HYDRATION_COMPLETE_EVENT = 'webui:hydration-complete';
6
+ const TEMPLATE_FN_COUNT = Symbol.for('microsoft.webui.templateFnCount');
7
+ const normalizedTemplates = new WeakSet();
8
+ const assetNormalizedTemplates = new WeakSet();
9
+ let webuiDataLoaded = false;
10
+ function runtimeTemplateFnCount(registry) {
11
+ const count = registry[TEMPLATE_FN_COUNT];
12
+ if (typeof count === 'number')
13
+ return count;
14
+ const initialized = Object.keys(registry).length;
15
+ registry[TEMPLATE_FN_COUNT] = initialized;
16
+ return initialized;
17
+ }
18
+ const pendingTemplateDefinitions = new Map();
19
+ let prepareResources;
20
+ let prepareDefinitions;
21
+ export function installTemplateResourcePreparation(prepare) {
22
+ prepareResources = prepare;
23
+ }
24
+ export function installTemplateDefinitionPreparation(prepare) {
25
+ if (prepareDefinitions !== null)
26
+ prepareDefinitions = prepare;
27
+ }
28
+ function acceptTemplateData(templates, templateFns, componentStyles) {
29
+ validateComponentStylesRegistration(componentStyles);
30
+ prepareTemplateData(templates, templateFns);
31
+ if (componentStyles) {
32
+ registerPreparedComponentStyles(componentStyles);
33
+ }
34
+ const w = window;
35
+ if (!w.__webui)
36
+ w.__webui = {};
37
+ if (!w.__webui.templates)
38
+ w.__webui.templates = {};
39
+ const names = Object.keys(templates);
40
+ for (let i = 0; i < names.length; i++) {
41
+ const tag = names[i];
42
+ w.__webui.templates[tag] = templates[tag];
43
+ }
44
+ for (let i = 0; i < names.length; i++) {
45
+ const pending = pendingTemplateDefinitions.get(names[i]);
46
+ if (!pending)
47
+ continue;
48
+ pendingTemplateDefinitions.delete(names[i]);
49
+ pending.define();
50
+ }
51
+ return names;
52
+ }
53
+ if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
54
+ if (window.__webui?.componentStyles) {
55
+ registerComponentStyles(window.__webui.componentStyles);
56
+ }
57
+ window.addEventListener(TEMPLATES_REGISTERED_EVENT, (event) => {
58
+ const detail = templateRegistrationDetail(event);
59
+ if (!detail?.templates)
60
+ return;
61
+ const styles = detail.componentStyles === undefined
62
+ ? undefined
63
+ : prepareComponentStyles(detail.componentStyles);
64
+ const templates = detail.templates;
65
+ const names = acceptTemplateData(templates, undefined, styles);
66
+ const definitions = detail.waitUntil
67
+ ? prepareDefinitions?.(templates, names)
68
+ : undefined;
69
+ if (definitions) {
70
+ detail.waitUntil?.(definitions.then(() => prepareResources?.(templates)));
71
+ }
72
+ else {
73
+ const ready = prepareResources?.(templates);
74
+ if (ready)
75
+ detail.waitUntil?.(ready);
76
+ }
77
+ });
78
+ window.addEventListener(HYDRATION_COMPLETE_EVENT, releaseNonRoutedSSRBootstrapState, { once: true });
79
+ }
80
+ export function getTemplate(name) {
81
+ let meta = window.__webui?.templates?.[name];
82
+ if (!meta) {
83
+ loadWebUIDataBlock();
84
+ meta = window.__webui?.templates?.[name];
85
+ }
86
+ if (meta)
87
+ normalizeTemplate(name, meta);
88
+ return meta;
89
+ }
90
+ export function getTemplateRegistry() {
91
+ loadWebUIDataBlock();
92
+ return window.__webui?.templates;
93
+ }
94
+ export function registerTemplateData(templates, templateFns, componentStylesValue) {
95
+ const componentStyles = prepareComponentStyles(componentStylesValue);
96
+ if (acceptTemplateData(templates, templateFns, componentStyles).length > 0) {
97
+ dispatchTemplatesRegistered(templates);
98
+ }
99
+ }
100
+ function prepareTemplateData(templates, templateFns) {
101
+ const names = Object.keys(templates);
102
+ for (let i = 0; i < names.length; i++) {
103
+ const name = names[i];
104
+ normalizeTemplate(name, templates[name], templateFns?.[name]);
105
+ }
106
+ }
107
+ export function prepareAssetTemplateData(templates, templateFns) {
108
+ const names = Object.keys(templates);
109
+ for (let i = 0; i < names.length; i++) {
110
+ const name = names[i];
111
+ const meta = templates[name];
112
+ if (assetNormalizedTemplates.has(meta))
113
+ continue;
114
+ normalizeTemplateConditions(name, meta, templateFns?.[name] ?? []);
115
+ normalizedTemplates.add(meta);
116
+ assetNormalizedTemplates.add(meta);
117
+ }
118
+ }
119
+ export function deferTemplateDefinition(tagName, ctor, define) {
120
+ const pending = pendingTemplateDefinitions.get(tagName);
121
+ if (pending) {
122
+ if (pending.ctor === ctor) {
123
+ throw new Error(`[WebUI] <${tagName}> is already pending definition.`);
124
+ }
125
+ throw new Error(`[WebUI] <${tagName}> already has a pending authored definition.`);
126
+ }
127
+ pendingTemplateDefinitions.set(tagName, { ctor, define });
128
+ }
129
+ function loadWebUIDataBlock() {
130
+ if (webuiDataLoaded || window.__webui?.state !== undefined || typeof document === 'undefined')
131
+ return;
132
+ const el = document.getElementById(WEBUI_DATA_ID);
133
+ if (!el) {
134
+ webuiDataLoaded = true;
135
+ return;
136
+ }
137
+ const text = el.textContent;
138
+ if (text) {
139
+ const templateFns = window.__webui?.templateFns;
140
+ const componentAssetStyles = window.__webui?.componentAssetStyles;
141
+ const parsed = JSON.parse(text);
142
+ if (templateFns)
143
+ parsed.templateFns = templateFns;
144
+ if (componentAssetStyles)
145
+ parsed.componentAssetStyles = componentAssetStyles;
146
+ window.__webui = parsed;
147
+ el.remove();
148
+ webuiDataLoaded = true;
149
+ if (parsed.componentStyles !== undefined) {
150
+ registerComponentStyles(parsed.componentStyles);
151
+ }
152
+ return;
153
+ }
154
+ el.remove();
155
+ webuiDataLoaded = true;
156
+ }
157
+ export function releaseSSRBootstrapState() {
158
+ const runtime = window.__webui;
159
+ if (runtime?.state !== undefined) {
160
+ delete runtime.state;
161
+ }
162
+ }
163
+ export function releaseNonRoutedSSRBootstrapState() {
164
+ const runtime = window.__webui;
165
+ if (runtime?.chain === undefined &&
166
+ runtime?.templateHostExclusions === undefined) {
167
+ releaseSSRBootstrapState();
168
+ }
169
+ }
170
+ function normalizeTemplate(name, meta, suppliedFns) {
171
+ if (normalizedTemplates.has(meta))
172
+ return;
173
+ const runtimeFns = window.__webui?.templateFns;
174
+ const fns = suppliedFns ?? runtimeFns?.[name] ?? [];
175
+ normalizeTemplateConditions(name, meta, fns);
176
+ normalizedTemplates.add(meta);
177
+ if (suppliedFns === undefined && runtimeFns?.[name] === fns) {
178
+ let remaining = runtimeTemplateFnCount(runtimeFns);
179
+ delete runtimeFns[name];
180
+ remaining--;
181
+ runtimeFns[TEMPLATE_FN_COUNT] = remaining;
182
+ if (remaining === 0 && window.__webui) {
183
+ const liveCount = Object.keys(runtimeFns).length;
184
+ if (liveCount === 0) {
185
+ delete window.__webui.templateFns;
186
+ }
187
+ else {
188
+ runtimeFns[TEMPLATE_FN_COUNT] = liveCount;
189
+ }
190
+ }
191
+ }
192
+ }
193
+ function normalizeTemplateConditions(name, meta, fns) {
194
+ const stack = [meta];
195
+ while (stack.length > 0) {
196
+ const block = stack.pop();
197
+ if (!block)
198
+ continue;
199
+ registerTrustedTemplateBlock(block);
200
+ if (block.a) {
201
+ for (let i = 0; i < block.a.length; i++) {
202
+ const attr = block.a[i];
203
+ if (attr[1] === 2)
204
+ normalizeCondition(name, attr[2], fns);
205
+ }
206
+ }
207
+ if (block.c) {
208
+ for (let i = 0; i < block.c.length; i++) {
209
+ normalizeCondition(name, block.c[i][0], fns);
210
+ }
211
+ }
212
+ const children = block.b;
213
+ if (children) {
214
+ for (let i = 0; i < children.length; i++)
215
+ stack.push(children[i]);
216
+ }
217
+ }
218
+ }
219
+ function normalizeCondition(tagName, condition, fns) {
220
+ const first = condition[0];
221
+ if (typeof first === 'function')
222
+ return;
223
+ const fn = fns[first];
224
+ if (typeof fn !== 'function') {
225
+ throw new Error(`[WebUI] Missing condition closure ${first} for <${tagName}>.`);
226
+ }
227
+ condition[0] = fn;
228
+ }
@@ -1,25 +1 @@
1
- export type { CompiledAttrGroupMeta, CompiledAttrMeta, CompiledAttrPart, CompiledCondition, CompiledConditionFn, CompiledConditionalMeta, CompiledEventArg, CompiledEventArgs, CompiledEventBindingMeta, CompiledEventGroupMeta, SerializedCompiledCondition, TemplateCondition, CompiledTextRunMeta, TemplateBlockMeta, TemplateMeta, TemplateNodeIndex, TemplateSlot, } from './template-types.js';
2
- import { type ComponentStyles } from './element/styles.js';
3
- import type { CompiledConditionFn, TemplateMeta } from './template-types.js';
4
- declare global {
5
- interface WebUIRuntimeGlobal {
6
- state?: Record<string, unknown>;
7
- templates?: Record<string, TemplateMeta>;
8
- templateFns?: Record<string, CompiledConditionFn[]>;
9
- componentAssetStyles?: Record<string, readonly string[]>;
10
- templateHostExclusions?: Set<string>;
11
- componentStyles?: ComponentStyles;
12
- [key: string]: unknown;
13
- }
14
- interface Window {
15
- __webui?: WebUIRuntimeGlobal;
16
- __webuiRegisterComponentStyles?: (value: unknown) => Promise<void> | undefined;
17
- }
18
- }
19
- export declare function getTemplate(name: string): TemplateMeta | undefined;
20
- export declare function getTemplateRegistry(): Record<string, TemplateMeta> | undefined;
21
- export declare function registerTemplateData(templates: Record<string, TemplateMeta>, templateFns?: Record<string, CompiledConditionFn[]>, componentStylesValue?: ComponentStyles | unknown): void;
22
- export declare function prepareAssetTemplateData(templates: Record<string, TemplateMeta>, templateFns?: Record<string, CompiledConditionFn[]>): void;
23
- export declare function deferTemplateDefinition(tagName: string, ctor: Function, define: () => void): void;
24
- export declare function releaseSSRBootstrapState(): void;
25
- export declare function releaseNonRoutedSSRBootstrapState(): void;
1
+ export * from './template-registry.js';