@microsoft/webui-framework 0.0.4 → 0.0.5

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.
@@ -0,0 +1,30 @@
1
+ export declare function getObservableNames(ctor: Function): Set<string>;
2
+ /**
3
+ * Marks a property as observable. When the value changes the decorator will:
4
+ * 1. Call `this.<prop>Changed(oldValue, newValue)` if defined.
5
+ * 2. Call `this.$update(name)` if the element is connected, targeting
6
+ * only bindings that reference this property.
7
+ */
8
+ export declare function observable(target: object, name: string): void;
9
+ /**
10
+ * Like {@link observable} but also reflects to/from an HTML attribute
11
+ * (kebab-case). The decorator patches `observedAttributes` and
12
+ * `attributeChangedCallback` on the class so changes flow in both directions.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * class MyEl extends WebUIElement {
17
+ * @attr myProp = 'default';
18
+ * // syncs with attribute "my-prop"
19
+ * }
20
+ * ```
21
+ */
22
+ export interface AttrOptions {
23
+ attribute?: string;
24
+ /** When `'boolean'`, the property is `true` when the attribute is present
25
+ * and `false` when absent — matching native HTML boolean attribute semantics.
26
+ * Default is string mode (property receives the attribute string value). */
27
+ mode?: 'boolean';
28
+ }
29
+ export declare function attr(target: object, name: string): void;
30
+ export declare function attr(options: AttrOptions): (target: object, name: string) => void;
@@ -0,0 +1,95 @@
1
+ function toKebabCase(str) {
2
+ return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
3
+ }
4
+ function createReactiveProperty(proto, name) {
5
+ const backingKey = `_${name}`;
6
+ const changedKey = `${name}Changed`;
7
+ Object.defineProperty(proto, name, {
8
+ get() {
9
+ return this[backingKey];
10
+ },
11
+ set(newValue) {
12
+ const oldValue = this[backingKey];
13
+ if (oldValue === newValue) return;
14
+ this[backingKey] = newValue;
15
+ const cb = this[changedKey];
16
+ if (typeof cb === "function") {
17
+ cb.call(this, oldValue, newValue);
18
+ }
19
+ if (this.isConnected) {
20
+ const upd = this["$update"];
21
+ if (upd) upd.call(this, name);
22
+ }
23
+ },
24
+ enumerable: true,
25
+ configurable: true
26
+ });
27
+ }
28
+ const observableRegistry = /* @__PURE__ */ new WeakMap();
29
+ const EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
30
+ function getObservableNames(ctor) {
31
+ return observableRegistry.get(ctor) ?? EMPTY_SET;
32
+ }
33
+ function observable(target, name) {
34
+ const ctor = target.constructor;
35
+ if (!observableRegistry.has(ctor)) {
36
+ observableRegistry.set(ctor, /* @__PURE__ */ new Set());
37
+ }
38
+ observableRegistry.get(ctor).add(name);
39
+ createReactiveProperty(target, name);
40
+ }
41
+ const attrMap = /* @__PURE__ */ new WeakMap();
42
+ const boolAttrs = /* @__PURE__ */ new WeakMap();
43
+ function applyAttr(target, name, options) {
44
+ const proto = target;
45
+ const ctor = proto.constructor;
46
+ createReactiveProperty(proto, name);
47
+ const attrName = options?.attribute ?? toKebabCase(name);
48
+ if (!attrMap.has(ctor)) {
49
+ attrMap.set(ctor, /* @__PURE__ */ new Map());
50
+ }
51
+ attrMap.get(ctor).set(attrName, name);
52
+ if (options?.mode === "boolean") {
53
+ if (!boolAttrs.has(ctor)) {
54
+ boolAttrs.set(ctor, /* @__PURE__ */ new Set());
55
+ }
56
+ boolAttrs.get(ctor).add(attrName);
57
+ }
58
+ if (!ctor._observedAttrs) {
59
+ ctor._observedAttrs = [];
60
+ Object.defineProperty(ctor, "observedAttributes", {
61
+ get() {
62
+ return ctor._observedAttrs ?? [];
63
+ },
64
+ configurable: true
65
+ });
66
+ const origACB = proto["attributeChangedCallback"];
67
+ proto["attributeChangedCallback"] = function(attribute, oldVal, newVal) {
68
+ const map = attrMap.get(this.constructor);
69
+ const propName = map?.get(attribute);
70
+ if (propName !== void 0) {
71
+ const isBool = boolAttrs.get(this.constructor)?.has(attribute);
72
+ this[propName] = isBool ? newVal !== null : newVal;
73
+ }
74
+ if (origACB) {
75
+ origACB.call(this, attribute, oldVal, newVal);
76
+ }
77
+ };
78
+ }
79
+ ctor._observedAttrs.push(attrName);
80
+ }
81
+ function attr(targetOrOptions, name) {
82
+ if (typeof name === "string") {
83
+ applyAttr(targetOrOptions, name);
84
+ return;
85
+ }
86
+ const options = targetOrOptions;
87
+ return (target, propName) => {
88
+ applyAttr(target, propName, options);
89
+ };
90
+ }
91
+ export {
92
+ attr,
93
+ getObservableNames,
94
+ observable
95
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Keyed child reconciliation for `@for(item of items)` repeat blocks.
3
+ *
4
+ * Diff that matches old instances by key, reuses what it
5
+ * can, creates/removes the rest, then reorders DOM nodes in one forward pass.
6
+ */
7
+ import type { RepeatBinding, RepeatHost } from './types.js';
8
+ /** Resolve a dotted path from a start offset without allocating. */
9
+ export declare function dotWalk(cursor: unknown, path: string, from: number): unknown;
10
+ /**
11
+ * Resolve a dotted path against a repeat scope variable.
12
+ *
13
+ * When a binding inside `@for(item of items)` references `item.title`,
14
+ * this function looks up `title` on the current scope value.
15
+ */
16
+ export declare function resolveRepeatValue(scopeVar: string, scope: unknown, path: string): unknown;
17
+ /**
18
+ * Reconcile a repeat binding against its current collection value.
19
+ *
20
+ * Called by `$updateInstance` on every reactive update. Resolves the
21
+ * collection path, diffs old vs. new items by key, and patches the DOM.
22
+ */
23
+ export declare function syncRepeat(host: RepeatHost, rep: RepeatBinding): void;
@@ -0,0 +1,117 @@
1
+ function asParent(node) {
2
+ if (!node) return null;
3
+ return "childNodes" in node ? node : null;
4
+ }
5
+ function dotWalk(cursor, path, from) {
6
+ let start = from;
7
+ for (let i = from; i <= path.length; i++) {
8
+ if (i === path.length || path.charCodeAt(i) === 46) {
9
+ if (cursor == null || typeof cursor !== "object") return void 0;
10
+ cursor = cursor[path.slice(start, i)];
11
+ start = i + 1;
12
+ }
13
+ }
14
+ return cursor;
15
+ }
16
+ function resolveRepeatValue(scopeVar, scope, path) {
17
+ if (path === scopeVar) return scope;
18
+ if (!path.startsWith(`${scopeVar}.`)) return void 0;
19
+ return dotWalk(scope, path, scopeVar.length + 1);
20
+ }
21
+ function itemKey(item, keyPath) {
22
+ if (keyPath === void 0 || keyPath === "") return null;
23
+ const v = dotWalk(item, keyPath, 0);
24
+ return v != null ? String(v) : "";
25
+ }
26
+ function itemScope(rep, item) {
27
+ return { name: rep.itemVar, value: item, parent: rep.scope };
28
+ }
29
+ function syncRepeat(host, rep) {
30
+ const resolved = host.$resolveValue(rep.collection, rep.scope);
31
+ const items = Array.isArray(resolved) ? resolved : [];
32
+ let container = rep.container ?? (rep.start ? asParent(rep.start.parentNode) : null) ?? (rep.owner.nodes[0] ? asParent(rep.owner.nodes[0].parentNode) : null);
33
+ if (!container) return;
34
+ rep.container = container;
35
+ if (!rep.synced && items.length === 0 && rep.instances.length > 0) return;
36
+ rep.synced = true;
37
+ if (items.length === 0) {
38
+ for (let i = 0; i < rep.instances.length; i += 1) {
39
+ host.$removeInstance(rep.instances[i].instance);
40
+ }
41
+ rep.instances = [];
42
+ return;
43
+ }
44
+ const keyPath = Object.values(rep.attrMap)[0];
45
+ const hasKeys = keyPath !== void 0 && keyPath !== "";
46
+ const oldInstances = rep.instances;
47
+ if (!hasKeys) {
48
+ const next2 = [];
49
+ const reuseCount = Math.min(oldInstances.length, items.length);
50
+ for (let i = 0; i < reuseCount; i += 1) {
51
+ const entry = oldInstances[i];
52
+ entry.value = items[i];
53
+ if (entry.instance.scope) entry.instance.scope.value = items[i];
54
+ next2.push(entry);
55
+ }
56
+ for (let i = reuseCount; i < items.length; i += 1) {
57
+ const scope = itemScope(rep, items[i]);
58
+ const instance = host.$createBlockInstance(rep.blockIndex, scope);
59
+ if (instance) {
60
+ next2.push({ key: null, value: items[i], instance });
61
+ }
62
+ }
63
+ for (let i = reuseCount; i < oldInstances.length; i += 1) {
64
+ host.$removeInstance(oldInstances[i].instance);
65
+ }
66
+ rep.instances = next2;
67
+ let cursor2 = rep.start;
68
+ for (let i = 0; i < next2.length; i += 1) {
69
+ cursor2 = host.$insertInstanceAfter(cursor2, container, next2[i].instance);
70
+ }
71
+ for (let i = 0; i < next2.length; i += 1) {
72
+ host.$updateInstance(next2[i].instance);
73
+ }
74
+ return;
75
+ }
76
+ const oldByKey = /* @__PURE__ */ new Map();
77
+ for (let i = 0; i < oldInstances.length; i += 1) {
78
+ const entry = oldInstances[i];
79
+ const k = entry.key;
80
+ if (k != null) oldByKey.set(k, entry);
81
+ }
82
+ const next = [];
83
+ for (let i = 0; i < items.length; i += 1) {
84
+ const item = items[i];
85
+ const key = itemKey(item, keyPath);
86
+ const existing = key != null ? oldByKey.get(key) : void 0;
87
+ if (existing) {
88
+ oldByKey.delete(key);
89
+ existing.value = item;
90
+ existing.key = key;
91
+ if (existing.instance.scope) existing.instance.scope.value = item;
92
+ next.push(existing);
93
+ } else {
94
+ const scope = itemScope(rep, item);
95
+ const instance = host.$createBlockInstance(rep.blockIndex, scope);
96
+ if (instance) {
97
+ next.push({ key: key ?? null, value: item, instance });
98
+ }
99
+ }
100
+ }
101
+ for (const leftover of oldByKey.values()) {
102
+ host.$removeInstance(leftover.instance);
103
+ }
104
+ rep.instances = next;
105
+ let cursor = rep.start;
106
+ for (let i = 0; i < next.length; i += 1) {
107
+ cursor = host.$insertInstanceAfter(cursor, container, next[i].instance);
108
+ }
109
+ for (let i = 0; i < next.length; i += 1) {
110
+ host.$updateInstance(next[i].instance);
111
+ }
112
+ }
113
+ export {
114
+ dotWalk,
115
+ resolveRepeatValue,
116
+ syncRepeat
117
+ };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Hydration marker utilities for zero-DOM-mutation in-place hydration.
3
+ *
4
+ * The WebUI handler plugin emits lightweight HTML comment markers around
5
+ * structural boundaries (for-loops and if-conditions). These utilities
6
+ * walk markers and locate elements so the hydration path can wire
7
+ * bindings in-place without reparenting DOM nodes.
8
+ *
9
+ * Marker format:
10
+ * <!--wr--> repeat block start
11
+ * <!--/wr--> repeat block end
12
+ * <!--wi--> repeat item boundary
13
+ * <!--wc--> conditional block start
14
+ * <!--/wc--> conditional block end
15
+ */
16
+ export declare const MARKER_REPEAT_START = "wr";
17
+ export declare const MARKER_REPEAT_END = "/wr";
18
+ export declare const MARKER_COND_START = "wc";
19
+ export declare const MARKER_COND_END = "/wc";
20
+ /**
21
+ * Collect the item markers (<!--wi-->) within a repeat range.
22
+ *
23
+ * Walks siblings from the repeat start marker to the repeat end marker.
24
+ * Returns an array of <!--wi--> comment nodes that delineate items.
25
+ */
26
+ export declare function collectItemMarkers(repeatStart: Comment): {
27
+ items: Comment[];
28
+ end: Comment | null;
29
+ };
30
+ /**
31
+ * Get the next element sibling after a marker comment, skipping
32
+ * whitespace text nodes and other comments.
33
+ */
34
+ export declare function nextElement(marker: Comment): Element | null;
@@ -0,0 +1,42 @@
1
+ const MARKER_REPEAT_START = "wr";
2
+ const MARKER_REPEAT_END = "/wr";
3
+ const MARKER_COND_START = "wc";
4
+ const MARKER_COND_END = "/wc";
5
+ const MARKER_REPEAT_ITEM = "wi";
6
+ function collectItemMarkers(repeatStart) {
7
+ const items = [];
8
+ let end = null;
9
+ let node = repeatStart.nextSibling;
10
+ while (node) {
11
+ if (node.nodeType === 8) {
12
+ const data = node.data;
13
+ if (data === MARKER_REPEAT_END) {
14
+ end = node;
15
+ break;
16
+ }
17
+ if (data === MARKER_REPEAT_ITEM) items.push(node);
18
+ }
19
+ node = node.nextSibling;
20
+ }
21
+ return { items, end };
22
+ }
23
+ function nextElement(marker) {
24
+ let node = marker.nextSibling;
25
+ while (node) {
26
+ if (node.nodeType === 1) return node;
27
+ if (node.nodeType === 8) {
28
+ const data = node.data;
29
+ if (data === MARKER_REPEAT_END || data === MARKER_REPEAT_ITEM) return null;
30
+ }
31
+ node = node.nextSibling;
32
+ }
33
+ return null;
34
+ }
35
+ export {
36
+ MARKER_COND_END,
37
+ MARKER_COND_START,
38
+ MARKER_REPEAT_END,
39
+ MARKER_REPEAT_START,
40
+ collectItemMarkers,
41
+ nextElement
42
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Inject a CSS module stylesheet. Shadow DOM components get a
3
+ * constructable stylesheet on their shadow root; light DOM components
4
+ * get a `<style>` in the document head. Each specifier is processed
5
+ * once per page.
6
+ */
7
+ export declare function injectModuleStyle(specifier: string, shadowRoot: ShadowRoot | null): void;
@@ -0,0 +1,29 @@
1
+ const injectedStyles = /* @__PURE__ */ new Set();
2
+ function injectModuleStyle(specifier, shadowRoot) {
3
+ if (injectedStyles.has(specifier)) return;
4
+ injectedStyles.add(specifier);
5
+ const defs = document.querySelectorAll('style[type="module"][specifier]');
6
+ let cssText = null;
7
+ for (let i = 0; i < defs.length; i++) {
8
+ if (defs[i].getAttribute("specifier") === specifier) {
9
+ cssText = defs[i].textContent;
10
+ break;
11
+ }
12
+ }
13
+ if (!cssText) return;
14
+ if (shadowRoot) {
15
+ const sheet = new CSSStyleSheet();
16
+ sheet.replaceSync(cssText);
17
+ shadowRoot.adoptedStyleSheets = [
18
+ ...shadowRoot.adoptedStyleSheets,
19
+ sheet
20
+ ];
21
+ } else {
22
+ const style = document.createElement("style");
23
+ style.textContent = cssText;
24
+ document.head.appendChild(style);
25
+ }
26
+ }
27
+ export {
28
+ injectModuleStyle
29
+ };
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Shared runtime types for the WebUI element system.
3
+ *
4
+ * These types define the binding data structures that are created once during
5
+ * hydration and then read on every reactive update. Each binding holds a
6
+ * direct DOM node reference so that updates can patch the DOM in O(1) per
7
+ * binding without any tree walking or selector queries.
8
+ *
9
+ * ## Key concepts
10
+ *
11
+ * - **TemplateInstance** — a connected block of DOM with its bindings. The
12
+ * root component has one instance; conditionals and repeat items each get
13
+ * their own nested instance.
14
+ *
15
+ * - **ScopeFrame** — a linked-list frame for repeat variable scoping.
16
+ * `@for(item of items)` creates a frame `{ name: 'item', value, parent }`.
17
+ * Nested repeats chain frames so inner bindings can resolve outer variables.
18
+ */
19
+ import type { CompiledAttrMeta, CompiledAttrPart, CompiledCondition } from '../template.js';
20
+ /** Direct reference to a text node bound to a property path. */
21
+ export interface TextBinding {
22
+ node: Text;
23
+ path?: string;
24
+ parts?: CompiledAttrPart[];
25
+ scope?: ScopeFrame;
26
+ /** When true, the binding renders unescaped HTML via innerHTML on the
27
+ * parent element instead of setting Text.data. Corresponds to the
28
+ * triple-brace `{{{expr}}}` template syntax. */
29
+ raw?: boolean;
30
+ /** The parent element for raw bindings — innerHTML is set here. */
31
+ rawParent?: Element;
32
+ }
33
+ /** Attribute binding kind constants (matches compiled metadata). */
34
+ export declare const ATTR_KIND_ATTRIBUTE = 0;
35
+ export declare const ATTR_KIND_COMPLEX = 1;
36
+ export declare const ATTR_KIND_BOOLEAN = 2;
37
+ export declare const ATTR_KIND_TEMPLATE = 3;
38
+ /** Direct reference to an attribute binding. */
39
+ export interface AttrBinding {
40
+ element: Element;
41
+ name: string;
42
+ kind: number;
43
+ path?: string;
44
+ condition?: CompiledCondition;
45
+ parts?: CompiledAttrPart[];
46
+ scope?: ScopeFrame;
47
+ }
48
+ export interface ScopeFrame {
49
+ name: string;
50
+ value: unknown;
51
+ parent?: ScopeFrame;
52
+ }
53
+ export interface TemplateInstance {
54
+ scope?: ScopeFrame;
55
+ nodes: Node[];
56
+ texts: TextBinding[];
57
+ attrs: AttrBinding[];
58
+ conds: CondBinding[];
59
+ repeats: RepeatBinding[];
60
+ }
61
+ /** Direct reference to a conditional block with anchor + nested compiled block. */
62
+ export interface CondBinding {
63
+ condition: CompiledCondition;
64
+ blockIndex: number;
65
+ anchor: Comment;
66
+ scope?: ScopeFrame;
67
+ instance: TemplateInstance | null;
68
+ }
69
+ /** Repeat block tracking. */
70
+ export interface RepeatBinding {
71
+ markerId: number;
72
+ collection: string;
73
+ itemVar: string;
74
+ blockIndex: number;
75
+ container: (ParentNode & Node) | null;
76
+ start: Comment | null;
77
+ end: Comment | null;
78
+ scope?: ScopeFrame;
79
+ owner: TemplateInstance;
80
+ instances: RepeatItemInstance[];
81
+ rootTag: string | null;
82
+ attrMap: Record<string, string>;
83
+ rootBindings: CompiledAttrMeta[];
84
+ /** Set to true once the collection has been explicitly set by client code. */
85
+ synced?: boolean;
86
+ }
87
+ export interface RepeatItemInstance {
88
+ key: string | null;
89
+ value: unknown;
90
+ instance: TemplateInstance;
91
+ }
92
+ /**
93
+ * Minimal host interface for repeat operations.
94
+ *
95
+ * Repeat functions need access to host capabilities (value resolution,
96
+ * block lookup, instance management) without depending on the full
97
+ * WebUIElement class.
98
+ */
99
+ export interface RepeatHost {
100
+ $resolveValue(path: string, scope?: ScopeFrame): unknown;
101
+ $createBlockInstance(blockIndex: number, scope?: ScopeFrame): TemplateInstance | null;
102
+ $updateInstance(instance: TemplateInstance): void;
103
+ $removeInstance(instance: TemplateInstance): void;
104
+ $insertInstanceAfter(cursor: Node | null, container: ParentNode & Node, instance: TemplateInstance): Node | null;
105
+ }
@@ -0,0 +1,10 @@
1
+ const ATTR_KIND_ATTRIBUTE = 0;
2
+ const ATTR_KIND_COMPLEX = 1;
3
+ const ATTR_KIND_BOOLEAN = 2;
4
+ const ATTR_KIND_TEMPLATE = 3;
5
+ export {
6
+ ATTR_KIND_ATTRIBUTE,
7
+ ATTR_KIND_BOOLEAN,
8
+ ATTR_KIND_COMPLEX,
9
+ ATTR_KIND_TEMPLATE
10
+ };
@@ -0,0 +1,104 @@
1
+ import type { TemplateBlockMeta } from './template.js';
2
+ import type { ScopeFrame, TemplateInstance } from './element/types.js';
3
+ export declare class WebUIElement extends HTMLElement {
4
+ private $root;
5
+ private $meta?;
6
+ private $ready;
7
+ private $hydrated;
8
+ private $dirtyPaths;
9
+ private $pendingFlush;
10
+ /** Cached condition resolver — avoids allocating a closure per evaluation. */
11
+ private $resolver;
12
+ private $pathIndex?;
13
+ /** Bindings that reference non-observable paths — updated on every flush. */
14
+ private $wildcardBindings?;
15
+ static define(tagName: string): void;
16
+ connectedCallback(): void;
17
+ /** Mount the component after children are available. */
18
+ private $mount;
19
+ disconnectedCallback(): void;
20
+ /** Dispatch a bubbling custom event. Uses composed:true when in shadow DOM. */
21
+ $emit(name: string, detail?: unknown): boolean;
22
+ /** Populate @observable properties from router state. */
23
+ setInitialState(state: Record<string, unknown>): void;
24
+ /**
25
+ * Apply SSR state from the global `window.__webui_state` object.
26
+ *
27
+ * Passing the same props to both server render and client
28
+ * hydrate, this ensures component observables match the server-rendered
29
+ * DOM. The handler emits the state as a `<script>` tag at the end of
30
+ * the page. Only observable properties are set — unknown keys are ignored.
31
+ *
32
+ * Writes directly to the backing field (`_prop`) to avoid triggering
33
+ * reactive updates before bindings are wired.
34
+ */
35
+ private $applySSRState;
36
+ /** Reactive update — called by @observable/@attr setters. */
37
+ $update(path?: string): void;
38
+ /** Synchronously flush all queued path updates. Call this when you need
39
+ * the DOM to reflect pending property changes immediately. */
40
+ $flushUpdates(): void;
41
+ /** Flush all queued path updates. Handles re-entrant setter calls. */
42
+ private $flush;
43
+ private $resolve;
44
+ private $resolveSSR;
45
+ private $parseTemplate;
46
+ private $wire;
47
+ /**
48
+ * Hydrate SSR-rendered DOM against compiled template metadata.
49
+ *
50
+ * When pathStart=0 (default): ssrRoot is a container with children
51
+ * (top-level component hydration).
52
+ *
53
+ * When pathStart=1: ssrRoot is a block element itself (repeat item
54
+ * in-place hydration). The leading [0] wrapper segment is skipped
55
+ * so compiled paths resolve directly against the element.
56
+ */
57
+ private $hydrate;
58
+ /** Collect sibling nodes between a start marker and an end marker comment. */
59
+ private $collectBetween;
60
+ /**
61
+ * Hydrate a conditional block's content — shared by top-level and
62
+ * repeat-item conditional hydration paths.
63
+ */
64
+ private $hydrateCondContent;
65
+ /**
66
+ * Find the next marker comment with the given data among a parent's children.
67
+ * Starts searching from `after` (exclusive) if provided, or from firstChild.
68
+ */
69
+ private $findMarker;
70
+ /** Find existing SSR text node by mapping template text-node ordinal. */
71
+ private $findSSRText;
72
+ /** Extract root tag name from block metadata. */
73
+ private $rootTag;
74
+ /** Wire attribute bindings using a resolver (shared by $wire and $hydrate). */
75
+ private $wireAttrs;
76
+ /** Wire events + root events + refs (shared by $wire and $hydrate). */
77
+ private $finalize;
78
+ /** Wire events using a resolver function (works for both client and SSR). */
79
+ private $wireEvents;
80
+ /** Wire root-level events on the host element (or shadow root when present). */
81
+ private $wireRoot;
82
+ /** Attach a single event listener. */
83
+ private $addEvent;
84
+ /** Find w-ref attributes and assign to component properties. */
85
+ private $wireRefs;
86
+ /** Create an AttrBinding from compiled metadata. */
87
+ private $makeAttr;
88
+ /** Build attrMap and rootBindings for a repeat block. */
89
+ private $repeatMaps;
90
+ private $buildPathIndex;
91
+ private $updateBindings;
92
+ $updateInstance(instance: TemplateInstance): void;
93
+ private $patchText;
94
+ private $patchAttr;
95
+ private $toggleCond;
96
+ $resolveValue(path: string, scope?: ScopeFrame): unknown;
97
+ private $resolveParts;
98
+ $block(blockIndex: number): TemplateBlockMeta | undefined;
99
+ $createBlockInstance(blockIndex: number, scope?: ScopeFrame): TemplateInstance | null;
100
+ $removeInstance(instance: TemplateInstance): void;
101
+ $insertInstanceAfter(cursor: Node | null, container: ParentNode & Node, instance: TemplateInstance): Node | null;
102
+ /** Extract the single dynamic path from a compiled attr parts array. */
103
+ private $singleDynamic;
104
+ }