@microsoft/webui-framework 0.0.18 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -70
- package/dist/decorators.d.ts +1 -0
- package/dist/decorators.js +3 -0
- package/dist/element/diff.d.ts +3 -1
- package/dist/element/diff.js +197 -90
- package/dist/element/markers.js +13 -5
- package/dist/element/types.d.ts +18 -10
- package/dist/element/types.js +3 -0
- package/dist/element.d.ts +0 -4
- package/dist/element.js +11 -69
- package/dist/hydration-mismatch.js +3 -2
- package/dist/index.js +1 -1
- package/dist/lifecycle.d.ts +17 -0
- package/dist/lifecycle.js +66 -3
- package/dist/static-host.js +20 -10
- package/dist/streaming-activation.d.ts +2 -0
- package/dist/streaming-activation.js +13 -0
- package/dist/streaming-bootstrap.d.ts +2 -0
- package/dist/streaming-bootstrap.js +48 -0
- package/dist/streaming-cleanup.d.ts +4 -0
- package/dist/streaming-cleanup.js +66 -0
- package/dist/streaming-coordinator.d.ts +7 -0
- package/dist/streaming-coordinator.js +367 -0
- package/dist/streaming-deferred.d.ts +22 -0
- package/dist/streaming-deferred.js +273 -0
- package/dist/streaming-dom.d.ts +32 -0
- package/dist/streaming-dom.js +148 -0
- package/dist/streaming-entry.d.ts +1 -0
- package/dist/streaming-entry.js +2 -0
- package/dist/streaming-install.d.ts +2 -0
- package/dist/streaming-install.js +25 -0
- package/dist/streaming-mode.d.ts +5 -0
- package/dist/streaming-mode.js +14 -0
- package/dist/streaming-protocol.d.ts +32 -0
- package/dist/streaming-protocol.js +27 -0
- package/dist/streaming.d.ts +5 -0
- package/dist/streaming.js +9 -0
- package/dist/template-element.d.ts +28 -9
- package/dist/template-element.js +448 -238
- package/dist/template-events.js +1 -1
- package/dist/template-roots.d.ts +0 -1
- package/dist/template-roots.js +0 -11
- package/dist/template-types.d.ts +7 -1
- package/dist/template.d.ts +2 -0
- package/dist/template.js +46 -19
- package/package.json +9 -3
package/dist/element/diff.js
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
function asParent(node) {
|
|
2
|
-
if (!node)
|
|
3
|
-
return null;
|
|
4
|
-
return 'childNodes' in node ? node : null;
|
|
5
|
-
}
|
|
6
1
|
export function dotWalk(cursor, path, from) {
|
|
7
2
|
let start = from;
|
|
8
3
|
for (let i = from; i <= path.length; i++) {
|
|
@@ -15,111 +10,223 @@ export function dotWalk(cursor, path, from) {
|
|
|
15
10
|
}
|
|
16
11
|
return cursor;
|
|
17
12
|
}
|
|
18
|
-
function itemKey(item, keyPath) {
|
|
19
|
-
if (keyPath === undefined || keyPath === '')
|
|
20
|
-
return null;
|
|
21
|
-
const v = dotWalk(item, keyPath, 0);
|
|
22
|
-
return v != null ? String(v) : '';
|
|
23
|
-
}
|
|
24
13
|
function itemScope(rep, item) {
|
|
25
|
-
return { name: rep.itemVar, value: item, parent: rep.scope };
|
|
14
|
+
return { name: rep.itemVar, value: item, parent: rep.scope, known: true };
|
|
26
15
|
}
|
|
27
|
-
export function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
export function createRepeatKeyState(path) {
|
|
17
|
+
return {
|
|
18
|
+
path,
|
|
19
|
+
warned: false,
|
|
20
|
+
keys: [],
|
|
21
|
+
nextKeys: [],
|
|
22
|
+
map: new Map(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function seedHydratedRepeatKeys(rep, items) {
|
|
26
|
+
const state = rep.keyState;
|
|
27
|
+
if (!state || items.length !== rep.instances.length)
|
|
34
28
|
return;
|
|
35
|
-
|
|
36
|
-
if (!rep.synced && items.length === 0 && rep.instances.length > 0)
|
|
29
|
+
if (!collectRepeatKeys(items, state))
|
|
37
30
|
return;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
rep.instances = [];
|
|
31
|
+
commitKeyIdentity(state);
|
|
32
|
+
}
|
|
33
|
+
function setItemScope(instance, item) {
|
|
34
|
+
if (!instance.scope)
|
|
44
35
|
return;
|
|
36
|
+
instance.scope.value = item;
|
|
37
|
+
instance.scope.known = true;
|
|
38
|
+
}
|
|
39
|
+
function syncPositional(host, rep, items, container) {
|
|
40
|
+
const instances = rep.instances;
|
|
41
|
+
const oldLength = instances.length;
|
|
42
|
+
const reuseCount = Math.min(oldLength, items.length);
|
|
43
|
+
let nextCount = reuseCount;
|
|
44
|
+
let created = false;
|
|
45
|
+
for (let i = 0; i < reuseCount; i += 1) {
|
|
46
|
+
setItemScope(instances[i], items[i]);
|
|
45
47
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
let nextCount = reuseCount;
|
|
53
|
-
for (let i = 0; i < reuseCount; i += 1) {
|
|
54
|
-
const entry = oldInstances[i];
|
|
55
|
-
entry.value = items[i];
|
|
56
|
-
if (entry.instance.scope)
|
|
57
|
-
entry.instance.scope.value = items[i];
|
|
58
|
-
}
|
|
59
|
-
for (let i = reuseCount; i < items.length; i += 1) {
|
|
60
|
-
const scope = itemScope(rep, items[i]);
|
|
61
|
-
const instance = host.$createBlockInstance(rep.blockIndex, scope);
|
|
62
|
-
if (instance) {
|
|
63
|
-
oldInstances[nextCount] = { key: null, value: items[i], instance };
|
|
64
|
-
nextCount += 1;
|
|
65
|
-
}
|
|
48
|
+
for (let i = reuseCount; i < items.length; i += 1) {
|
|
49
|
+
const instance = host.$createBlockInstance(rep.blockIndex, itemScope(rep, items[i]), rep.owner, container);
|
|
50
|
+
if (instance) {
|
|
51
|
+
instances[nextCount] = instance;
|
|
52
|
+
nextCount += 1;
|
|
53
|
+
created = true;
|
|
66
54
|
}
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
}
|
|
56
|
+
for (let i = reuseCount; i < oldLength; i += 1) {
|
|
57
|
+
host.$removeInstance(instances[i]);
|
|
58
|
+
}
|
|
59
|
+
instances.length = nextCount;
|
|
60
|
+
const removed = oldLength > reuseCount;
|
|
61
|
+
let cursor = rep.start;
|
|
62
|
+
for (let i = 0; i < instances.length; i += 1) {
|
|
63
|
+
cursor = host.$insertInstanceAfter(cursor, container, instances[i]);
|
|
64
|
+
}
|
|
65
|
+
for (let i = 0; i < reuseCount; i += 1) {
|
|
66
|
+
host.$updateInstance(instances[i]);
|
|
67
|
+
}
|
|
68
|
+
if (created || removed)
|
|
69
|
+
host.$changeStructure(removed ? rep.owner : undefined);
|
|
70
|
+
}
|
|
71
|
+
function readRepeatKey(item, path) {
|
|
72
|
+
if (path.length === 0)
|
|
73
|
+
return item;
|
|
74
|
+
return dotWalk(item, path, 0);
|
|
75
|
+
}
|
|
76
|
+
function isRepeatKey(value) {
|
|
77
|
+
return (typeof value === 'string' ||
|
|
78
|
+
(typeof value === 'number' && Number.isFinite(value)));
|
|
79
|
+
}
|
|
80
|
+
function collectRepeatKeys(items, state) {
|
|
81
|
+
const keys = state.nextKeys;
|
|
82
|
+
const seen = state.map;
|
|
83
|
+
keys.length = items.length;
|
|
84
|
+
seen.clear();
|
|
85
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
86
|
+
let value;
|
|
87
|
+
try {
|
|
88
|
+
value = readRepeatKey(items[i], state.path);
|
|
69
89
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
90
|
+
catch {
|
|
91
|
+
keys.length = 0;
|
|
92
|
+
seen.clear();
|
|
93
|
+
return false;
|
|
74
94
|
}
|
|
75
|
-
|
|
76
|
-
|
|
95
|
+
if (!isRepeatKey(value) || seen.has(value)) {
|
|
96
|
+
keys.length = 0;
|
|
97
|
+
seen.clear();
|
|
98
|
+
return false;
|
|
77
99
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const oldByKey = new Map();
|
|
81
|
-
for (let i = 0; i < oldInstances.length; i += 1) {
|
|
82
|
-
const entry = oldInstances[i];
|
|
83
|
-
const k = entry.key;
|
|
84
|
-
if (k != null)
|
|
85
|
-
oldByKey.set(k, entry);
|
|
100
|
+
keys[i] = value;
|
|
101
|
+
seen.set(value, null);
|
|
86
102
|
}
|
|
103
|
+
seen.clear();
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
function commitKeyIdentity(state) {
|
|
107
|
+
const oldKeys = state.keys;
|
|
108
|
+
state.keys = state.nextKeys;
|
|
109
|
+
state.nextKeys = oldKeys;
|
|
110
|
+
state.nextKeys.length = 0;
|
|
111
|
+
}
|
|
112
|
+
function clearKeyIdentity(state) {
|
|
113
|
+
state.keys.length = 0;
|
|
114
|
+
state.nextKeys.length = 0;
|
|
115
|
+
state.map.clear();
|
|
116
|
+
}
|
|
117
|
+
function warnKeyFallback(rep, state) {
|
|
118
|
+
if (state.warned)
|
|
119
|
+
return;
|
|
120
|
+
state.warned = true;
|
|
121
|
+
const key = state.path.length === 0
|
|
122
|
+
? rep.itemVar
|
|
123
|
+
: `${rep.itemVar}.${state.path}`;
|
|
124
|
+
console.warn(`[webui] repeat "${rep.collection}" produced duplicate or invalid values for child key="${key}"; using positional reconciliation`);
|
|
125
|
+
}
|
|
126
|
+
function reconcileByKey(host, rep, items, container, state) {
|
|
127
|
+
const instances = rep.instances;
|
|
128
|
+
const map = state.map;
|
|
87
129
|
let nextCount = 0;
|
|
130
|
+
let created = false;
|
|
131
|
+
let removed = false;
|
|
88
132
|
for (let i = 0; i < items.length; i += 1) {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
existing.value = item;
|
|
95
|
-
existing.key = key;
|
|
96
|
-
if (existing.instance.scope)
|
|
97
|
-
existing.instance.scope.value = item;
|
|
98
|
-
oldInstances[nextCount] = existing;
|
|
99
|
-
nextCount += 1;
|
|
133
|
+
const key = state.nextKeys[i];
|
|
134
|
+
let instance = map.get(key);
|
|
135
|
+
if (instance) {
|
|
136
|
+
map.set(key, null);
|
|
137
|
+
setItemScope(instance, items[i]);
|
|
100
138
|
}
|
|
101
139
|
else {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
140
|
+
instance = host.$createBlockInstance(rep.blockIndex, itemScope(rep, items[i]), rep.owner, container) ?? undefined;
|
|
141
|
+
if (instance)
|
|
142
|
+
created = true;
|
|
143
|
+
}
|
|
144
|
+
if (instance) {
|
|
145
|
+
instances[nextCount] = instance;
|
|
146
|
+
state.nextKeys[nextCount] = key;
|
|
147
|
+
nextCount += 1;
|
|
108
148
|
}
|
|
109
149
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
150
|
+
state.nextKeys.length = nextCount;
|
|
151
|
+
for (const instance of map.values()) {
|
|
152
|
+
if (instance) {
|
|
153
|
+
host.$removeInstance(instance);
|
|
154
|
+
removed = true;
|
|
155
|
+
}
|
|
113
156
|
}
|
|
114
|
-
oldInstances.length = nextCount;
|
|
115
157
|
let cursor = rep.start;
|
|
116
|
-
for (let i = 0; i <
|
|
117
|
-
cursor = host.$insertInstanceAfter(cursor, container,
|
|
158
|
+
for (let i = 0; i < nextCount; i += 1) {
|
|
159
|
+
cursor = host.$insertInstanceAfter(cursor, container, instances[i]);
|
|
160
|
+
}
|
|
161
|
+
for (let i = 0; i < nextCount; i += 1) {
|
|
162
|
+
if (map.get(state.nextKeys[i]) === null) {
|
|
163
|
+
host.$updateInstance(instances[i]);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
map.clear();
|
|
167
|
+
instances.length = nextCount;
|
|
168
|
+
commitKeyIdentity(state);
|
|
169
|
+
if (created || removed)
|
|
170
|
+
host.$changeStructure(removed ? rep.owner : undefined);
|
|
171
|
+
}
|
|
172
|
+
function syncKeyed(host, rep, items, container, state) {
|
|
173
|
+
if (!collectRepeatKeys(items, state)) {
|
|
174
|
+
warnKeyFallback(rep, state);
|
|
175
|
+
clearKeyIdentity(state);
|
|
176
|
+
syncPositional(host, rep, items, container);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
let sharedOrder = true;
|
|
180
|
+
const sharedLength = Math.min(state.keys.length, state.nextKeys.length);
|
|
181
|
+
for (let i = 0; sharedOrder && i < sharedLength; i += 1) {
|
|
182
|
+
sharedOrder = state.keys[i] === state.nextKeys[i];
|
|
118
183
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
|
|
184
|
+
if (state.keys.length !== rep.instances.length || sharedOrder) {
|
|
185
|
+
syncPositional(host, rep, items, container);
|
|
186
|
+
if (rep.instances.length === items.length) {
|
|
187
|
+
commitKeyIdentity(state);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
clearKeyIdentity(state);
|
|
123
191
|
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
for (let i = 0; i < state.keys.length; i += 1) {
|
|
195
|
+
state.map.set(state.keys[i], rep.instances[i]);
|
|
196
|
+
}
|
|
197
|
+
reconcileByKey(host, rep, items, container, state);
|
|
198
|
+
}
|
|
199
|
+
export function syncRepeat(host, rep) {
|
|
200
|
+
const resolved = host.$resolveValue(rep.collection, rep.scope);
|
|
201
|
+
const items = Array.isArray(resolved) ? resolved : [];
|
|
202
|
+
const container = (rep.container
|
|
203
|
+
?? rep.start?.parentNode
|
|
204
|
+
?? rep.owner.nodes[0]?.parentNode);
|
|
205
|
+
if (!container)
|
|
206
|
+
return;
|
|
207
|
+
rep.container = container;
|
|
208
|
+
if (!rep.synced
|
|
209
|
+
&& rep.instances.length > 0
|
|
210
|
+
&& !host.$hasStateRoot(rep.collection, rep.scope))
|
|
211
|
+
return;
|
|
212
|
+
rep.synced = true;
|
|
213
|
+
if (items.length === 0) {
|
|
214
|
+
const hadInstances = rep.instances.length !== 0;
|
|
215
|
+
for (let i = 0; i < rep.instances.length; i += 1) {
|
|
216
|
+
host.$removeInstance(rep.instances[i]);
|
|
217
|
+
}
|
|
218
|
+
rep.instances.length = 0;
|
|
219
|
+
if (hadInstances)
|
|
220
|
+
host.$changeStructure(rep.owner);
|
|
221
|
+
if (rep.keyState) {
|
|
222
|
+
clearKeyIdentity(rep.keyState);
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (rep.keyState) {
|
|
227
|
+
syncKeyed(host, rep, items, container, rep.keyState);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
syncPositional(host, rep, items, container);
|
|
124
231
|
}
|
|
125
232
|
}
|
package/dist/element/markers.js
CHANGED
|
@@ -6,16 +6,24 @@ const MARKER_REPEAT_ITEM = 'wi';
|
|
|
6
6
|
export function collectItemMarkers(repeatStart) {
|
|
7
7
|
const items = [];
|
|
8
8
|
let end = null;
|
|
9
|
+
let depth = 1;
|
|
9
10
|
let node = repeatStart.nextSibling;
|
|
10
11
|
while (node) {
|
|
11
12
|
if (node.nodeType === 8) {
|
|
12
13
|
const data = node.data;
|
|
13
|
-
if (data ===
|
|
14
|
-
|
|
15
|
-
break;
|
|
14
|
+
if (data === MARKER_REPEAT_START) {
|
|
15
|
+
depth++;
|
|
16
16
|
}
|
|
17
|
-
if (data ===
|
|
17
|
+
else if (data === MARKER_REPEAT_END) {
|
|
18
|
+
depth--;
|
|
19
|
+
if (depth === 0) {
|
|
20
|
+
end = node;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (data === MARKER_REPEAT_ITEM && depth === 1) {
|
|
18
25
|
items.push(node);
|
|
26
|
+
}
|
|
19
27
|
}
|
|
20
28
|
node = node.nextSibling;
|
|
21
29
|
}
|
|
@@ -28,7 +36,7 @@ export function nextElement(marker) {
|
|
|
28
36
|
return node;
|
|
29
37
|
if (node.nodeType === 8) {
|
|
30
38
|
const data = node.data;
|
|
31
|
-
if (data === MARKER_REPEAT_END || data === MARKER_REPEAT_ITEM)
|
|
39
|
+
if (data === MARKER_REPEAT_END || data === MARKER_REPEAT_ITEM || data === MARKER_COND_END)
|
|
32
40
|
return null;
|
|
33
41
|
}
|
|
34
42
|
node = node.nextSibling;
|
package/dist/element/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare const ATTR_KIND_ATTRIBUTE = 0;
|
|
|
11
11
|
export declare const ATTR_KIND_COMPLEX = 1;
|
|
12
12
|
export declare const ATTR_KIND_BOOLEAN = 2;
|
|
13
13
|
export declare const ATTR_KIND_TEMPLATE = 3;
|
|
14
|
+
export declare function hasNativeLiveProperty(element: Element, name: string): boolean;
|
|
14
15
|
export interface AttrBinding {
|
|
15
16
|
element: Element;
|
|
16
17
|
name: string;
|
|
@@ -24,9 +25,12 @@ export interface ScopeFrame {
|
|
|
24
25
|
name: string;
|
|
25
26
|
value: unknown;
|
|
26
27
|
parent?: ScopeFrame;
|
|
28
|
+
known?: boolean;
|
|
27
29
|
}
|
|
28
30
|
export interface TemplateInstance {
|
|
29
31
|
scope?: ScopeFrame;
|
|
32
|
+
parent?: TemplateInstance;
|
|
33
|
+
container: (ParentNode & Node) | null;
|
|
30
34
|
nodes: Node[];
|
|
31
35
|
texts: TextBinding[];
|
|
32
36
|
attrs: AttrBinding[];
|
|
@@ -39,8 +43,17 @@ export interface CondBinding {
|
|
|
39
43
|
blockIndex: number;
|
|
40
44
|
anchor: Comment;
|
|
41
45
|
scope?: ScopeFrame;
|
|
46
|
+
owner: TemplateInstance;
|
|
42
47
|
instance: TemplateInstance | null;
|
|
43
48
|
}
|
|
49
|
+
export type RepeatKey = string | number;
|
|
50
|
+
export interface RepeatKeyState {
|
|
51
|
+
path: string;
|
|
52
|
+
warned: boolean;
|
|
53
|
+
keys: RepeatKey[];
|
|
54
|
+
nextKeys: RepeatKey[];
|
|
55
|
+
map: Map<RepeatKey, TemplateInstance | null>;
|
|
56
|
+
}
|
|
44
57
|
export interface RepeatBinding {
|
|
45
58
|
markerId: number;
|
|
46
59
|
collection: string;
|
|
@@ -51,21 +64,16 @@ export interface RepeatBinding {
|
|
|
51
64
|
end: Comment | null;
|
|
52
65
|
scope?: ScopeFrame;
|
|
53
66
|
owner: TemplateInstance;
|
|
54
|
-
instances:
|
|
55
|
-
|
|
56
|
-
keyAttribute?: string;
|
|
57
|
-
keyPath?: string;
|
|
67
|
+
instances: TemplateInstance[];
|
|
68
|
+
keyState?: RepeatKeyState;
|
|
58
69
|
synced?: boolean;
|
|
59
70
|
}
|
|
60
|
-
export interface RepeatItemInstance {
|
|
61
|
-
key: string | null;
|
|
62
|
-
value: unknown;
|
|
63
|
-
instance: TemplateInstance;
|
|
64
|
-
}
|
|
65
71
|
export interface RepeatHost {
|
|
66
72
|
$resolveValue(path: string, scope?: ScopeFrame): unknown;
|
|
67
|
-
$
|
|
73
|
+
$hasStateRoot(path: string, scope?: ScopeFrame): boolean;
|
|
74
|
+
$createBlockInstance(blockIndex: number, scope?: ScopeFrame, parent?: TemplateInstance, container?: ParentNode & Node): TemplateInstance | null;
|
|
68
75
|
$updateInstance(instance: TemplateInstance): void;
|
|
69
76
|
$removeInstance(instance: TemplateInstance): void;
|
|
77
|
+
$changeStructure(removedFrom?: TemplateInstance): void;
|
|
70
78
|
$insertInstanceAfter(cursor: Node | null, container: ParentNode & Node, instance: TemplateInstance): Node | null;
|
|
71
79
|
}
|
package/dist/element/types.js
CHANGED
|
@@ -2,3 +2,6 @@ export const ATTR_KIND_ATTRIBUTE = 0;
|
|
|
2
2
|
export const ATTR_KIND_COMPLEX = 1;
|
|
3
3
|
export const ATTR_KIND_BOOLEAN = 2;
|
|
4
4
|
export const ATTR_KIND_TEMPLATE = 3;
|
|
5
|
+
export function hasNativeLiveProperty(element, name) {
|
|
6
|
+
return element.localName.indexOf('-') === -1 && name in element;
|
|
7
|
+
}
|
package/dist/element.d.ts
CHANGED
|
@@ -8,14 +8,10 @@ export declare class WebUIElement extends TemplateElement {
|
|
|
8
8
|
$emit(name: string, detail?: unknown): boolean;
|
|
9
9
|
protected $finalize(instance: TemplateInstance, root: Node, meta: TemplateBlockMeta, resolver: (root: Node, path: TemplateNodePath) => Node | null, scope?: ScopeFrame): void;
|
|
10
10
|
private $wireEvents;
|
|
11
|
-
private $resolveDelegatedEvents;
|
|
12
11
|
private $wireRoot;
|
|
13
|
-
private $addDelegatedEvent;
|
|
14
|
-
private $dispatchDelegatedEvent;
|
|
15
12
|
private $addEvent;
|
|
16
13
|
private $addCleanup;
|
|
17
14
|
private $callEventHandler;
|
|
18
|
-
private $callEventHandlerWithCurrentTarget;
|
|
19
15
|
private $resolveEventArgs;
|
|
20
16
|
private $resolveEventArg;
|
|
21
17
|
private $wireRefs;
|
package/dist/element.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { TemplateElement } from './template-element.js';
|
|
2
|
-
import {
|
|
2
|
+
import { attributeNameForProperty, getObservableNames, syncAttrProperties, } from './decorators.js';
|
|
3
3
|
export class WebUIElement extends TemplateElement {
|
|
4
4
|
$observableNames() {
|
|
5
5
|
return getObservableNames(this.constructor);
|
|
6
6
|
}
|
|
7
7
|
$shouldApplySSRState(key) {
|
|
8
|
-
|
|
8
|
+
const attribute = attributeNameForProperty(this.constructor, key);
|
|
9
|
+
return attribute === undefined || !this.hasAttribute(attribute);
|
|
9
10
|
}
|
|
10
11
|
$syncAuthoredAttributes() {
|
|
11
12
|
syncAttrProperties(this, this.constructor);
|
|
@@ -28,32 +29,16 @@ export class WebUIElement extends TemplateElement {
|
|
|
28
29
|
const groups = meta.eg;
|
|
29
30
|
if (!groups)
|
|
30
31
|
return;
|
|
31
|
-
const delegateTarget = this.shadowRoot ?? this;
|
|
32
32
|
for (let i = 0; i < groups.length; i++) {
|
|
33
33
|
const [eventName, bindings] = groups[i];
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const [handlerName, args, target, usesEvent] = bindings[i];
|
|
42
|
-
const el = resolver(root, target);
|
|
43
|
-
if (!el || el.nodeType !== 1)
|
|
44
|
-
continue;
|
|
45
|
-
const method = this[handlerName];
|
|
46
|
-
if (typeof method !== 'function')
|
|
47
|
-
continue;
|
|
48
|
-
entries.push({
|
|
49
|
-
target: el,
|
|
50
|
-
method: method,
|
|
51
|
-
args,
|
|
52
|
-
usesEvent: usesEvent === 1,
|
|
53
|
-
scope,
|
|
54
|
-
});
|
|
34
|
+
for (let j = 0; j < bindings.length; j++) {
|
|
35
|
+
const [handlerName, args, target] = bindings[j];
|
|
36
|
+
const el = resolver(root, target);
|
|
37
|
+
if (el && el.nodeType === 1) {
|
|
38
|
+
this.$addEvent(instance, el, eventName, handlerName, args, scope);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
55
41
|
}
|
|
56
|
-
return entries;
|
|
57
42
|
}
|
|
58
43
|
$wireRoot(instance, re) {
|
|
59
44
|
const target = this.shadowRoot ?? this;
|
|
@@ -61,27 +46,6 @@ export class WebUIElement extends TemplateElement {
|
|
|
61
46
|
this.$addEvent(instance, target, re[i][0], re[i][1], re[i][2], undefined);
|
|
62
47
|
}
|
|
63
48
|
}
|
|
64
|
-
$addDelegatedEvent(instance, target, eventName, entries) {
|
|
65
|
-
if (entries.length === 0)
|
|
66
|
-
return;
|
|
67
|
-
const listener = (event) => {
|
|
68
|
-
this.$dispatchDelegatedEvent(entries, event);
|
|
69
|
-
};
|
|
70
|
-
target.addEventListener(eventName, listener);
|
|
71
|
-
this.$addCleanup(instance, () => target.removeEventListener(eventName, listener));
|
|
72
|
-
}
|
|
73
|
-
$dispatchDelegatedEvent(entries, event) {
|
|
74
|
-
let current = event.target;
|
|
75
|
-
while (current) {
|
|
76
|
-
for (let i = 0; i < entries.length; i++) {
|
|
77
|
-
const entry = entries[i];
|
|
78
|
-
if (entry.target === current) {
|
|
79
|
-
this.$callEventHandler(entry.method, entry.args, event, entry.scope, entry.target, entry.usesEvent);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
current = current.parentNode;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
49
|
$addEvent(instance, target, eventName, handlerName, args, scope) {
|
|
86
50
|
const method = this[handlerName];
|
|
87
51
|
if (typeof method !== 'function')
|
|
@@ -93,11 +57,7 @@ export class WebUIElement extends TemplateElement {
|
|
|
93
57
|
$addCleanup(instance, cleanup) {
|
|
94
58
|
(instance.cleanups ??= []).push(cleanup);
|
|
95
59
|
}
|
|
96
|
-
$callEventHandler(method, args, event, scope
|
|
97
|
-
if (currentTarget && usesEvent) {
|
|
98
|
-
this.$callEventHandlerWithCurrentTarget(method, args, event, scope, currentTarget);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
60
|
+
$callEventHandler(method, args, event, scope) {
|
|
101
61
|
switch (args.length) {
|
|
102
62
|
case 0:
|
|
103
63
|
method.call(this);
|
|
@@ -118,24 +78,6 @@ export class WebUIElement extends TemplateElement {
|
|
|
118
78
|
method.apply(this, this.$resolveEventArgs(args, event, scope));
|
|
119
79
|
}
|
|
120
80
|
}
|
|
121
|
-
$callEventHandlerWithCurrentTarget(method, args, event, scope, currentTarget) {
|
|
122
|
-
const descriptor = Object.getOwnPropertyDescriptor(event, 'currentTarget');
|
|
123
|
-
Object.defineProperty(event, 'currentTarget', {
|
|
124
|
-
configurable: true,
|
|
125
|
-
value: currentTarget,
|
|
126
|
-
});
|
|
127
|
-
try {
|
|
128
|
-
this.$callEventHandler(method, args, event, scope);
|
|
129
|
-
}
|
|
130
|
-
finally {
|
|
131
|
-
if (descriptor) {
|
|
132
|
-
Object.defineProperty(event, 'currentTarget', descriptor);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
delete event.currentTarget;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
81
|
$resolveEventArgs(args, event, scope) {
|
|
140
82
|
const resolved = [];
|
|
141
83
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ATTR_KIND_BOOLEAN, ATTR_KIND_COMPLEX, ATTR_KIND_TEMPLATE, } from './element/types.js';
|
|
1
|
+
import { ATTR_KIND_BOOLEAN, ATTR_KIND_COMPLEX, ATTR_KIND_TEMPLATE, hasNativeLiveProperty, } from './element/types.js';
|
|
2
2
|
export function reportHydrationMismatch(tag, writes, index, ctx) {
|
|
3
3
|
const mismatched = [];
|
|
4
4
|
for (const path of writes) {
|
|
@@ -51,7 +51,8 @@ export function attrDiffersFromDom(b, ctx) {
|
|
|
51
51
|
case ATTR_KIND_TEMPLATE:
|
|
52
52
|
return (el.getAttribute(b.name) ?? '') !== ctx.resolveParts(b.parts, b.scope);
|
|
53
53
|
default: {
|
|
54
|
-
if (b.name === 'value' || b.name === 'checked' || b.name === 'selected')
|
|
54
|
+
if ((b.name === 'value' || b.name === 'checked' || b.name === 'selected')
|
|
55
|
+
&& hasNativeLiveProperty(el, b.name))
|
|
55
56
|
return false;
|
|
56
57
|
const v = ctx.resolveValue(b.path, b.scope);
|
|
57
58
|
return (el.getAttribute(b.name) ?? '') !== (v == null ? '' : String(v));
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { installTemplateElementRuntime } from './static-host.js';
|
|
2
|
-
installTemplateElementRuntime
|
|
2
|
+
setTimeout(installTemplateElementRuntime, 0);
|
|
3
3
|
export { WebUIElement } from './element.js';
|
|
4
4
|
export { observable, attr } from './decorators.js';
|
|
5
5
|
export { getTemplate, registerTemplateData } from './template.js';
|
package/dist/lifecycle.d.ts
CHANGED
|
@@ -1,2 +1,19 @@
|
|
|
1
1
|
export declare function hydrationStart(): void;
|
|
2
2
|
export declare function hydrationEnd(): void;
|
|
3
|
+
export declare function beginStreamingGate(): void;
|
|
4
|
+
export declare function abortStreamingGate(): void;
|
|
5
|
+
export declare function markBoundaryPending(): void;
|
|
6
|
+
export declare function markBoundaryCommitted(terminal: boolean): void;
|
|
7
|
+
export declare function markLateActivationPending(): void;
|
|
8
|
+
export declare function settleLateActivation(): void;
|
|
9
|
+
export declare function __getLifecycleStateForTests(): {
|
|
10
|
+
pendingCount: number;
|
|
11
|
+
started: boolean;
|
|
12
|
+
completed: boolean;
|
|
13
|
+
streamingGateActive: boolean;
|
|
14
|
+
streamingGateAborted: boolean;
|
|
15
|
+
terminalReached: boolean;
|
|
16
|
+
pendingBoundaries: number;
|
|
17
|
+
pendingLateActivations: number;
|
|
18
|
+
};
|
|
19
|
+
export declare function __resetLifecycleForTests(): void;
|