@jay-framework/runtime 0.5.0
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/dist/index.d.ts +481 -0
- package/dist/index.js +836 -0
- package/docs/context.md +85 -0
- package/docs/jay-element.md +81 -0
- package/docs/kindergarten.md +51 -0
- package/docs/refs.md +200 -0
- package/docs/runtime.md +310 -0
- package/package.json +43 -0
- package/readme.md +113 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => {
|
|
4
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
|
+
return value;
|
|
6
|
+
};
|
|
7
|
+
import { RandomAccessLinkedList, listCompare, ITEM_ADDED, ITEM_REMOVED } from "@jay-framework/list-compare";
|
|
8
|
+
class KindergartenGroup {
|
|
9
|
+
constructor(kindergarten) {
|
|
10
|
+
__publicField(this, "kindergarten");
|
|
11
|
+
__publicField(this, "groupListener");
|
|
12
|
+
__publicField(this, "children");
|
|
13
|
+
this.kindergarten = kindergarten;
|
|
14
|
+
this.children = /* @__PURE__ */ new Set();
|
|
15
|
+
}
|
|
16
|
+
addListener(groupListener) {
|
|
17
|
+
this.groupListener = groupListener;
|
|
18
|
+
}
|
|
19
|
+
ensureNode(node, atIndex) {
|
|
20
|
+
atIndex = atIndex || 0;
|
|
21
|
+
atIndex = atIndex < 0 ? this.children.size + 1 + atIndex : atIndex;
|
|
22
|
+
let offset = this.kindergarten.getOffsetFor(this);
|
|
23
|
+
if (this.kindergarten.parentNode.childNodes.length > offset + atIndex)
|
|
24
|
+
this.kindergarten.parentNode.insertBefore(
|
|
25
|
+
node,
|
|
26
|
+
this.kindergarten.parentNode.childNodes[offset + atIndex]
|
|
27
|
+
);
|
|
28
|
+
else {
|
|
29
|
+
this.kindergarten.parentNode.appendChild(node);
|
|
30
|
+
}
|
|
31
|
+
this.children.add(node);
|
|
32
|
+
if (this.groupListener)
|
|
33
|
+
this.groupListener.addNode(node);
|
|
34
|
+
}
|
|
35
|
+
removeNode(node) {
|
|
36
|
+
if (this.children.has(node)) {
|
|
37
|
+
this.kindergarten.parentNode.removeChild(node);
|
|
38
|
+
this.children.delete(node);
|
|
39
|
+
if (this.groupListener)
|
|
40
|
+
this.groupListener.removeNode(node);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
removeNodeAt(pos) {
|
|
44
|
+
let offset = this.kindergarten.getOffsetFor(this);
|
|
45
|
+
this.removeNode(this.kindergarten.parentNode.childNodes[offset + pos]);
|
|
46
|
+
}
|
|
47
|
+
moveNode(from, to) {
|
|
48
|
+
let offset = this.kindergarten.getOffsetFor(this);
|
|
49
|
+
let nodeToMove = this.kindergarten.parentNode.childNodes[offset + from];
|
|
50
|
+
if (to > from)
|
|
51
|
+
to += 1;
|
|
52
|
+
if (this.kindergarten.parentNode.childNodes.length > offset + to)
|
|
53
|
+
this.kindergarten.parentNode.insertBefore(
|
|
54
|
+
nodeToMove,
|
|
55
|
+
this.kindergarten.parentNode.childNodes[offset + to]
|
|
56
|
+
);
|
|
57
|
+
else {
|
|
58
|
+
this.kindergarten.parentNode.appendChild(nodeToMove);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class Kindergarten {
|
|
63
|
+
constructor(parentNode) {
|
|
64
|
+
__publicField(this, "parentNode");
|
|
65
|
+
__publicField(this, "groups", []);
|
|
66
|
+
this.parentNode = parentNode;
|
|
67
|
+
}
|
|
68
|
+
newGroup() {
|
|
69
|
+
let kindergartenGroup = new KindergartenGroup(this);
|
|
70
|
+
this.groups.push(kindergartenGroup);
|
|
71
|
+
return kindergartenGroup;
|
|
72
|
+
}
|
|
73
|
+
getOffsetFor(group) {
|
|
74
|
+
let index = 0;
|
|
75
|
+
let offset = 0;
|
|
76
|
+
while (index < this.groups.length && this.groups[index] !== group) {
|
|
77
|
+
offset += this.groups[index].children.size;
|
|
78
|
+
index = index + 1;
|
|
79
|
+
}
|
|
80
|
+
return offset;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const noopUpdate = (_newData) => {
|
|
84
|
+
};
|
|
85
|
+
const noopMount = () => {
|
|
86
|
+
};
|
|
87
|
+
let currentContext = void 0;
|
|
88
|
+
function NewContextStack(context, marker, parent) {
|
|
89
|
+
return { context, marker, parent };
|
|
90
|
+
}
|
|
91
|
+
function createJayContext() {
|
|
92
|
+
return Symbol();
|
|
93
|
+
}
|
|
94
|
+
function withContext(marker, context, callback) {
|
|
95
|
+
let aContext = NewContextStack(context, marker, currentContext);
|
|
96
|
+
try {
|
|
97
|
+
currentContext = aContext;
|
|
98
|
+
return callback();
|
|
99
|
+
} finally {
|
|
100
|
+
currentContext = aContext.parent;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function useContext(marker) {
|
|
104
|
+
let context = findContext((_) => _ === marker);
|
|
105
|
+
if (!context)
|
|
106
|
+
throw new Error();
|
|
107
|
+
return context;
|
|
108
|
+
}
|
|
109
|
+
function findContext(predicate) {
|
|
110
|
+
let aContext = currentContext;
|
|
111
|
+
while (aContext) {
|
|
112
|
+
if (predicate(aContext.marker))
|
|
113
|
+
return aContext.context;
|
|
114
|
+
aContext = aContext.parent;
|
|
115
|
+
}
|
|
116
|
+
return void 0;
|
|
117
|
+
}
|
|
118
|
+
function saveContext() {
|
|
119
|
+
return currentContext;
|
|
120
|
+
}
|
|
121
|
+
function restoreContext(savedContext, callback) {
|
|
122
|
+
let aContext = currentContext;
|
|
123
|
+
try {
|
|
124
|
+
currentContext = savedContext;
|
|
125
|
+
return callback();
|
|
126
|
+
} finally {
|
|
127
|
+
currentContext = aContext;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const CONSTRUCTION_CONTEXT_MARKER = createJayContext();
|
|
131
|
+
function currentConstructionContext() {
|
|
132
|
+
return useContext(CONSTRUCTION_CONTEXT_MARKER);
|
|
133
|
+
}
|
|
134
|
+
function wrapWithModifiedCheck(initialData, baseJayElement) {
|
|
135
|
+
let update = baseJayElement.update;
|
|
136
|
+
let current = initialData;
|
|
137
|
+
baseJayElement.update = (newData) => {
|
|
138
|
+
let isModified = newData !== current;
|
|
139
|
+
current = newData;
|
|
140
|
+
if (isModified)
|
|
141
|
+
update(current);
|
|
142
|
+
};
|
|
143
|
+
return baseJayElement;
|
|
144
|
+
}
|
|
145
|
+
class ConstructContext {
|
|
146
|
+
constructor(data, forStaticElements = true, coordinateBase = []) {
|
|
147
|
+
__publicField(this, "coordinate", (refName) => {
|
|
148
|
+
return [...this.coordinateBase, refName];
|
|
149
|
+
});
|
|
150
|
+
this.data = data;
|
|
151
|
+
this.forStaticElements = forStaticElements;
|
|
152
|
+
this.coordinateBase = coordinateBase;
|
|
153
|
+
}
|
|
154
|
+
get currData() {
|
|
155
|
+
return this.data;
|
|
156
|
+
}
|
|
157
|
+
forItem(childViewState, id) {
|
|
158
|
+
return new ConstructContext(childViewState, false, [...this.coordinateBase, id]);
|
|
159
|
+
}
|
|
160
|
+
static withRootContext(viewState, refManager, elementConstructor) {
|
|
161
|
+
let context = new ConstructContext(viewState);
|
|
162
|
+
let element2 = withContext(
|
|
163
|
+
CONSTRUCTION_CONTEXT_MARKER,
|
|
164
|
+
context,
|
|
165
|
+
() => wrapWithModifiedCheck(currentConstructionContext().currData, elementConstructor())
|
|
166
|
+
);
|
|
167
|
+
element2.mount();
|
|
168
|
+
return refManager.applyToElement(element2);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const STYLE = "style";
|
|
172
|
+
function mkRef(ref, referenced, updates, mounts, unmounts) {
|
|
173
|
+
updates.push(ref.update);
|
|
174
|
+
ref.set(referenced);
|
|
175
|
+
mounts.push(ref.mount);
|
|
176
|
+
unmounts.push(ref.unmount);
|
|
177
|
+
}
|
|
178
|
+
function childComp(compCreator, getProps, ref) {
|
|
179
|
+
let context = currentConstructionContext();
|
|
180
|
+
let childComp2 = compCreator(getProps(context.currData));
|
|
181
|
+
let updates = [(t) => childComp2.update(getProps(t))];
|
|
182
|
+
let mounts = [childComp2.mount];
|
|
183
|
+
let unmounts = [childComp2.unmount];
|
|
184
|
+
if (ref) {
|
|
185
|
+
mkRef(ref, childComp2, updates, mounts, unmounts);
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
dom: childComp2.element.dom,
|
|
189
|
+
update: normalizeUpdates(updates),
|
|
190
|
+
mount: normalizeMount(mounts),
|
|
191
|
+
unmount: normalizeMount(unmounts)
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
const PROPERTY = 1, ATTRIBUTE = 2, BOOLEAN_ATTRIBUTE = 3;
|
|
195
|
+
function isDynamicAttributeOrProperty(value) {
|
|
196
|
+
return typeof value.valueFunc === "function";
|
|
197
|
+
}
|
|
198
|
+
function dynamicAttribute(attributeValue) {
|
|
199
|
+
return { valueFunc: attributeValue, style: ATTRIBUTE };
|
|
200
|
+
}
|
|
201
|
+
function dynamicProperty(propertyValue) {
|
|
202
|
+
return { valueFunc: propertyValue, style: PROPERTY };
|
|
203
|
+
}
|
|
204
|
+
function booleanAttribute(propertyValue) {
|
|
205
|
+
return { valueFunc: propertyValue, style: BOOLEAN_ATTRIBUTE };
|
|
206
|
+
}
|
|
207
|
+
function doSetAttribute(target, key, value, attributeStyle) {
|
|
208
|
+
const isHTMLElement = target instanceof Element;
|
|
209
|
+
if (isHTMLElement && attributeStyle === ATTRIBUTE) {
|
|
210
|
+
target.setAttribute(key, value);
|
|
211
|
+
} else if (isHTMLElement && attributeStyle === BOOLEAN_ATTRIBUTE) {
|
|
212
|
+
if (value)
|
|
213
|
+
target.setAttribute(key, value);
|
|
214
|
+
else
|
|
215
|
+
target.removeAttribute(key);
|
|
216
|
+
} else
|
|
217
|
+
target[key] = value;
|
|
218
|
+
}
|
|
219
|
+
function setAttribute(target, key, value, updates) {
|
|
220
|
+
if (isDynamicAttributeOrProperty(value)) {
|
|
221
|
+
let context = currentConstructionContext();
|
|
222
|
+
let attributeValue = value.valueFunc(context.currData);
|
|
223
|
+
doSetAttribute(target, key, attributeValue, value.style);
|
|
224
|
+
updates.push((newData) => {
|
|
225
|
+
let newAttributeValue = value.valueFunc(newData);
|
|
226
|
+
if (newAttributeValue !== attributeValue)
|
|
227
|
+
doSetAttribute(target, key, newAttributeValue, value.style);
|
|
228
|
+
attributeValue = newAttributeValue;
|
|
229
|
+
});
|
|
230
|
+
} else
|
|
231
|
+
doSetAttribute(target, key, value, ATTRIBUTE);
|
|
232
|
+
}
|
|
233
|
+
function conditional(condition, elem) {
|
|
234
|
+
return {
|
|
235
|
+
condition,
|
|
236
|
+
elem: () => {
|
|
237
|
+
const createdElem = elem();
|
|
238
|
+
return typeof createdElem === "string" ? text(createdElem) : createdElem;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function isCondition(c) {
|
|
243
|
+
return c.condition !== void 0;
|
|
244
|
+
}
|
|
245
|
+
function isForEach(c) {
|
|
246
|
+
return c.elemCreator !== void 0;
|
|
247
|
+
}
|
|
248
|
+
function forEach(getItems, elemCreator, matchBy) {
|
|
249
|
+
return { getItems, elemCreator, trackBy: matchBy };
|
|
250
|
+
}
|
|
251
|
+
function applyListChanges(group, instructions) {
|
|
252
|
+
instructions.forEach((instruction) => {
|
|
253
|
+
if (instruction.action === ITEM_ADDED) {
|
|
254
|
+
group.ensureNode(instruction.elem.dom, instruction.pos);
|
|
255
|
+
instruction.elem.mount();
|
|
256
|
+
} else if (instruction.action === ITEM_REMOVED) {
|
|
257
|
+
group.removeNodeAt(instruction.pos);
|
|
258
|
+
instruction.elem.unmount();
|
|
259
|
+
} else {
|
|
260
|
+
group.moveNode(instruction.fromPos, instruction.pos);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
function mkUpdateCollection(child, group) {
|
|
265
|
+
let lastItems = [];
|
|
266
|
+
let lastItemsList = new RandomAccessLinkedList([], child.trackBy);
|
|
267
|
+
let mount = () => lastItemsList.forEach((value, attach) => attach.mount);
|
|
268
|
+
let unmount = () => lastItemsList.forEach((value, attach) => attach.unmount);
|
|
269
|
+
let parentContext = currentConstructionContext();
|
|
270
|
+
let savedContext = saveContext();
|
|
271
|
+
const update = (newData) => {
|
|
272
|
+
const items = child.getItems(newData) || [];
|
|
273
|
+
let isModified = items !== lastItems;
|
|
274
|
+
lastItems = items;
|
|
275
|
+
if (isModified) {
|
|
276
|
+
let itemsList = new RandomAccessLinkedList(items, child.trackBy);
|
|
277
|
+
let instructions = listCompare(
|
|
278
|
+
lastItemsList,
|
|
279
|
+
itemsList,
|
|
280
|
+
(item, id) => {
|
|
281
|
+
let childContext = parentContext.forItem(item, id);
|
|
282
|
+
return restoreContext(
|
|
283
|
+
savedContext,
|
|
284
|
+
() => withContext(
|
|
285
|
+
CONSTRUCTION_CONTEXT_MARKER,
|
|
286
|
+
childContext,
|
|
287
|
+
() => wrapWithModifiedCheck(
|
|
288
|
+
currentConstructionContext().currData,
|
|
289
|
+
child.elemCreator(item, id)
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
lastItemsList = itemsList;
|
|
296
|
+
applyListChanges(group, instructions);
|
|
297
|
+
itemsList.forEach((value, elem) => elem.update(value));
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
return [update, mount, unmount];
|
|
301
|
+
}
|
|
302
|
+
function mkUpdateCondition(child, group) {
|
|
303
|
+
let mount = noopMount, unmount = noopMount;
|
|
304
|
+
let lastResult = false;
|
|
305
|
+
let childElement = void 0;
|
|
306
|
+
const update = (newData) => {
|
|
307
|
+
if (!childElement) {
|
|
308
|
+
childElement = child.elem();
|
|
309
|
+
mount = () => lastResult && childElement.mount();
|
|
310
|
+
unmount = () => childElement.unmount();
|
|
311
|
+
}
|
|
312
|
+
let result = child.condition(newData);
|
|
313
|
+
if (result) {
|
|
314
|
+
if (!lastResult) {
|
|
315
|
+
group.ensureNode(childElement.dom);
|
|
316
|
+
childElement.mount();
|
|
317
|
+
}
|
|
318
|
+
childElement.update(newData);
|
|
319
|
+
} else if (lastResult) {
|
|
320
|
+
group.removeNode(childElement.dom);
|
|
321
|
+
childElement.unmount();
|
|
322
|
+
}
|
|
323
|
+
lastResult = result;
|
|
324
|
+
};
|
|
325
|
+
return [update, mount, unmount];
|
|
326
|
+
}
|
|
327
|
+
function text(content) {
|
|
328
|
+
return {
|
|
329
|
+
dom: document.createTextNode(content),
|
|
330
|
+
update: noopUpdate,
|
|
331
|
+
mount: noopMount,
|
|
332
|
+
unmount: noopMount
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function dynamicText(textContent) {
|
|
336
|
+
let context = currentConstructionContext();
|
|
337
|
+
let content = textContent(context.currData);
|
|
338
|
+
let n = document.createTextNode(content);
|
|
339
|
+
return {
|
|
340
|
+
dom: n,
|
|
341
|
+
update: (newData) => {
|
|
342
|
+
let newContent = textContent(newData);
|
|
343
|
+
if (newContent !== content)
|
|
344
|
+
n.textContent = newContent;
|
|
345
|
+
content = newContent;
|
|
346
|
+
},
|
|
347
|
+
mount: noopMount,
|
|
348
|
+
unmount: noopMount
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const elementNS = (ns) => (tagName, attributes, children = [], ref) => {
|
|
352
|
+
let { e, updates, mounts, unmounts } = createBaseElement(ns, tagName, attributes, ref);
|
|
353
|
+
children.forEach((child) => {
|
|
354
|
+
if (typeof child === "string")
|
|
355
|
+
child = text(child);
|
|
356
|
+
e.append(child.dom);
|
|
357
|
+
if (child.update !== noopUpdate)
|
|
358
|
+
updates.push(child.update);
|
|
359
|
+
if (child.mount !== noopMount) {
|
|
360
|
+
mounts.push(child.mount);
|
|
361
|
+
unmounts.push(child.unmount);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
return {
|
|
365
|
+
dom: e,
|
|
366
|
+
update: normalizeUpdates(updates),
|
|
367
|
+
mount: normalizeMount(mounts),
|
|
368
|
+
unmount: normalizeMount(unmounts)
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
const HTML = "http://www.w3.org/1999/xhtml";
|
|
372
|
+
const SVG = "http://www.w3.org/2000/svg";
|
|
373
|
+
const MathML = "http://www.w3.org/1998/Math/MathML";
|
|
374
|
+
const element = elementNS(HTML);
|
|
375
|
+
const svgElement = elementNS(SVG);
|
|
376
|
+
const mathMLElement = elementNS(MathML);
|
|
377
|
+
const dynamicElementNS = (ns) => (tagName, attributes, children = [], ref) => {
|
|
378
|
+
let { e, updates, mounts, unmounts } = createBaseElement(ns, tagName, attributes, ref);
|
|
379
|
+
let kindergarten = new Kindergarten(e);
|
|
380
|
+
children.forEach((child) => {
|
|
381
|
+
if (typeof child === "string")
|
|
382
|
+
child = text(child);
|
|
383
|
+
let group = kindergarten.newGroup();
|
|
384
|
+
let update = noopUpdate, mount = noopMount, unmount = noopMount;
|
|
385
|
+
if (isCondition(child)) {
|
|
386
|
+
[update, mount, unmount] = mkUpdateCondition(child, group);
|
|
387
|
+
} else if (isForEach(child)) {
|
|
388
|
+
[update, mount, unmount] = mkUpdateCollection(child, group);
|
|
389
|
+
} else {
|
|
390
|
+
group.ensureNode(child.dom);
|
|
391
|
+
if (child.update !== noopUpdate)
|
|
392
|
+
update = child.update;
|
|
393
|
+
if (child.mount !== noopMount) {
|
|
394
|
+
mount = child.mount;
|
|
395
|
+
unmount = child.unmount;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (update !== noopUpdate) {
|
|
399
|
+
let context = currentConstructionContext();
|
|
400
|
+
update(context.currData);
|
|
401
|
+
updates.push(update);
|
|
402
|
+
}
|
|
403
|
+
if (mount !== noopMount) {
|
|
404
|
+
mounts.push(mount);
|
|
405
|
+
unmounts.push(unmount);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
return {
|
|
409
|
+
dom: e,
|
|
410
|
+
update: normalizeUpdates(updates),
|
|
411
|
+
mount: normalizeMount(mounts),
|
|
412
|
+
unmount: normalizeMount(unmounts)
|
|
413
|
+
};
|
|
414
|
+
};
|
|
415
|
+
const dynamicElement = dynamicElementNS(HTML);
|
|
416
|
+
const svgDynamicElement = dynamicElementNS(SVG);
|
|
417
|
+
const mathMLDynamicElement = dynamicElementNS(MathML);
|
|
418
|
+
function createBaseElement(ns, tagName, attributes, ref) {
|
|
419
|
+
let e = document.createElementNS(ns, tagName);
|
|
420
|
+
let updates = [];
|
|
421
|
+
let mounts = [];
|
|
422
|
+
let unmounts = [];
|
|
423
|
+
if (ref)
|
|
424
|
+
mkRef(ref, e, updates, mounts, unmounts);
|
|
425
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
426
|
+
if (key === STYLE && e instanceof HTMLElement) {
|
|
427
|
+
Object.entries(value).forEach(([styleKey, styleValue]) => {
|
|
428
|
+
setAttribute(
|
|
429
|
+
e.style,
|
|
430
|
+
styleKey,
|
|
431
|
+
styleValue,
|
|
432
|
+
updates
|
|
433
|
+
);
|
|
434
|
+
});
|
|
435
|
+
} else {
|
|
436
|
+
setAttribute(
|
|
437
|
+
e,
|
|
438
|
+
key,
|
|
439
|
+
value,
|
|
440
|
+
updates
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
return { e, updates, mounts, unmounts };
|
|
445
|
+
}
|
|
446
|
+
function normalizeUpdates(updates) {
|
|
447
|
+
if (updates.length === 1)
|
|
448
|
+
return updates[0];
|
|
449
|
+
else if (updates.length > 0) {
|
|
450
|
+
for (let i = updates.length - 1; i >= 0; i--) {
|
|
451
|
+
if (updates[i]._origUpdates)
|
|
452
|
+
updates.splice(i, 1, ...updates[i]._origUpdates);
|
|
453
|
+
}
|
|
454
|
+
let updateFunc2 = (newData) => {
|
|
455
|
+
updates.forEach((updateFn) => updateFn(newData));
|
|
456
|
+
};
|
|
457
|
+
updateFunc2._origUpdates = updates;
|
|
458
|
+
return updateFunc2;
|
|
459
|
+
} else {
|
|
460
|
+
return noopUpdate;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function normalizeMount(mounts) {
|
|
464
|
+
if (mounts.length === 1)
|
|
465
|
+
return mounts[0];
|
|
466
|
+
else if (mounts.length > 0) {
|
|
467
|
+
return () => {
|
|
468
|
+
mounts.forEach((updateFn) => updateFn());
|
|
469
|
+
};
|
|
470
|
+
} else {
|
|
471
|
+
return noopMount;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
class PrivateRefs {
|
|
475
|
+
constructor() {
|
|
476
|
+
__publicField(this, "elements", /* @__PURE__ */ new Set());
|
|
477
|
+
__publicField(this, "listeners", []);
|
|
478
|
+
}
|
|
479
|
+
addEventListener(type, listener, options) {
|
|
480
|
+
this.listeners.push({ type, listener, options });
|
|
481
|
+
this.elements.forEach((ref) => ref.addEventListener(type, listener, options));
|
|
482
|
+
}
|
|
483
|
+
addRef(ref) {
|
|
484
|
+
if (!this.elements.has(ref)) {
|
|
485
|
+
this.elements.add(ref);
|
|
486
|
+
this.listeners.forEach(
|
|
487
|
+
(listener) => ref.addEventListener(listener.type, listener.listener, listener.options)
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
removeRef(ref) {
|
|
492
|
+
this.elements.delete(ref);
|
|
493
|
+
this.listeners.forEach(
|
|
494
|
+
(listener) => ref.removeEventListener(listener.type, listener.listener, listener.options)
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
removeEventListener(type, listener, options) {
|
|
498
|
+
this.listeners = this.listeners.filter(
|
|
499
|
+
(item) => item.type !== type || item.listener !== listener
|
|
500
|
+
);
|
|
501
|
+
this.elements.forEach((ref) => ref.removeEventListener(type, listener, options));
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
class PrivateCollectionRefs extends PrivateRefs {
|
|
505
|
+
map(handler) {
|
|
506
|
+
return [...this.elements].map(
|
|
507
|
+
(ref) => handler(ref.getPublicAPI(), ref.viewState, ref.coordinate)
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
find(predicate) {
|
|
511
|
+
for (let ref of this.elements)
|
|
512
|
+
if (predicate(ref.viewState, ref.coordinate))
|
|
513
|
+
return ref.getPublicAPI();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
class HTMLElementCollectionRefImpl extends PrivateCollectionRefs {
|
|
517
|
+
mkManagedRef(currData, coordinate, eventWrapper) {
|
|
518
|
+
return new HTMLElementRefImpl(
|
|
519
|
+
currData,
|
|
520
|
+
coordinate,
|
|
521
|
+
eventWrapper,
|
|
522
|
+
this
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
getPublicAPI() {
|
|
526
|
+
return newHTMLElementPublicApiProxy(this);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
class HTMLElementRefsImpl extends PrivateRefs {
|
|
530
|
+
mkManagedRef(currData, coordinate, eventWrapper) {
|
|
531
|
+
return new HTMLElementRefImpl(
|
|
532
|
+
currData,
|
|
533
|
+
coordinate,
|
|
534
|
+
eventWrapper,
|
|
535
|
+
this
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
getPublicAPI() {
|
|
539
|
+
return newHTMLElementPublicApiProxy(this);
|
|
540
|
+
}
|
|
541
|
+
exec$(handler) {
|
|
542
|
+
return [...this.elements][0].exec$(handler);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
class ComponentRefsImpl extends PrivateRefs {
|
|
546
|
+
getInstance() {
|
|
547
|
+
return [...this.elements][0]?.getPublicAPI();
|
|
548
|
+
}
|
|
549
|
+
mkManagedRef(currData, coordinate, eventWrapper) {
|
|
550
|
+
return new ComponentRefImpl(
|
|
551
|
+
currData,
|
|
552
|
+
coordinate,
|
|
553
|
+
eventWrapper,
|
|
554
|
+
this
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
getPublicAPI() {
|
|
558
|
+
return newComponentPublicApiProxy(this);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
class ComponentCollectionRefImpl extends PrivateCollectionRefs {
|
|
562
|
+
mkManagedRef(currData, coordinate, eventWrapper) {
|
|
563
|
+
return new ComponentRefImpl(
|
|
564
|
+
currData,
|
|
565
|
+
coordinate,
|
|
566
|
+
eventWrapper,
|
|
567
|
+
this
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
getPublicAPI() {
|
|
571
|
+
return newComponentCollectionPublicApiProxy(this);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
class RefImpl {
|
|
575
|
+
constructor(viewState, coordinate, eventWrapper, parentCollection) {
|
|
576
|
+
__publicField(this, "listeners", []);
|
|
577
|
+
__publicField(this, "element");
|
|
578
|
+
__publicField(this, "mount", () => {
|
|
579
|
+
this.parentCollection?.addRef(this);
|
|
580
|
+
});
|
|
581
|
+
__publicField(this, "unmount", () => {
|
|
582
|
+
this.parentCollection?.removeRef(this);
|
|
583
|
+
});
|
|
584
|
+
__publicField(this, "update", (newData) => {
|
|
585
|
+
this.viewState = newData;
|
|
586
|
+
});
|
|
587
|
+
this.viewState = viewState;
|
|
588
|
+
this.coordinate = coordinate;
|
|
589
|
+
this.eventWrapper = eventWrapper;
|
|
590
|
+
this.parentCollection = parentCollection;
|
|
591
|
+
this.viewState = viewState;
|
|
592
|
+
}
|
|
593
|
+
set(referenced) {
|
|
594
|
+
this.element = referenced;
|
|
595
|
+
this.listeners.forEach(
|
|
596
|
+
({ type, wrappedHandler, options }) => this.element.addEventListener(type, wrappedHandler, options)
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
addEventListener(type, listener, options) {
|
|
600
|
+
let wrappedHandler = (event) => {
|
|
601
|
+
return this.eventWrapper(listener, this.formatEvent(event));
|
|
602
|
+
};
|
|
603
|
+
this.element?.addEventListener(type, wrappedHandler, options);
|
|
604
|
+
this.listeners.push({ type, listener, wrappedHandler, options });
|
|
605
|
+
}
|
|
606
|
+
removeEventListener(type, listener, options) {
|
|
607
|
+
let index = this.listeners.findIndex(
|
|
608
|
+
(item) => item.type === type && item.listener === listener
|
|
609
|
+
);
|
|
610
|
+
if (index > -1) {
|
|
611
|
+
let item = this.listeners[index];
|
|
612
|
+
this.listeners.splice(index, 1);
|
|
613
|
+
this.element?.removeEventListener(type, item.wrappedHandler, options);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
class HTMLElementRefImpl extends RefImpl {
|
|
618
|
+
formatEvent(event) {
|
|
619
|
+
return { event, viewState: this.viewState, coordinate: this.coordinate };
|
|
620
|
+
}
|
|
621
|
+
getPublicAPI() {
|
|
622
|
+
return newHTMLElementPublicApiProxy(this);
|
|
623
|
+
}
|
|
624
|
+
exec$(handler) {
|
|
625
|
+
return new Promise((resolve, reject) => {
|
|
626
|
+
try {
|
|
627
|
+
resolve(handler(this.element, this.viewState));
|
|
628
|
+
} catch (e) {
|
|
629
|
+
reject(e);
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
class ComponentRefImpl extends RefImpl {
|
|
635
|
+
getFromComponent(prop) {
|
|
636
|
+
return this.element[prop];
|
|
637
|
+
}
|
|
638
|
+
formatEvent(event) {
|
|
639
|
+
return { ...event, viewState: this.viewState, coordinate: this.coordinate };
|
|
640
|
+
}
|
|
641
|
+
getPublicAPI() {
|
|
642
|
+
return newComponentInCollectionPublicApiProxy(
|
|
643
|
+
this
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const EVENT_TRAP = (target, prop) => {
|
|
648
|
+
if (typeof prop === "string") {
|
|
649
|
+
if (prop.indexOf("on") === 0) {
|
|
650
|
+
let eventName = prop.substring(2);
|
|
651
|
+
return (handler) => {
|
|
652
|
+
target.addEventListener(eventName, handler);
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
if (prop === "addEventListener")
|
|
656
|
+
return target.addEventListener.bind(target);
|
|
657
|
+
}
|
|
658
|
+
return false;
|
|
659
|
+
};
|
|
660
|
+
const EVENT$_TRAP = (target, prop) => {
|
|
661
|
+
if (typeof prop === "string") {
|
|
662
|
+
if (prop.indexOf("on") === 0 && prop.at(-1) === "$") {
|
|
663
|
+
let eventName = prop.slice(2, -1);
|
|
664
|
+
return (nativeHandler) => {
|
|
665
|
+
let regularHandler;
|
|
666
|
+
const handler = ({ event, viewState, coordinate }) => {
|
|
667
|
+
const returnedEvent = nativeHandler({ event, viewState, coordinate });
|
|
668
|
+
if (regularHandler)
|
|
669
|
+
regularHandler({ event: returnedEvent, viewState, coordinate });
|
|
670
|
+
};
|
|
671
|
+
target.addEventListener(eventName, handler);
|
|
672
|
+
return {
|
|
673
|
+
then: (handler2) => {
|
|
674
|
+
regularHandler = handler2;
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return false;
|
|
681
|
+
};
|
|
682
|
+
const DELEGATE_REF_TO_COMP_TRAP = (target, prop) => {
|
|
683
|
+
return target.getFromComponent(prop);
|
|
684
|
+
};
|
|
685
|
+
const DELEGATE_REFS_TO_COMP_TRAP = (target, prop) => {
|
|
686
|
+
const instance = target.getInstance();
|
|
687
|
+
return instance ? instance[prop] : void 0;
|
|
688
|
+
};
|
|
689
|
+
const GetTrapProxy = (getTraps) => {
|
|
690
|
+
return {
|
|
691
|
+
get: function(target, prop, receiver) {
|
|
692
|
+
let result;
|
|
693
|
+
for (let getTrap of getTraps) {
|
|
694
|
+
result = getTrap(target, prop, receiver);
|
|
695
|
+
if (result)
|
|
696
|
+
return result;
|
|
697
|
+
}
|
|
698
|
+
return target[prop];
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
};
|
|
702
|
+
const HTMLElementRefProxy = GetTrapProxy([EVENT$_TRAP, EVENT_TRAP]);
|
|
703
|
+
function newHTMLElementPublicApiProxy(ref) {
|
|
704
|
+
return new Proxy(ref, HTMLElementRefProxy);
|
|
705
|
+
}
|
|
706
|
+
const ComponentRefProxy = GetTrapProxy([EVENT_TRAP, DELEGATE_REFS_TO_COMP_TRAP]);
|
|
707
|
+
function newComponentPublicApiProxy(ref) {
|
|
708
|
+
return new Proxy(ref, ComponentRefProxy);
|
|
709
|
+
}
|
|
710
|
+
const ComponentInCollectionRefProxy = GetTrapProxy([EVENT_TRAP, DELEGATE_REF_TO_COMP_TRAP]);
|
|
711
|
+
function newComponentInCollectionPublicApiProxy(ref) {
|
|
712
|
+
return new Proxy(ref, ComponentInCollectionRefProxy);
|
|
713
|
+
}
|
|
714
|
+
const ComponentCollectionRefProxy = GetTrapProxy([EVENT_TRAP]);
|
|
715
|
+
function newComponentCollectionPublicApiProxy(ref) {
|
|
716
|
+
return new Proxy(ref, ComponentCollectionRefProxy);
|
|
717
|
+
}
|
|
718
|
+
function defaultEventWrapper(orig, event) {
|
|
719
|
+
return orig(event);
|
|
720
|
+
}
|
|
721
|
+
var ManagedRefType = /* @__PURE__ */ ((ManagedRefType2) => {
|
|
722
|
+
ManagedRefType2[ManagedRefType2["element"] = 0] = "element";
|
|
723
|
+
ManagedRefType2[ManagedRefType2["elementCollection"] = 1] = "elementCollection";
|
|
724
|
+
ManagedRefType2[ManagedRefType2["component"] = 2] = "component";
|
|
725
|
+
ManagedRefType2[ManagedRefType2["componentCollection"] = 3] = "componentCollection";
|
|
726
|
+
return ManagedRefType2;
|
|
727
|
+
})(ManagedRefType || {});
|
|
728
|
+
class BaseReferencesManager {
|
|
729
|
+
constructor(eventWrapper = defaultEventWrapper) {
|
|
730
|
+
__publicField(this, "refs", {});
|
|
731
|
+
__publicField(this, "refsPublicAPI");
|
|
732
|
+
this.eventWrapper = eventWrapper;
|
|
733
|
+
}
|
|
734
|
+
mkRefsOfType(refType, refNames) {
|
|
735
|
+
return refNames.map((refName) => {
|
|
736
|
+
const managedRef = this.mkManagedRef(refType, refName);
|
|
737
|
+
this.refs[refName] = managedRef;
|
|
738
|
+
return () => {
|
|
739
|
+
let { currData, coordinate } = this.currentContext();
|
|
740
|
+
return managedRef.mkManagedRef(currData, coordinate(refName), this.eventWrapper);
|
|
741
|
+
};
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
mkRefs(elem, elemCollection, comp, compCollection, childRefManagers = {}) {
|
|
745
|
+
this.refs = childRefManagers;
|
|
746
|
+
return [
|
|
747
|
+
...this.mkRefsOfType(0, elem),
|
|
748
|
+
...this.mkRefsOfType(1, elemCollection),
|
|
749
|
+
...this.mkRefsOfType(2, comp),
|
|
750
|
+
...this.mkRefsOfType(3, compCollection)
|
|
751
|
+
];
|
|
752
|
+
}
|
|
753
|
+
mkRefsPublicAPI() {
|
|
754
|
+
this.refsPublicAPI = Object.keys(this.refs).reduce((publicRefAPIs, key) => {
|
|
755
|
+
publicRefAPIs[key] = this.refs[key].getPublicAPI();
|
|
756
|
+
return publicRefAPIs;
|
|
757
|
+
}, {});
|
|
758
|
+
}
|
|
759
|
+
get(refName) {
|
|
760
|
+
return this.refs[refName];
|
|
761
|
+
}
|
|
762
|
+
getPublicAPI() {
|
|
763
|
+
if (!this.refsPublicAPI)
|
|
764
|
+
this.mkRefsPublicAPI();
|
|
765
|
+
return this.refsPublicAPI;
|
|
766
|
+
}
|
|
767
|
+
applyToElement(element2) {
|
|
768
|
+
return { ...element2, refs: this.getPublicAPI() };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
class ReferencesManager extends BaseReferencesManager {
|
|
772
|
+
mkManagedRef(refType) {
|
|
773
|
+
switch (refType) {
|
|
774
|
+
case 0:
|
|
775
|
+
return new HTMLElementRefsImpl();
|
|
776
|
+
case 1:
|
|
777
|
+
return new HTMLElementCollectionRefImpl();
|
|
778
|
+
case 2:
|
|
779
|
+
return new ComponentRefsImpl();
|
|
780
|
+
case 3:
|
|
781
|
+
return new ComponentCollectionRefImpl();
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
currentContext() {
|
|
785
|
+
const { currData, coordinate } = currentConstructionContext();
|
|
786
|
+
return { currData, coordinate };
|
|
787
|
+
}
|
|
788
|
+
static for(options, elem, elemCollection, comp, compCollection, childRefManagers) {
|
|
789
|
+
const refManager = new ReferencesManager(options?.eventWrapper);
|
|
790
|
+
return [
|
|
791
|
+
refManager,
|
|
792
|
+
refManager.mkRefs(elem, elemCollection, comp, compCollection, childRefManagers)
|
|
793
|
+
];
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
export {
|
|
797
|
+
BaseReferencesManager,
|
|
798
|
+
ComponentCollectionRefImpl,
|
|
799
|
+
ComponentRefImpl,
|
|
800
|
+
ComponentRefsImpl,
|
|
801
|
+
ConstructContext,
|
|
802
|
+
EVENT_TRAP,
|
|
803
|
+
GetTrapProxy,
|
|
804
|
+
ManagedRefType,
|
|
805
|
+
PrivateRefs,
|
|
806
|
+
ReferencesManager,
|
|
807
|
+
booleanAttribute,
|
|
808
|
+
childComp,
|
|
809
|
+
conditional,
|
|
810
|
+
createJayContext,
|
|
811
|
+
currentConstructionContext,
|
|
812
|
+
defaultEventWrapper,
|
|
813
|
+
dynamicAttribute,
|
|
814
|
+
dynamicElement,
|
|
815
|
+
dynamicElementNS,
|
|
816
|
+
dynamicProperty,
|
|
817
|
+
dynamicText,
|
|
818
|
+
element,
|
|
819
|
+
findContext,
|
|
820
|
+
forEach,
|
|
821
|
+
isCondition,
|
|
822
|
+
isForEach,
|
|
823
|
+
mathMLDynamicElement,
|
|
824
|
+
mathMLElement,
|
|
825
|
+
mkUpdateCollection,
|
|
826
|
+
noopMount,
|
|
827
|
+
noopUpdate,
|
|
828
|
+
normalizeMount,
|
|
829
|
+
normalizeUpdates,
|
|
830
|
+
restoreContext,
|
|
831
|
+
saveContext,
|
|
832
|
+
svgDynamicElement,
|
|
833
|
+
svgElement,
|
|
834
|
+
useContext,
|
|
835
|
+
withContext
|
|
836
|
+
};
|